【问题标题】:How to seperate declaration and implementation of a templated class with a default template parameter?如何使用默认模板参数分离模板类的声明和实现?
【发布时间】:2017-11-16 18:10:33
【问题描述】:

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

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

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>' : 模板参数太少

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

失败了

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

错误 C3855: 'Foo>' : 模板参数 '__formal' 与声明不兼容

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

template &lt;size_t S, typename = std::enable_if_t&lt;(S &gt; 0)&gt;&gt;

这也失败了,第一条错误消息。

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

【问题讨论】:

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


    【解决方案1】:

    您不能部分专门化模板函数(这就是您在第一个 sn-p 中所做的)。如果您询问如何在课堂外定义它,请尝试以下操作:

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

    您不能只将std::enable_if_t&lt;(S &gt; 0), int&gt; 替换为int,因为定义并不相同(enable_if 一个 SFINAE 与S == 0 不同)。

    Live snippet

    【讨论】:

      【解决方案2】:

      保持简单:

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

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

      【讨论】:

      • 条件其实有点复杂。我只是为了这个例子而把它简化了。列出所有无效值是不切实际的。不过,关于static_assert 的观点很好。我想我对尝试enable_if 感到太兴奋了。
      【解决方案3】:

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

      我想你已经尝试过第二个,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
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-16
        相关资源
        最近更新 更多