C++98 [temp.local] says "Within the scope of a class template specialization or partial specialization, when the name of the template is neither qualified nor followed by <, it is equivalent to the name of the template followed by the template-arguments enclosed in <>." That does not work when a template specialization is used as a base class. In that case g++ does not accept the unqualified base class name as a type. This test case: template <class T> struct base {}; struct derived : base<int> { typedef base b; base* p; }; gives these errors: foo.cc:5: error: invalid use of template-name ‘base’ without an argument list foo.cc:6: error: ISO C++ forbids declaration of ‘base’ with no type foo.cc:6: error: expected ‘;’ before ‘*’ token I believe this is an incorrect rejection of valid C++ code. At least, I can't find anything in the C++ standard which says that this code is invalid.
I don't read from the sentence that this applies to base class names, it says "the name of the template" only.
EDG rejects it with t.C(5): error: argument list for class template "base" is missing typedef base b; ^ but accepts it if you use derived instead of base (like gcc does).
Here is further argument from a programmer here. Any language lawyers want to comment? 14.6.1 Locally declared names [temp.local] 1. Like normal (non-template) classes, class templates have an injected-class-name (clause 9). The injected-class-name can be used with or without a template-argument-list. When it is used without a template-argument-list, it is equivalent to the injected-class-name followed by the template-parameters of the class template enclosed in <>. When it is used with a template-argument-list, it refers to the specified class template specialization, which could be the current specialization or another specialization. It makes this code valid: template <class T> struct base { typedef base b; }; And now according to this: 9 Classes [class] 2 A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name. For purposes of access checking, the injected-class-name is treated as if it were a public member name. A class-specifier is commonly referred to as a class definition. A class is considered defined after the closing brace of its class-specifier has been seen even though its member functions are in general not yet defined. injected-class-name is public, therefore it is accessible in derived class. It makes the example valid.
Looks like this is a dup of bug 9937.
*** This bug has been marked as a duplicate of 189 ***