2017-11-02 14 views
3
ヘッダファイル内の次のテンプレートを考える

、そして専門のカップル:打ち鳴らす-5とclang - ヘッダファイルに静的なconst intを宣言するには?

template<typename> class A { 
     static const int value; 
}; 

template<> const int A<int>::value = 1; 
template<> const int A<long>::value = 2; 

及び建物、それはすべてのために複数の定義文句、ファイルを構成する各光源ユニットのためのエラーになりますA<int>::valueおよびA<long>::value

最初は、テンプレートの特殊化を特定の翻訳単位に入れる必要があるかもしれないと思っていましたが、仕様を確認する際に値が一定の整数なので、これを許可する必要があります。

何か間違っていますか?

EDIT:定義を単一の翻訳単位に移動すると、のコンテキストでは、もはやA<T>::valueの値を使用できません(たとえば、その値が別のconst代入の値を計算するために使用されている)、その値は本当にヘッダー内にある必要があります。

+0

あなたは*定義するので、*あなたがまだそれらを配置する必要があり専門の変数を単一の翻訳単位でリンカーはそれをまとめることができます。 –

+1

他の定数の値を計算するために定数の値を使用する必要がある場合(これは、割り当てられているすべての定数の値を知る必要があります。ヘッダーから削除する場合は同じ翻訳単位)。 – markt1964

+0

ヘッダーでなぜそれを初期化する必要があるのか​​分かりません。 'template <> const int A :: value = 1;を定義できます。 template <> const int A :: value = A :: value + 1; 'をあなたの'に入れてください。cpp'ファイル。何か不足していますか? – cantordust

答えて

5

C++ 11では、あなたは多分その道を行くことができます。

template<typename> class B { 
    public: 
     static const int value = 1; 
}; 

template<> class B<long> { 
    public: 
     static const int value = 2; 
}; 

template<typename T> const int B<T>::value; 

だけ値のVARを専門としたい場合は、そのためにCRTPを使用することができます。あなたの定義をインラインすることができますC++ 17から

:++ 17 Cから削除することができます。また

template<> inline const int A<int>::value = 1; 
template<> inline const int A<long>::value = 2; 

を 'テンプレートのconst int型のB ::値を;' constexprのため:

template<typename> class C { 
    public: 
     static constexpr int value = 1; 
}; 

template<> class C<long> { 
    public: 
     static constexpr int value = 2; 
}; 

// no need anymore for: template<typename T> const int C<T>::value; 

とC++ 11のための別の解決策ではなく、++ 17 Cからの許可されているインラインVARSのインラインメソッドを使用することができます。

template<typename T> class D { 
    public: 
     static constexpr int GetVal() { return 0; } 

     static const int value = GetVal(); 
}; 

template <> inline constexpr int D<int>::GetVal() { return 1; } 
template <> inline constexpr int D<long>::GetVal() { return 2; } 

template< typename T> 
const int D<T>::value; 

あなたの最後に加えて、編集:

他の従属定義でも値を使用するには、インラインconstexprメソッドを使用すると最も読みやすいバージョンのようです。

編集:「OPEN」と言うと「clang」は「インスタンス化後に特殊化が起こっている」と文句を言います。打ち鳴らすか、gccがその場所に間違っている場合、私は、私は完全なクラスを再定義する必要がありますされていない場合CRTPが可能であることが既に言われ

template<typename T> class D { 
    public: 
     static constexpr int GetVal(); 
     static const int value; 
}; 


template <> inline constexpr int D<int>::GetVal() { return 1; } 
template <> inline constexpr int D<long>::GetVal() { return 2; } 

template <typename T> const int D<T>::value = D<T>::GetVal(); 

int main() 
{ 
    std::cout << D<int>::value << std::endl; 
    std::cout << D<long>::value << std::endl; 
} 

...

を知りません。私が打ち鳴らす上でコードをチェックし、OP、彼はそれを使用する方法を理解していなかったことをコメントしているため、それは、任意の警告やエラーなしでコンパイル:

template<typename> class E_Impl { 
    public: 
     static const int value = 1; 
}; 

template<> class E_Impl<long> { 
    public: 
     static const int value = 2; 
}; 

template<typename T> const int E_Impl<T>::value; 

template < typename T> 
class E : public E_Impl<T> 
{ 
    // rest of class definition goes here and must not specialized 
    // and the values can be used here! 

    public: 

     void Check() 
     { 
      std::cout << this->value << std::endl; 
     } 
}; 


int main() 
{ 
    E<long>().Check(); 
    std::cout << E<long>::value << std::endl; 
    E<int>().Check(); 
    std::cout << E<int>::value << std::endl; 
} 
+0

@ markt1964:CRTPを使うことができると私はすでに言っていましたが、私はあなたのための例も追加しました。 GetVarメソッドの特殊化のclang準拠バージョンが既に追加されています。 – Klaus

関連する問題