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

How do I define methods outside of the declaration for my specialization of a non-type template class?

本文关键字:专用 定义 方法 声明 类型      更新时间:2023-10-16

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

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
}

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

错误:模板 ID "A<>"表示"A<(EnumType(0u>::A(double("没有 匹配任何模板声明

我做错了吗?

在网上搜索类似案例后,我试图删除template<>(即使我不明白为什么这会起作用(,但后来我得到了

'A<(EnumType(0u>::A(double(' 的多重定义

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

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

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

该标准说:

显式专用类模板的成员的定义方式与普通类的成员相同,并且不使用模板<>语法。

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

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

完全没有template<>就好了。这是因为您实际上是在专门化显式专用类模板的(特殊(成员函数(构造函数(。
在科利鲁上看到它。


如果没有明确的专业化,情况会有所不同。
作为一个最小的工作示例:

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<>,因为您没有定义已专用类模板的成员函数的专用化。

您错过了一个分号 (;)在类定义的末尾。非模板成员函数可以这样定义:

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() {}

并且需要一个空的模板参数列表来显式专业化函数模板(我想,这就是您在此处使用它的原因(,非正式地因为它告诉编译器这不是函数重载。