Nested template

This is a discussion on Nested template within the C++ Programming forums, part of the General Programming Boards category; I have been trying to reinforce my knowledge of templates lately, and was unable to get the following to compile.
...

I've only had to use that a couple times so far.
I just don't really understand why WE are required to put the typename keyword there in the first place? Surely the compiler could figure this out for itself??

I just don't really understand why WE are required to put the typename keyword there in the first place? Surely the compiler could figure this out for itself??

From what I understand, the reason is that the compiler does not have enough information to determine if the name is a type name or a member name. Depending on the template argument, it could be interpreted one way or the other.

From what I understand, the reason is that the compiler does not have enough information to determine if the name is a type name or a member name. Depending on the template argument, it could be interpreted one way or the other.

It seems to have plenty of information to me:

Code:

std::list< A< T > >::const_iterator i;

1. Replace T with the type used with this template.
2. Now it knows what types are stored in std::list.
3. const_iterator is a typedef in std::list, so it knows what type to assign to i.

It might just be more of a silly requirement. All default values must be const (even though you could theoretically assign them), and all types within a namespace or class requires "typename" even though the compiler knows all the information.
Might just be a thing in the standard that makes no sense!

From what I understand the problem is that at the time of parsing of the template, T is not known. The compiler cannot replace T with any type since the template has not been instantiated.

I am not sure if this is a correct counterexample, but suppose there is a specialisation of std::list such that, for that particular A<T>, const_iterator is a member variable, not a type. Now, If T happens to be any other type, const_iterator would be a typename. But if T is of that type such that A<T> has this unusual specialisation, const_iterator would be a member variable.

This would not happen in practice since we are dealing with a standard container (and my knowledge of templates and C++ in general is such that I am not sure if it is even legal/possible), so perhaps Stephen Dewhurst's example from C++ Common Knowledge Item #49 is clearer:

Consider the following fragment:

Code:

template <typename T>
void aFuncTemplate( T &arg ) {
...T::ElemT...

When the compiler encounters the qualified name T::ElemT, what does it know? From the template parameter list it knows that T is a type name of some sort. It can also determine that T is a class name because we've employed the scope operator (: to access a nested name of T. But that's all the compiler knows, because there is no information available about the content of T. For instance, we could call aFuncTemplate with a PtrList, in which case T::ElemT would be a type name.

In this case, T::ElemT is the name of a data member - a nontype name. What's a compiler to do? The standard tossed a coin, and in cases where it can't determine the type of a nested name, the compiler will assume the nested name is a nontype name.

I think the only point your argument fails at is that the compiler knows the type of T.
Why? Because templates are only compiled if they invoked somewhere. And if they are, the compiler will know the type T or it will complain.
At least this is my understanding of Microsoft's compilers.

I think the only point your argument fails at is that the compiler knows the type of T.
Why? Because templates are only compiled if they invoked somewhere.

I believe that is false. Templates are compiled whether or not they are instantiated, but if they are not instantiated, the compiler does not generate object code for the template instantiation. If not, templates with syntax errors should be ignored by the compiler since there is no reason to care about code that is never used.

Templates that are never used used are never compiled, or at least, as you mention, ignored.
You can create a lot of compile errors in a template but never call it and the compiler will not complain.
Therefore, the compiler can ignore template declarations when it does not know the type of T, and compile it only when it knows the type of T, and therefore the argument that the compiler does not know T fails.

On Microsoft compilers, this is not the case. Templates that are never used used are never compiled.
You can create a lot of compile errors in a template but never call it and the compiler will not complain.

hmm... that is true, at least I can verify it with MSVC8.

I think we need to call Prelude in on this. Dewhurst might be wrong, but considering that he has participated in the writing of C++ compilers on top of his experience, it seems unlikely.

The compiler will also parse the function header, though not the body.

That makes sense, the compiler at least has to know what the template looks like in order to identify if it is or is not used. Like g++ 3.4.2, the Comeau online compiler also reports a compile error if the function template body has syntax errors, but this behaviour could be compiler specific as I have not found the relevant part of the standard concerning this.

By the way, note that MSVC2005 is MSVC8.

Reading the error message from the MinGW port of g++ 3.4.2 more closely, I see:

test.cpp:12: error: dependent-name ` T::meta' is parsed as a non-type, but instantiation yields a type
test.cpp:12: note: say `typename T::meta' if a type is meant

Additionally, there are various other different contexts from the above where the compiler needs to know whether it is dealing with a declaration or an expression. In the case of templates, similar parsing issues comes up. In particular, if T is a template parameter as it is in xyz above, then what does it mean for it to use say T::x? In other words, if the compiler does not know what T is until you instantiate it, how could it know what x is, since it is based upon T?

This reiterates Dewhurst's claim that the typename keyword "allows the compiler to parse the template correctly".

On the other hand, it seems from the g++ example that the compiler can parse the template "correctly", perhaps by first parsing the name as a nontype name, then parsing the template again but this time interpreting the name as a type name. If on the second try there is no syntax error because "instantiation yields a type", all is well. If so, my guess is that the real reasons for the standards committee decision to introduce typename are to make life a little easier for compiler writers, and to allow the compilation process to be a little faster, by forcing C++ programmers to make it clear that the type name is indeed a type name.