9

Writing a templated function, I declared:

template <typename T>
T invertible(T const& container, T::size_type startIndex, T::size_type endIndex);

Compiling with g++ 4.0.1 I got the error:

error: 'T::size_type' is not a type
chollida
  • 7,834
  • 11
  • 55
  • 85
Walter Nissen
  • 16,451
  • 4
  • 26
  • 27

4 Answers4

31

You need to add typename.

I.e.

template <typename T>
T invertible(T const& container, typename T::size_type startIndex, typename T::size_type endIndex);

Without having any information on your type T, the compiler needs to know that T::size_type designates a type.

From the standard, section 14.6.2:

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

Tobias
  • 6,388
  • 4
  • 39
  • 64
8

As you found out T::size_type needs to be prefixed with typename. Why?

From "C++ Templates: The Complete Guide"

The language definition resolves this problem by specifying that in general a dependent qualified name does not denote a type unless that name is prefixed with the keyword typename.

... The typename prefix to a name is required when the name

  1. Appears in a template
  2. Is qualified
  3. Is not used as a list of base class specifications or in a list of member initializations introducing a constructor definition
  4. Is dependent on a template parameter

Furthermore the typename prefix is not allowed unless at least the first three previous conditions hold.

Community
  • 1
  • 1
maccullt
  • 2,769
  • 1
  • 18
  • 15
  • I've now read that passage, thanks (those reading along at home can see the detailed explanation on page 130). I still don't see why "typename" is required in an argument declaration, as that has to be a type, but maybe that's just for consistency with statements in general. – Walter Nissen Aug 19 '09 at 19:44
  • 1
    @wnissen: Typically such requirements exist to keep parser builders happy. Part of the problem is that you apparently already know it's an argument declaration. Due to the "most vexing parse" problem, the parser typically has to deduce that from the tokens between (). Now, if you say the interpretation of the tokens between () should depend on knowing it's an argument declaration, then you've introduced a cyclic parsing problem. – MSalters Aug 20 '09 at 07:52
3

Because during parsing the template declaration, T is not known. So the compiler doesn't know if T::size_type exists at all. It may refer to a static variable, for example. When you later use the template, T is of course known, but the error happens earlier. And please use something less ancient than gcc 4.0.1 ;-)

Edit: If you compile it with -fpermissive, the compiler probably chews your code, but he will give a warning.

Gunther Piez
  • 29,760
  • 6
  • 71
  • 103
0

It turned out I needed to specify that T::size_type was a typename. Why is that?

template <typename T>
T invertible(T const& container, typename T::size_type startIndex, typename T::size_type endIndex);
Walter Nissen
  • 16,451
  • 4
  • 26
  • 27
  • To disambiguate between a possible instance name and a possible type name. For more info read the book C++ Templates; The Complete Guide - info at http://www.josuttis.com/tmplbook/tmplbook.html –  Aug 19 '09 at 17:24
  • 1
    that should be a separate question. (Although it has been asked before. Search around a bit) – jalf Aug 19 '09 at 17:38