tags:

views:

396

answers:

4

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
+26  A: 

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
A: 

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
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
anon
that should be a separate question. (Although it has been asked before. Search around a bit)
jalf
+3  A: 

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.

drhirsch
gcc 4.0.1 is the most current one – on the mac :)
Tobias
If true, yet another reason for not using a mac. The latest production quality g++ is 4.4.0
anon
Actually gcc 4.4.1.
drhirsch
I don't suppose you'll be cheered to learn that the September release of Mac 10.6 will use gcc 4.2.1 as the default?
Walter Nissen
+2  A: 

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.

maccullt
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
@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