Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a class template explicit specialization also declare something else?

It would be nice if this code were invalid. But it's conceptually sound, and GCC accepts it although Comeau doesn't:

template< typename > struct t;

template<> struct t< int > {} r; // Bad declarator! Don't pee on the carpet!

(Edit: the above compiles but r seems no to be declared into any scope, so it is essentially ignored.)

Explicit specializations populate a kind of nether region between templates and classes. The type declared by an explicit specialization is complete once it is defined. From the compiler's standpoint, it is not a template. If it were a parameterized template, declaring an object would be impossible. Consider §14/3:

In a template-declaration, explicit specialization, or explicit instantiation the init-declarator-list in the dec- laration shall contain at most one declarator. When such a declaration is used to declare a class template, no declarator is permitted.

What does "is used to declare a class template" mean? Clearly a primary template declares a class template. And a partial specialization does too, according to §14.5.5/1 (FDIS numbers):

A template declaration in which the class template name is a simple-template-id is a partial specialization of the class template named in the simple-template-id.

When it comes to explicit specializations, though, the Standard speaks in terms of a declaration preceded by the token sequence template<>. It looks like a template and it names a template-name, but it doesn't seem to declare a template.

The really bizarre thing is that §14/3 restricts the number of declarators to "at most one." A function template declaration, explicit specialization or instantiation must have exactly one declarator. Any declaration involving a class template must have exactly zero… except explicit specialization, which seems to fall through the cracks. Faithfully, GCC refuses to allow

template<> struct t< int > {} r, s; // Offer valid one per specialization.

I tend to agree with GCC's interpretation, nonsense as it may be. Unfortunately, it may be inhibiting its ability to detect missing semicolons. Please, let the number of allowed declarators be exactly zero!

like image 815
Potatoswatter Avatar asked Jun 10 '11 09:06

Potatoswatter


Video Answer


1 Answers

Several points: first, explicit specializations are not in a nether region between templates and classes; an explicit specialization is a class, period. The only relation is has with templates (except for the funny name) is that it will be used instead of a template instantiation if the template is to be instantiated on the specialization type.

Secondly, if there is a problem with the paragraph in §14/3 that you cite, it is that it includes explicit instantiation; an explicit instantiation is a class definition, and if

struct S {} s, *p;

is legal,

template<> struct T<int> {} s, *p;

should be too. (I would argue against allowing either, but that train has already left the station, and since C allows the first, we're stuck with it.)

Otherwise, the statement in §14/3 is a bit irrelevant. A function template must have exactly one declarator, and a class template exactly zero; there's no need to try to englobe them both in some "at most one" gobbledygook. (If I were designing the language from scratch, I'd not allow any declarator in a declaration which defined a class or enum type. But again, it's too late for that.)

And I agree that it's a bother:

template<> struct T<int> {};    //  Requires a ';'
template<> void f<int>() {}     //  ';' forbidden

(At least C++11 will allow a semicolon after the function definition.)

like image 99
James Kanze Avatar answered Sep 22 '22 21:09

James Kanze