Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 error at all. What is wrong with my definition of _field and how do I fix it?

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

like image 411
user541686 Avatar asked Feb 21 '26 04:02

user541686


2 Answers

For the compiler to identify this as a template specialization (e.g. to be able to check the syntax), you need the template keyword:

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

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

like image 195
dyp Avatar answered Feb 22 '26 17:02

dyp


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

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

Note, however, that your typing of Field<Class>, if unique, could be used to construct 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 I would have is, do you really need storage for said Field<Class> to actually have a pointer to a string, and if so does it need to be unique, and if so does it need to be "bare"? Because 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 moves the problem of "where is the _field stored" to being the compilers problem. And it is initialized by the contents of field_traits<T>::get_name().

like image 35
Yakk - Adam Nevraumont Avatar answered Feb 22 '26 18:02

Yakk - Adam Nevraumont



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!