4

関数呼び出し間で状態を維持するためではなく、関数呼び出し間で共有されるいくつかの引数を取得したいため、ファンクターを作成する傾向があります。例として:

class SuperComplexAlgorithm
{
    public:
        SuperComplexAlgorithm( unsigned int x, unsigned int y, unsigned int z )
            : x_( x ), y_( y ), z_( z )
        {}

        unsigned int operator()( unsigned int arg ) const /* yes, const! */
        {
            return x_ * arg * arg + y_ * arg + z_;
        }

    private:
        // Lots of parameters are stored as member variables.
        unsigned int x_, y_, z_;
};

// At the call site:
SuperComplexAlgorithm a( 3, 4, 5 );
for( unsigned int i = 0; i < 100; ++i )
    do_stuff_with( a ); // or whatever

に比べ

unsigned int superComplexAlgorithm( unsigned int x, unsigned int y,
                                    unsigned int z, unsigned int arg )
{
    return x * arg * arg + y * arg + z;
}

// At the call site:
auto a = std::bind( superComplexAlgorithm, 3, 4, 5, std::placeholders::_1 );
for( unsigned int i = 0; i < 100; ++i )
    do_stuff_with( a );

私の意見では、最初の解決策には多くの欠点があります。

  • x, y,が行うことのドキュメントはz、別の場所 (コンストラクター、クラス定義、operator()) に分かれています。
  • 定型コードがたくさん。
  • 柔軟性が低い。パラメータの別のサブセットをキャプチャしたい場合はどうすればよいですか?

boost::bindはい、私は、またはがどれほど有用であるかを理解しstd::bindました。多くのコードでこれを使い始める前の質問ですが、単純な関数で引数をバインドするよりも、手書きのステートレス ファンクターを使用することを検討すべき状況はありますか?

4

2 に答える 2

9

ラムダ ソリューションは、偶像的な C++11 の方法になります。

auto a = [&]( int x ){ return superComplexAlgorithm( 3, 4, 5, x ); };
for( unsigned int i = 0; i < 100; ++i )
  do_stuff_with( a );

手書きのファンクターを使用する利点は、次のことができることです。

  1. bind引数をキャプチャに移動するか、それらを変換します (C++1y ではラムダを使用して実行できますが、まだ実行できません。これは .
  2. これには非匿名型があります (したがって、 を使用せずに型について話すことができますauto) -- 同じことが にも当てはまりますが、式全体を ingせずに取得できるbind非匿名の意味のある型もあります! decltypeC++1y は、bind/lambda に対してこれを改善します。
  3. 残りの引数の完全な転送を行うことができます (ラムダを使用して C++1y でこれを行うことができる場合があり、これを行いますbind)
  4. インスタンスを作成するコードを台無しにすることなく、キャプチャされたデータの格納方法をいじることができます (ポインターで? スマート ポインターで?)。

複数の関数のオーバーロード セットを 1 つのオブジェクト (名前を共有する場合と共有しない場合があります) にラップするなど、手書きのファンクターとラムダでは実行できない非常に強力なこともできますbindが、そのようなコーナー ケースは使用できません。頻繁に登場するわけではありません。

于 2013-07-23T12:35:45.193 に答える