Why does this code give the error, “template specialization requires 'template<>'”?

人盡茶涼 提交于 2019-12-22 04:39:25

问题


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.)


回答1:


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.




回答2:


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().




回答3:


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

// header:
class C {
    static int i;
};

// source:
int C::i = 3;

Templates aren't ordinarily defined in source files, so the code would 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 don't have the definition of the static data member. That's okay if you don't use it. But the code that the compiler is complaining about defines a static data member for CRTP<Class>; that's a specialization (because it's not applicable to all instantiations of CRTP, just to this one), and the compiler is saying that you have to tell it that it's a specialization. So do as you're told:

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

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

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


来源:https://stackoverflow.com/questions/15723850/why-does-this-code-give-the-error-template-specialization-requires-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!