"? When I try to compile this with Clang template str...">

Why does this code give the error, "template specialization requires" template <> "?

When I try to compile this with Clang

 template<class T> struct Field { char const *name; Field(char const *name) : name(name) { } }; template<class Derived> class CRTP { static Field<Derived> const _field; }; class Class : public CRTP<Class> { }; Field<Class> const CRTP<Class>::_field("blah"); int main() { } 

I get

 error: template specialization requires 'template<>' Field<Class> const CRTP<Class>::_field("blah"); ~~~~~~~~~~~ ^ 

I don’t understand the mistake at all. What is wrong with my _field definition and how to fix it?

(Note that _field arguments _field not necessarily the same for all subclasses.)

+5
source share
3 answers

In order for the compiler to identify this as a template specialization (for example, to check the syntax), you need the template keyword:

 template<> Field<Class> const CRTP<Class>::_field("blah"); 

Its brackets are empty, since all template parameters are specialized, but you cannot just leave it.

+11
source

The error says exactly what is missing. template<> missing before this line.

 template<> Field<Class> const CRTP<Class>::_field("blah"); 

Note, however, that your typing of Field<Class> , if unique, can be used to build all instances of Field<Class> with a given string.

 template<typename T> struct field_trait; template<class T> struct Field { char const *name; Field() : name(field_trait<T>::get_name()) {} }; template<class Derived> class CRTP { static Field<Derived> const _field; }; template<class Derived> class CRTP<Derived>::_field; class Class; template<> struct field_traits<Class> { static const char* get_name() { return "blah"; } }; class Class : public CRTP<Class> { }; int main() { } 

which means that every instance of Field<Class> always has the name "blah" .

One question that I have is whether you really need to store for the mentioned Field<Class> , in order to actually have a pointer to a string, and if so, then this should be unique, and if so, then you need to be "naked ",? Since figuring out where the static instance exists is somewhat annoying.

Together with field_traits above:

 template<class Derived> class CRTP { static Field<Derived>& field() const { static Field<Derived> _field( field_traits<Derived>::get_name()); return _field; }; 

this translates the β€œwhere _field is stored” problem into a problem with compilers. And it is initialized with the contents of field_traits<T>::get_name() .

+2
source

A static data member must have both a declaration and a definition. If it were a simple class, it would look like this:

 // header: class C { static int i; }; // source: int C::i = 3; 

Templates are usually not specified in the source files, so the code will look something like this:

 // header: template <class T> class C { static int i; }; template <class T> int C<T>::i = 3; 

In your code, you do not have a static data member definition. It is good if you do not use it. But the code that the compiler complains defines a static data member for CRTP<Class> ; that specialization (because it does not apply to all CRTP instances, only this one), and the compiler says that you should tell it that this is specialization. Do as you were told:

 template <> Field<Class> const CRTP<Class>::_field("blah"); 

or, to write a non-specialized version of a template, use the usual template syntax:

 template <class T> Field<T> const CRTP<T>::_field("blah"); 
+2
source

All Articles