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: