22

2 つの引数を取る関数があるとします。

void f(int x, int y);

そのうちの1つをバインドしたいと思います。std::bind次のように使用できます。

auto partiallyBoundF = std::bind(f, 10, _1);

partiallyBoundFは引数を 1 つしか取りませんが、複数で呼び出すことができます。最初の引数を超える引数は、意味のある型である必要さえありません。

partiallyBoundF(20, 0);
partiallyBoundF(0, 44, -99, "Hello", 4.5, true, []{});

bindから返されたオブジェクトに追加の引数を渡すことを許可する目的は何ですか? 他の場所では拒否される呼び出しエラーをコンパイルできます。

4

1 に答える 1

19

余分な引数を無視すると、実装がはるかに簡単になり、実際に役立ちます。

operator()libstdc++ (g++) などの典型的な実装では、引数をタプルに集めてから、必要に応じてstd::placeholderバインド引数にそれらを抽出させるというアプローチが取られます。引数のカウントを強制するには、使用されたプレースホルダーの数をカウントする必要があり、これはかなり複雑です。bind callable は、複数の呼び出しパターンまたはテンプレート化されたoperator()呼び出しパターンを持つファンクターになる可能性があるため、バインド オブジェクトoperator()は単一の「正しい」署名では生成できないことに注意してください。

また、次のように記述できることに注意してください。

std::bind(&foo, std::placeholders::_1, std::placeholders::_3);

つまり、バインド オブジェクトの 2 番目の引数を明示的に無視します。引数の数を強制する場合bind、たとえば 4 番目の引数も無視するように指定する追加の方法が必要になります。

有用性については、メンバーシグナルハンドラーをシグナルにバインドすることを検討してください。

sig.connect(std::bind(&C::on_sig, this, param, std::placeholders::_1));

余分sigな不要な放出パラメータがある場合、それらはbindオブジェクトによって単純に無視されます。そうしないと、同じハンドラーを複数のシグナルにバインドすると、実際の目的がなくても複数の転送ラッパーを作成する必要があります。

于 2012-11-06T13:58:23.180 に答える