2016-09-14 1 views
1

私は以下の問題があります。クラスAには、compute1()、compute2()、compute3()...という一連のメソッドがあり、それぞれがパフォーマンス重視のメソッドが呼び出されるネストループが深くあります。 )この方法は、(関数func1()またはfunc2のいずれかである必要があり、実行時の条件によって:パフォーマンスクリティカルなメソッドをC++で多態性を呼び出す最速の方法は?

class A { 
public: 
    void compute1(){ 
     for(i...) 
     for(j...) 
      for(k...) 
      // call func1(i,j,k) or func2(i,j,k) 
    } 

    void compute2(){ 
     for(i...) 
     for(j...) 
      for(k...) 
      // call func1(i,j,k) or func2(i,j,k) 
    } 
    .... 
} 

FUNCの呼び出しは()なしFUNC内部の文が許容できるかどうほどパフォーマンス重視です。 compute()メソッドの数が多いので、各funcのメソッドを別々にすることもオプションではありません。パフォーマンス上の理由からfunc()をvirtualにすることもできません。 デザイン上の理由から、私はクラスAをテンプレートにしたくありません(これは巨大であり、たくさんの論理を含んでいるので、これをすべてヘッダファイルに入れたくありません)。

この問題の他の解決方法はありますか?実行時に切り替わるいくつかの "バックエンド"を持つのはむしろ一般的に見えますが、これを達成する方法としては受け入れられないでしょう...

+0

は、あなたのパフォーマンスを測定していますか?最近、 'バーチャル'メソッドはボトルネックになることはめったにありません。コンパイラは、可能であればインラインでインライン展開することがありますが、可能でない場合は、CPUの分岐予測とiキャッシュによって、アクセスパターンに応じた測定可能なコストが排除されます。 – WhiZTiM

+0

パフォーマンスを気にする前に、***対策***!本当にボトルネックと思うコードですか?あなたが考える*それがボトルネックですか?問題の可能性があると思われるもののためにソリューションを却下しないでください。常に測定し、最初にプロファイルしてください。 –

+0

'パフォーマンス上の理由で動作しません'を定義します。余計なインダイレクションであり、あなたが考えている選択肢のどれよりもはるかに高速です。明白な選択肢は、もし可能であれば、ループ外の決定を行うことであり、すなわち、メソッドごとに2組のループを書くことである。あるいは、テンプレート:ヘッダーファイルにすべてのテンプレート実装ロジックを入れる必要がないので、異論は偽です。 – EJP

答えて

6

可能な方法は、compute1()などのテンプレート自分自身。テンプレートは、呼び出す適切な内部関数を選択するためにのみ使用されます。

template <typename FuncTrait> 
void A::compute1(FuncTrait trait) 
{ 
    for (...) 
     choose_func(trait); 
} 

struct trait_1 {}; 

template <> 
void choose_func<trait_1>(trait_1) 
{ 
    func1(); 
} 

compute1()を呼び出すための可能な方法:たとえば

a.compute1(trait_1()); 
+0

これはテンプレートの引数として 'func1'または' func2'自体への参照を受け入れることです: 'template ' – Angew

関連する問題