【问题标题】:Why does this code give the error, "template specialization requires 'template<>'"?为什么这段代码会给出错误,“模板专业化需要'模板<>'”?
【发布时间】:2013-03-21 08:54:03
【问题描述】:

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

【问题讨论】:

  • 您是否尝试过添加模板?
  • @AlexChamberlain:哈哈,不,我完全不明白这与专业化有什么关系,因为我没有专业化任何东西......我真的没想到会去方向。
  • @Mehrdad:实际上,您正在为 Class 类专门化您的类模板的 static 数据成员(根据 17.4.3/1,static 数据成员可以专门化,只是像成员函数)
  • @AndyProwl:啊……我不知道你可以专门化一个成员,我以为你只能专门化一个类/函数。太棒了,谢谢!
  • @Mehrdad 尽可能按字面意思阅读 clang 错误消息...

标签: c++ templates clang template-specialization crtp


【解决方案1】:

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

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

它的括号是空的,因为所有模板参数都是专用的,但你不能就这样离开它。

【讨论】:

    【解决方案2】:

    该错误准确地说明了缺少的内容。在该行之前缺少template&lt;&gt;

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

    但是,请注意,如果您输入的 Field&lt;Class&gt; 是唯一的,则可以使用给定的字符串构造 Field&lt;Class&gt; 的所有实例。

    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&lt;Class&gt; 的每个实例始终具有名称"blah"

    我想问的一个问题是,你真的需要为上述Field&lt;Class&gt; 存储一个指向字符串的指针吗?如果需要,它是否需要是唯一的,如果需要,它是否需要“裸露” ?因为找出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&lt;T&gt;::get_name()的内容初始化。

    【讨论】:

    • 不,我真的确实需要它是这样的静态字段。您可能想查看here 的示例,了解在哪里需要(工厂注册就是其中之一)。
    【解决方案3】:

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

    // 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&lt;Class&gt;定义了一个静态数据成员;这是一种特化(因为它不适用于CRTP 的所有实例化,仅适用于这个),编译器说你必须告诉它这是一种特化。照你说的做:

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

    或者,要编写非专用模板版本,请使用通常的模板语法:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-22
      • 1970-01-01
      • 2021-01-01
      • 2018-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多