如何用默认模板参数分离模板类的声明和实现

How to seperate declaration and implementation of a templated class with a default template parameter?

本文关键字:声明 实现 参数 何用 默认 分离      更新时间:2023-10-16

我喜欢将类的声明和实现分开。我知道类模板和函数的实现也必须进入头文件,这不是问题所在。

我在实现这个类时遇到了问题:

template <size_t S, std::enable_if_t<(S > 0), int> = 0>
class Foo {
public:
Foo();
}

到目前为止,我已经尝试过:

template<size_t S>
Foo<S>::Foo() {}

失败

错误C3860:类模板名称后面的模板参数列表必须按模板参数列表中使用的顺序列出参数

错误C2976:‘Foo<S、 &lt__正式&gt>':模板参数太少

template<size_t S, int i>
Foo<S, i>::Foo() {}

失败

错误C3860:类模板名称后面的模板参数列表必须按模板参数列表中使用的顺序列出参数

错误C3855:‘Foo<S、 <未命名符号>gt;':模板参数"__formal"与声明不兼容

我还尝试将模板声明更改为

template <size_t S, typename = std::enable_if_t<(S > 0)>>

其也因第一错误消息而失败。

正确的方法是什么?

您不能部分专门化模板函数(这就是您在第一个代码段中所做的)。如果你问如何在类外定义它,可以试试这个:

template <size_t S, std::enable_if_t<(S > 0), int> j>
Foo<S, j>::Foo(){}

您不能仅用int替换std::enable_if_t<(S > 0), int>,因为定义不等价(enable_if一个SFINAE排除了S == 0的情况)。

实时片段

保持简单:

template <size_t S>
class Foo {
public:
Foo();
};
template <size_t S>
Foo<S>::Foo() { }
template <>
class Foo<0>;

在这种特殊情况下,我不确定添加SFINAE是否会给您带来任何额外的好处。即使是显式的专门化也有可能是不必要的,只要一个简单的static_assert(S > 0, "!")就足够了。

正确的方法是什么?

我想是您尝试过的第二个,typename

给定

template <size_t S, typename = std::enable_if_t<(S > 0)>>
class Foo {
public:
Foo();
};

构造函数可以定义为

template <std::size_t S, typename T>
Foo<S, T>::Foo() {}

的完整编译示例

#include <iostream>
#include <type_traits>
template <size_t S, typename = std::enable_if_t<(S > 0)>>
class Foo {
public:
Foo();
};
template <std::size_t S, typename T>
Foo<S, T>::Foo() {}
int main ()
{
Foo<12U>  f12;   // compile
// Foo<0U>   f0; // compilation error
}