0

C++ テンプレートを使用して Strategy ファンクターを渡し、関数の動作を変更しています。それは正常に動作します。私が渡すファンクターは、ストレージを持たないステートレス クラスであり、() 演算子を従来のファンクターの方法でオーバーロードするだけです。

template <typename Operation> int foo(int a) 
{
int b=Operation()(a);
/* use b here, etc */
}

私はこれを頻繁に行っており、うまく機能しており、多くの場合、6 つまたは 7 つのテンプレート化されたファンクターを渡してテンプレートを作成しています!

ただし、コードのエレガンスと効率の両方について心配しています。ファンクターはステートレスであるため、Operation() コンストラクターはフリーであり、ファンクターの評価はインライン関数と同じくらい効率的であると想定していますが、すべての C++ プログラマーと同様に、私は常にいくつかのしつこい疑問を抱いています。

私の 2 番目の質問は、別のファンクター アプローチを使用できるかどうかです。() 演算子をオーバーライドせず、コンストラクター内のすべてを副作用として実行する方法です。何かのようなもの:

struct Operation {
  Operation(int a, int &b) { b=a*a; }
};
template <typename Operation> int foo(int a) 
 {
   int b;
   Operation(a,b);
    /* use b here, etc */
 }

ファンクターの「作業」としてコンストラクターを使用している人を見たことがありませんが、機能するはずです。何か利点はありますか?デメリットは?私は奇妙な二重括弧 "Operator()(a)" の削除が好きですが、それはおそらく美的です。

4

5 に答える 5

2

デメリットは?

  • Ctor は有用な値を返しません。連鎖呼び出し (例: foo(bar())) では使用できません。
  • 彼らは投げることができます。
  • 設計の観点 -- ctor はオブジェクト作成関数であり、主力製品を意図したものではありません。
于 2009-03-07T16:22:14.250 に答える
1
  1. コンパイラは実際には Operation の空のコンストラクターをインライン化します (最適化をオフにした場合を除いて、少なくとも同様の状況の gcc はインライン化します)。
  2. コンストラクターですべてを行うことの欠点は、この方法では内部状態を持つファンクターを作成できないことです。述語を満たす要素の数をカウントするためのファンクター。また、実際のオブジェクトのメソッドをファンクターとして使用すると、後で実行するためにそのインスタンスを格納できます。これは、コンストラクター アプローチではできないことです。
于 2009-03-07T16:21:56.873 に答える
0

別のクラスでコンストラクターを実装する意味はないようです。
あなたがしているのは、カプセル化を破り、悪用のためにクラスを設定することだけです。

コンストラクターは、オブジェクトをクラスで定義された適切な状態に初期化することになっています。別のオブジェクトがクラスを初期化できるようにしています。このテンプレート クラスがクラスを正しく初期化する方法を知っているという保証はありますか? クラスのユーザーは、意図しない方法でオブジェクトの内部状態を台無しにする可能性のあるオブジェクトを提供できます。

クラスは自己完結型であり、適切な状態に初期化する必要があります。あなたがしているように見えるのは、テンプレートが何ができるかを見るためだけにテンプレートをいじっていることです。

于 2009-03-08T12:52:31.737 に答える