8

Wikibook Optimizing C++を読むと、この段落に次の提案があります。

整数値がアプリケーション コードでは定数であるが、ライブラリ コードでは変数である場合は、それをテンプレート パラメーターにします。

したがって、次のような関数がある場合

void myfunction(int param)
{
     switch(param)
     {
          case 1:
              do_something_1();
          break;

          case 2:
              do_something_2();
          break; 

          ...

          case 100:                 // 100 is taken as example
              do_something_100();
          break;
     }
}

次のように置き換えると便利ですか?

template<int param> void myfunction()
{
     switch(param)
     {
          case 1:
              do_something_1();
          break;

          case 2:
              do_something_2();
          break; 

          ...

          case 100:                 // 100 is taken as example
              do_something_100();
          break;
     }
}

それとも完全に不要ですか?理由を教えてください。

4

3 に答える 3

6

念頭に置いている微調整は、コンパイル時にパラメーターがわかっている場合にのみ機能します。あなたの引用には、ライブラリを作成するときに作成できないアプリケーション コードに関する仮定があります。

アプリケーションコードでの関数呼び出しが以前は

const int x = 3;
myfunction(1);
myfunction(2);
myfunction(x);
//etc...

これらは次のように書き換えることができます。

const int x = 3;
myfunction<1>();
myfunction<2>();
myfunction<x>();
//etc...

しかしx、変数の場合、それは不可能です:

int x = ...;      // unknown at compile-time!
myfunction<x>();  // will fail to compile!

前述のように、ライブラリを作成するときに、アプリケーションについて想定してはいけない場合があります。やりたいことややらなければならないことがあります。アプリケーションが定数を使用することを期待しているが、強制的に使用したくない場合を考えてみましょう。

定数を使用する場合に最適化したいが、変数の使用を許可したい。これには、次の 2 つのオプションをお勧めします。

  • 1 つはテンプレート パラメーターを使用し、もう 1 つは関数パラメーターを使用します。

  • 関数をインライン化します。これにより、アプリケーション コードをコンパイルするときに、関数の定義がコンパイラによって認識され、パラメーターが定数である場合do_something_*()に単一の呼び出しに最適化するために使用できます。

どちらのオプションでも、関数の定義をアプリケーションのコードに公開する必要があることに注意してください。2番目のオプションを使用したいと思います。

于 2013-02-27T09:34:10.560 に答える
3

それはあなたがどのように使いたいかによって異なりますmyfunction。たとえば、テンプレート化された関数は、実行時に宣言された変数では使用できませんでした。

int dosomethingmaybe = 1;
dosomethingmaybe += 2;
myfunction< dosomethingmaybe >(); // <--- Error, you cannot instantiate a template with a non-constant variable
myfunction( dosomethingmaybe ); // <--- Will call `do_something_3();`, according to your code

実行時に変更されない引数をコンパイル時に提供できる場合は、テンプレートを使用します。テンプレートは常にコンパイル時に評価されるため、プログラムが実行される前に入力と出力が修正されます

誰かが入力を修正し、機能の特定の出力を前もって期待できることがわかっている場合は、テンプレート バージョンを作成します。それ以外の場合は、通常の関数ランタイム バージョンで問題ありません。

于 2013-02-27T09:34:36.837 に答える
1

ここでの実際の状況で実際にパフォーマンス上の利点が見られるとは思えません。呼び出しがインライン化されている場合、2 つのアプローチに違いはありません。パラメーターがコンパイル時にわかっている限り (そうである必要があります)、まともなコンパイラはどちらの場合も不要なスイッチを削除します。違いが見られる唯一のケースは、インライン化が発生しない場合です。この場合、テンプレート化されたアプローチではスイッチを削除できますが、他のアプローチでは削除できません。ただし、関数呼び出しのオーバーヘッドは、この場合、いずれにせよ切り替えのコストを小さくする可能性があります。

于 2013-02-27T09:43:25.350 に答える