Bug 37350 - Specialized template base class name not accepted
Summary: Specialized template base class name not accepted
Status: RESOLVED DUPLICATE of bug 189
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2008-09-03 14:06 UTC by Ian Lance Taylor
Modified: 2009-12-23 23:31 UTC (History)
11 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ian Lance Taylor 2008-09-03 14:06:13 UTC
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.
Comment 1 Richard Biener 2008-09-03 14:50:36 UTC
I don't read from the sentence that this applies to base class names, it
says "the name of the template" only.
Comment 2 Richard Biener 2008-09-03 14:51:49 UTC
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).
Comment 3 Ian Lance Taylor 2008-09-04 03:38:18 UTC
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.
Comment 4 Andrew Pinski 2008-09-04 03:59:22 UTC
Looks like this is a dup of bug 9937.
Comment 5 Jonathan Wakely 2009-12-23 23:31:12 UTC

*** This bug has been marked as a duplicate of 189 ***