[cfe-dev] Is clang name lookup too restrictive for dependent base classes?

Enea Zaffanella zaffanella at cs.unipr.it
Fri Feb 12 02:09:50 PST 2010

John McCall wrote:
> On Feb 11, 2010, at 3:03 AM, Enea Zaffanella wrote:


>> I checked clang source for a reference to the standard and I found the
>> following (Sema/SemaTemplate.cpp):
>>     // C++0x [temp.expl.spec]p17:
>>     //   A member or a member template may be nested within many
>>     //   enclosing class templates. In an explicit specialization for
>>     //   such a member, the member declaration shall be preceded by a
>>     //   template<> for each enclosing class template that is
>>     //   explicitly specialized.
>>     // We interpret this as forbidding typedefs of template
>>     // specializations in the scope specifiers of out-of-line decls.
>> Both g++ and Comeau will refuse the example above if the "template <>"
>> was omitted ... but I don't see a strong relation between this behavior
>> and the presence of a typedef name.
> Without the template<>, the compiler doesn't realize you're declaring
> an explicit specialization.  But the design of template parameters in the
> language (and Doug can speak more to this) is that parameter clauses
> are matched up with argument clauses in the declared name — that is,
> you match angle brackets to angle brackets.  Using a typedef screws
> up this matching because it means that parts of the name without
> angle-brackets are supposed to matched against.
> That's why the language requires it.  From a user-design point of view,
> gcc's permissiveness on this goes a long way towards explaining why
> nobody but language geeks understands how this matching is
> supposed to work.
> John.

Unfortunately, I made an error when extracting the testcase from GMP.

The complete testcase showing the problem (that could be found in 
gmpxx.h, both versions 4.3.2 and 5.0.1) is as follows:
// Declaration of class template (__gmp_expr).
template <typename T>
struct S;

// Definition of explicit specialization (__gmp_expr<mpz_t, mpz_t>).
template <>
struct S<int> {
   S foo(S);

// Typedef declaration for explicit specialization (mpz_class).
typedef S<int> SInt;

// Out-of-line definition of member of explicit specialization
// (e.g., mpz_class::operator+=).
SInt SInt::foo(SInt x)
   return x;

The big difference wrt previous testcase is that the class template 
specialization is *defined* before introducing its typedef alias.

Here, clang complains the same way as above:
# clang++ -fsyntax-only test.cc
test.cc:15:1: error: cannot use typedef 'SInt' (aka 'S<int>') in scope 
       for out-of-line declaration
SInt SInt::foo(SInt x)
1 diagnostic generated.

This code is accepted by g++ and Comeau and, as far as I can tell, it is 
standard compliant. In fact, since we now have the explicit 
specialization, C++98 14.7.3 p5 becomes relevant.
Quoting the end of that paragraph:

   "Definitions of members of an explicitly specialized class
    are defined in the same manner as members of normal classes,
    and not using the explicit specialization syntax."

Since these definitions do not use the "template <>" prefixes, there is 
no way (or need) to perform the matching you were mentioning above, 
hence there is no need to forbid the use of typedef names.

Enea Zaffanella.

More information about the cfe-dev mailing list