如何为非类型模板类的特化定义声明之外的方法?

时间:2017-02-09 16:44:55

标签: c++ c++11 templates

标题是满口的,但基本上我写了这样的东西:

enum EnumType{ValA, ValB};

template<EnumType> class A {};

template<>
class A<ValA>
{
private:
    double param;
public:
    A(double param);
};

template<>
A<ValA>::A(double param)
{
    // Do Stuff
}

当我尝试编译它时,我得到:

  

错误:template-id&#39; A&lt;&gt;&#39; for&#39; A&lt;(EnumType)0u&gt; :: A(double)&#39;才不是   匹配任何模板声明

我这样做错了吗?

在网上搜索类似的案例后,我尝试删除template<>(即使我不明白为什么会这样做),但后来我

  

&#39; A&lt;(EnumType)0u&gt; :: A(double)&#39;

的多重定义

我想我可以将template<>替换为inline(我试过并编译),但这并不是正确的方法(或者如果它是,我不明白为什么。)

有人可以向我解释我写的内容有什么问题,为什么改变它似乎有效,以及正确的做法是什么?

2 个答案:

答案 0 :(得分:6)

  

有人可以向我解释我写的内容有什么问题,为什么改变它似乎有用,有什么方法可以做到这一点?

标准说:

  

显式专用类模板的成员以与普通类成员相同的方式定义,而不是使用模板&lt;&gt;语法。

因此,在您的情况下,您必须使用:

A<EnumType::ValA>::A(double param)
{
    // Do Stuff
}

根本没有template<>就好了。那是因为你实际上是专门化一个显式专用类模板的(特殊)成员函数(构造函数) 请在coliru上查看。

如果没有给出明确的专业化,那将会有所不同 作为一个最小的工作示例:

enum EnumType{ValA, ValB};

template<EnumType> class A
{
private:
    double param;
public:
    A(double param);
};

template<>
A<EnumType::ValA>::A(double)
{
    // Do Stuff
}

int main() {
    A<EnumType::ValA> a{0.};
}

在这种情况下,在构造函数的定义之前需要template<>,因为您没有定义已经专门化的类模板的成员函数的特化。

答案 1 :(得分:0)

您在类定义结束时错过了分号(;)。 非模板成员函数可以这样定义:

A<ValA>::A(double param) {
    // Do Stuff
}

非正式地,模板参数列表仅在必要时写入,例如,为了定义类模板的成员函数模板,两个模板参数列表都应该写入

template<class U, class V>
class A{
  template <class T>
  A();
};

template<class U, class V>
template <class T>
A<U, V>::A() {}

并且函数模板的显式特化需要一个空的模板参数列表(我猜,这就是你在这里使用的原因),非正式地,因为它告诉编译器这不是函数重载。