[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

g++: Full VS Partial Specialization of Nested Templates



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

- --- Problem ---

struct outer0 {
  template<typename inner_var>
  struct inner { };

  template<>
  struct inner<void> { };
};

Gives "error: invalid explicit specialization before '>' token" message when 
you attempt to compile it (gcc 3.4) or "error: explicit specialization in 
non-namespace scope `struct outer0<outer_var>'" (gcc 3.4).

struct outer1 {
  template<typename inner_var0,typename inner_var1=void>
  struct inner { };

  template<typename inner_var1>
  struct inner<void,inner_var1> { };
};

Compiles fine.  It appears that partial, but not full, specialization is 
allowed inside of nested templates.  This seems to be a bit strange (i.e. 
inconsistent).

- --- Broken Hack of a Solution ---

template<>
struct outer0::inner<void> { };

This, however, does not work if the outer class is itself a template (which is 
what I really need).

template<typename outer_var>
struct outer {
  template<typename inner_var>
  struct inner { };
};

template<typename outer_var>
template<>
struct outer<outer_var>::inner<void> { };

Gives "error: enclosing class templates are not explicitly specialized" (gcc 
3.3) or "error: invalid explicit specialization before '>' token" (gcc 3.4).

- --- Background ---

Doing a google search on the non-namespace error message pulls a pretty old 
gcc maillist discusion (egcs era -- 1998).  It seems things where implemented 
this way because due to a (possibly mistaken) interpretation of the specs:

>    [temp.expl.spec]
>
>     An explicit specialization shall be declared in the namespace of
>     which the template is a member, or, for member templates, in the
>     namespace of which the enclosing class or enclosing class
>     template is a member.  An explicit specialization of a member
>     function, member class or static data member of a class template
>     shall be declared in the namespace of which the class template
>     is a member.

But, as someone else at that time pointed out:

>     It's still not clear that the above text applies to the case mentioned.
>     "In the namespace of which the enclosing class is a member" is
>     satisified both outside and inside the class.  When it means to say "not
>     in a class or in a block", it says "at namespace scope" or sometimes "in
>     namespace scope"; these are changed from "at global scope" which is what
>     it said before we had namespaces.  "In the namespace of" does not imply
>     "only at namespace scope".

The coding solution of "do an explicit instantiation at namespace scope" was 
suggest to the original poster.  It was then noted that this doesn't work for 
nested templates (the problem I'm having).

Finally, Mark Mitchel (who implemented the code that enforced the former 
interpretation) noted that the wording for the part of the standard that 
disallows full specialization of nested templates at namespace scope (unless 
the the outer templates are fully specialized as well) added credence to the 
former interpretation (that it should be allowed inside of classes):

>     In an explicit specialization declaration for a member of a class
>     template or a member template that appears in namespace scope, the
>     member template and some of its enclosing class templates may remain
>     unspecialized, except that the declaration shall not explicitly
>     specialize a class member template if its enclosing class templates 
>     are not explicitly specialized as well.

Specifically, he noted, that the above does not disallow specializations that 
are not at namespace scope (i.e. the difference pointed out above between "in 
the namespace of" and "at [or in] namespace scope").  He concluded with, 
"Perhaps I had better get that code out of CVS, and reenable it".

- --- Comments ---

I just checked our Beowulf clusters to see what other compilers are now doing:

- - Digital (cxx 6.5.9.31) -- no
- - Intel (icc 8.0)  -- yes
- - Microsoft's (VC ??) -- apparently (from googling)

Personally, I think gcc should allow full specialization inside a class or 
block as:

0- There is good reason to believe it is the standard.
1- Other vendors's compilers, with the exception of Digital's, allow it.
2- The syntax is much cleaner (especially for large expressions).
3- Allowing partial specialization, but not full, seems inconsistent.
4- The "do the very verbose instantiation at namespace scope" solution does 
not work for nested templates.
5- Mark Mitchell (who implemented this limitation), appeared to be in 
agreement about un-implementing it (I have no idea why he did not -- possibly 
he just never got around to it?).

- -T

PS:  Please CC me in responses as I don't subscribe to this list...

- -- 
 Tyson Whitehead  (-twhitehe at uwo.ca -- WSC-)
 Computer Engineer                        Dept. of Applied Mathematics,
 Graduate Student- Applied Mathematics    University of Western Ontario,
 GnuPG Key ID# 0x8A2AB5D8                 London, Ontario, Canada
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFBNjCoRXbLmIoqtdgRAuHEAJ9zV9k3Jnt0wtmeJzswjbWB1wKhqgCgpoSA
jwCigOAK1AZTk7Qu0GXiy8k=
=kvzT
-----END PGP SIGNATURE-----



Reply to: