2009-10-01 8 views
23

テンプレートクラスの特定のメンバーを特化できますか?次のようなものがあります。特定のメンバーのテンプレート特化?

template <typename T,bool B> 
struct X 
{ 
    void Specialized(); 
}; 

template <typename T> 
void X<T,true>::Specialized() 
{ 
    ... 
} 

template <typename T> 
void X<T,false>::Specialized() 
{ 
    ... 
} 

もちろん、このコードは無効です。これは私が思い付いたものです

+0

あなたがここで何を意味するかは完全にはっきりしていません。テンプレートパラメータを特定の型の子孫にすることを意味しますか?あなたはJavaでと同様にできますか? –

+1

@Alconテンプレートクラスを専門にするときは、クラス全体に対して* different *実装を提供する必要があります。機能を除いて、専門分野間で共通のコードを共有したいと思うようです。 – AraK

+0

この質問は、「メンバー」ではなく「メンバー機能」と言うべきでしょうか?誰もこれがデータメンバーであるとは思わない。 –

答えて

3

、あなたが唯一、すべてのテンプレート引数を提供することで、それを明示的に特化することができます:)

//The generic template is by default 'flag == false' 
template <class Type, bool flag> 
struct something 
{ 
    void doSomething() 
    { 
     std::cout << "something. flag == false"; 
    } 
}; 

template <class Type> 
struct something<Type, true> : public something<Type, false> 
{ 
    void doSomething() // override original dosomething! 
    { 
     std::cout << "something. flag == true"; 
    } 
}; 

int main() 
{ 
    something<int, false> falseSomething; 
    something<int, true> trueSomething; 

    falseSomething.doSomething(); 
    trueSomething.doSomething(); 
} 
+5

あなたは上書きしていない、あなたはただ隠れているだけです。 – curiousguy

26

それほど悪くはありません。クラステンプレートのメンバ関数の部分的な特殊化は許されません。

template <typename T,bool B> 
struct X 
{ 
    void Specialized(); 
}; 

// works 
template <> 
void X<int,true>::Specialized() 
{ 
    ... 
} 

周りの仕事はまだ同じクラスであるという利点を持つオーバーロードされた関数を導入することであり、したがって、彼らはメンバ変数に同じアクセス権を持って、機能や

// "maps" a bool value to a struct type 
template<bool B> struct i2t { }; 

template <typename T,bool B> 
struct X 
{ 
    void Specialized() { SpecializedImpl(i2t<B>()); } 

private: 
    void SpecializedImpl(i2t<true>) { 
     // ... 
    } 

    void SpecializedImpl(i2t<false>) { 
     // ... 
    } 
}; 

注意を詰め込みますオーバーロードされた関数に渡し、テンプレートパラメータを関数パラメータにプッシュすることによって、関数を任意に「特殊化」することができ、必要に応じてテンプレート化することもできます。他の一般的な手法は、私は通常より多くのコードを必要とし、私は他の人がクラステンプレートの道に延期を好む機能は、扱いやすい過負荷に見つけることがわかり別途

template<typename T, bool B> 
struct SpecializedImpl; 

template<typename T> 
struct SpecializedImpl<T, true> { 
    static void call() { 
    // ... 
    } 
}; 

template<typename T> 
struct SpecializedImpl<T, false> { 
    static void call() { 
    // ... 
    } 
}; 

template <typename T,bool B> 
struct X 
{ 
    void Specialized() { SpecializedImpl<T, B>::call(); } 
}; 

定義されたクラステンプレートに延期することです。結局それは味の問題です。この場合、他のテンプレートをネストされたテンプレートとしてXに入れておくこともできます。名前空間のスコープでのみ明示的な特殊化を行うことができるため、部分的にではなく明示的に特殊化し、クラススコープではありません。以下のバリアントがあまりにも最初のパラメータ変数を残す実証として

あなたはまた、単にオーバーロードする関数の目的のために、このようなSpecializedImplのテンプレートを作成することができ、(それはその後、前の私たちのi2tに似ています)(あなたが他とそれを呼び出すことができますタイプ - だけではなく、現在のインスタンスのテンプレートパラメータを持つ)

template <typename T,bool B> 
struct X 
{ 
private: 
    // maps a type and non-type parameter to a struct type 
    template<typename T, bool B> 
    struct SpecializedImpl { }; 

public: 
    void Specialized() { Specialized(SpecializedImpl<T, B>()); } 

private: 
    template<typename U> 
    void Specialized(SpecializedImpl<U, true>) { 
     // ... 
    } 

    template<typename U> 
    void Specialized(SpecializedImpl<U, false>) { 
     // ... 
    } 
}; 

私は時々、別のテンプレートに延期すると良いです(それは配列とポインタのような例になると、トリッキーな缶をオーバーロードし、ちょうどクラステンプレートへの転送と思います私にとってはより簡単でした)、時にはテンプレート内でのオーバーロードがより効果的です。あなたがクラスのメンバ変数に触れているかどうかを調べます。

+0

+1私の目の前には洗練された洗練されたソリューションがあります。 – AraK

+0

ありがとう、ありがとう、ありがとう、 –

+0

C++ 11がリリースされたので、これは 'std :: integral_constant'を使ってください。自分自身を編集することができますが、iPod Touchのモバイルビューでは本当に面倒です。 – Xeo

関連する問題