如何使用默认模板参数分离模板化 class 的声明和实现?

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

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

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

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

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

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

失败

error C3860: template argument list following class template name must list parameters in the order used in template parameter list

error C2976: 'Foo<S,<__formal>>' : too few template arguments

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

失败

error C3860: template argument list following class template name must list parameters in the order used in template parameter list

error C3855: 'Foo<S,<unnamed-symbol>>' : template parameter '__formal' is incompatible with the declaration

我也试过将模板声明更改为

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

也失败并显示第一条错误消息。

正确的做法是什么?

您不能部分特化模板函数(这是您在第一个片段中所做的)。如果您询问如何在 class 之外定义它,试试这个:

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

您不能仅将 std::enable_if_t<(S > 0), int> 替换为 int,因为定义不相同(enable_if 一个 SFINAE 出 S == 0 案例)。

Live snippet

What is the correct way of doing this?

我想你试过的第二个是 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
 }

保持简单:

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

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

template <>
class Foo<0>;

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