当我尝试用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() { }
我得到了
error: template specialization requires 'template<>'
Field<Class> const CRTP<Class>::_field("blah");
~~~~~~~~~~~ ^
我根本不明白这个错误。我对_field
的定义有什么问题?如何解决?
(注意_field
的参数对于所有子类不一定相同。)
答案 0 :(得分:12)
为了让编译器将其识别为模板特化(例如,为了能够检查语法),您需要template
关键字:
template<>
Field<Class> const CRTP<Class>::_field("blah");
它的括号是空的,因为所有模板参数都是专用的,但你不能把它丢弃。
答案 1 :(得分:2)
错误说明究竟缺少什么。该行之前缺少template<>
。
template<>
Field<Class> const CRTP<Class>::_field("blah");
但请注意,您输入Field<Class>
(如果唯一)可用于构造具有给定字符串的Field<Class>
的所有实例。
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() { }
表示Field<Class>
的每个实例始终具有名称"blah"
。
我要问的一个问题是,你真的需要存储器来说Field<Class>
实际上有一个指向字符串的指针,如果是这样,它需要是唯一的,如果需要,它需要是“裸”?因为找出static
实例存在的位置有点烦人。
与上面的field_traits
一起:
template<class Derived>
class CRTP { static Field<Derived>& field() const { static Field<Derived> _field( field_traits<Derived>::get_name()); return _field; };
这将“存储_field
的位置”问题转变为编译器问题。它由field_traits<T>::get_name()
。
答案 2 :(得分:2)
静态数据成员必须同时具有声明和定义。如果这是一个简单的类,它将如下所示:
// header:
class C {
static int i;
};
// source:
int C::i = 3;
模板通常不在源文件中定义,因此代码看起来像这样:
// header:
template <class T>
class C {
static int i;
};
template <class T>
int C<T>::i = 3;
在您的代码中,您没有静态数据成员的定义。如果你不使用它,那没关系。但是编译器抱怨的代码定义了CRTP<Class>
的静态数据成员;这是一个专门化(因为它不适用于CRTP
的所有实例化,只适用于这一个),并且编译器说你必须告诉它它是一个特化。就像你被告知的那样:
template <>
Field<Class> const CRTP<Class>::_field("blah");
或者,要编写非专业模板版本,请使用通常的模板语法:
template <class T>
Field<T> const CRTP<T>::_field("blah");