2017-11-16 25 views
2

私はクラスの宣言と実装を分離したいと思っています。クラステンプレートと関数の実装もヘッダーファイルに入っていることがわかりますが、それは問題ではありません。デフォルトのテンプレートパラメータを使用してテンプレートクラスの宣言と実装を分離する方法は?

私は、このクラスを実装するトラブルを抱えている:

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

は、これまでのところ、私が試してみました:

エラーC3860で失敗しました

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

:テンプレート引数リスト以下のクラスをテンプレート名は、テンプレートパラメータリストで使用される順序でパラメータをリストする必要があります

エラーC2976: 'フー< S、< __formal >>':テンプレート引数リスト:

エラーC3860で失敗した数が少なすぎるテンプレート引数

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

次のクラステンプレート名は、テンプレートパラメータリストで使用される順序でパラメータをリストする必要があります

エラーC3855: 'フー< S、<無名のシンボル>>':テンプレートパラメータ '__formalは' 私も

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

にテンプレート宣言を変更しようとした宣言

と互換性がありません。

も最初のエラーメッセージで失敗しました。

これを行う正しい方法は何ですか?

答えて

3

テンプレート関数を部分的に特殊化することはできません(これは、最初のスニペットで行っていることです)。あなたはクラスの外にそれを定義する方法について尋ねている場合は、これを試してみてください。

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

定義は(S == 0ケースアウトenable_if 1 SFINAEs)等価ではないとあなただけの、intによってstd::enable_if_t<(S > 0), int>を置き換えることはできません。

Live snippet

0

これを行うための正しい方法は何ですか?

私はあなたが試みた2番目のものをtypenameとします。コンストラクタは

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 
} 
2

として定義することができます

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

考える

はそれをシンプルに保つ:

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

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

template <> 
class Foo<0>; 

この特定のケースでは、私はSFINAEを追加することで余分なメリットが得られるとは限りません。明示的な特殊化さえも不要で、単純なstatic_assert(S > 0, "!")で十分です。

+0

実際には、状況は少し複雑です。私は例のためにそれを愚かにしました。無効な値をすべて列挙することは実用的ではありません。しかし、 'static_assert'についての良い点です。私は 'enable_if'を試してみることに興奮していると思います。 – IchBinKeinBaum

関連する問題