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

时间:2017-11-16 18:10:33

标签: c++ templates c++14 sfinae enable-if

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

我在实施这门课时遇到了麻烦:

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:&#39; Foo&lt; S,&lt; __ formal&gt;&gt;&#39; :模板参数太少

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

失败

  

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

     

错误C3855:&#39; Foo&lt; S,&lt; unnamed-symbol&gt;&gt;&#39; :模板参数&#39; __ formal&#39;与声明

不兼容

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

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

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

这样做的正确方法是什么?

3 个答案:

答案 0 :(得分:3)

您不能部分专门化模板功能(这是您在第一个代码段中所做的事情)。如果您要询问如何在课外定义它,请尝试以下方法:

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的情况。)

Scanner

答案 1 :(得分:2)

保持简单:

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

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

template <>
class Foo<0>;

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

答案 2 :(得分: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
 }