为什么这段代码会给出错误,"template specialization requires 'template<>'"?

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

本文关键字:template gt specialization requires lt 错误 段代码 代码 出错 为什么      更新时间:2023-10-16

当我尝试用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的参数不一定对所有子类都相同)

为了让编译器将其识别为模板专门化(例如能够检查语法),您需要template关键字:

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

它的括号是空的,因为所有模板参数都是特化的,但是你不能把它放在一边。

该错误准确地说明了缺少的内容。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()的内容初始化

静态数据成员必须同时具有声明和定义。如果这是一个普通类,它看起来像这样:

// 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");