2017-06-11 3 views
0

は、このコードを考えてみましょう:C++複数definitons、

template<typename T, SomeEnum mode> struct TC{ 

    T data; 

    //... 

    void doStuff(); 
}; 

は「doStuffは、」テンプレートの設定列挙型の値に基づいて、複数の定義を持つことができますか?

TC<int, SomeEnum::MODE_1> tc1; tc.doStuff(); //do some stuff 
TC<int, SomeEnum::MODE_2> tc2; tc.doStuff(); //do some other stuff 

は(私は「モード」を保存して、それにブランチを作るが、実際には複数の定義を意味するものではありません。)

+0

[this](http://dev-jungle.blogspot.de/2014/02/conditional-type-selection-using-c.html)が役立つかどうかを確認してください。これは少し違っていますが、基本的に同じテクニックです。 –

答えて

3

あなたは、タグディスパッチを行うことができます。ただ、列挙型の各パッケージ値のための過負荷を提供します。

template<typename T, SomeEnum mode> struct TC{ 

    T data; 

    //... 
    template<SomeEnum v> 
    using tag_type = std::integral_constant<SomeEnum, v>; 

    void reallyDoStuff(tag_type<SomeEnum::MODE_1>); 
    void reallyDoStuff(tag_type<SomeEnum::MODE_2>); 

    void doStuff() { reallyDoStuff(tag_type<mode>{}); } 
}; 

クラステンプレートのメンバ関数を使用していない限り、あなただけのためにreallyDoStuffの一つの定義(適切なもの)をインスタンス化したいインスタンス化されることはありませんのでTCのすべてのインスタンス。

不明な点がある場合は、機能テンプレートの特化へのオーバーロードを推奨します。これは通常、優れた選択肢です。

0

これは一般的に、ある、何のためのテンプレートの特殊です。どのようなテンプレートの特殊化がわからない場合は、残りの答えを読む前にまずC++の本を読む必要があります。ここ

のみつまずきは、個々のクラスメソッドは特殊なことができない、クラス全体が専門なければならないということです。しかし、次のような共通のアプローチがあります。

は、このようなヘルパーテンプレートクラスへの単なる関数呼び出しのラッパー、としてあなたのメンバ関数を定義します。

実際doStuffだ
template<typename T, SomeEnum mode> void TC::doStuff() 
{ 
    doStuff_helper<T, mode>::doStuff(*this); 
} 

()。実際のコードはヘルパークラスに入ります。次のようにヘルパークラステンプレートを定義 (あなたはもちろん、適切に宣言、および他のそのような雑貨を前方に使用する必要があります):元のクラスメソッドがした

template<typename T, SomeEnum mode> class doStuff_helper { 
public: 

    static void doStuff(TC<T, mode> &me) 
    { 
     // ... 
    } 
}; 

すべてを、今いくつかと、ここで行うことができます明らかな違い。これはもはや元のクラスの実際のメソッドではありません。だから、代わりに元thisの、あなたが使用することをここにmeの参照を持っています。これは実際のクラスメソッドではないため、プライベートクラスまたは保護されたクラスメンバーにアクセスする際の通常の問題があります。しかし、これらは自分のメリットで簡単に解決できる細部の細部です。

template<typename T> class doStuff_helper<T, MODE_VALUE> { 
public: 

    static void doStuff(TC<T, MODE_VALUE> &me) 
    { 
     // ... 
    } 
}; 

このdoStuff()は今完全に異なるものになることができます。ポイントは、あなたが今何ができるか、全体のことを専門であるということです。これは、許可されていないクラスメソッドのスペシャライゼーションを通常の、ガーデン多様な、クラスのスペシャリゼーションに変えるための一般的なアプローチです。

頻繁に使用されている。この一般的なアプローチのさらなる改良があります。そのような改良は、これ自体は一般的な、オリジナルのテンプレートクラスの異なるメソッドを呼び出す特化したバージョンのラッパーとmeへのメソッド呼び出し以外の何物でも、ならないdoStuff()を因数分解持っているだろう。

ここで、紙と鉛筆を使って何が起こったのか分かると、元のdoStuff()クラスメソッドへの1回の呼び出しで2つの異なるクラスメソッドが呼び出されます。通常は元のテンプレートクラスのパラメータに応じてprivate)です。唯一の適切な方法は、テンプレートパラメータに応じて使用されているとし、これらの二つの異なるクラスメソッドは、基本的に、あなたがもともと持っていると思ったdoStuff()のあなたの2つの異なるバージョンをだろう。