最近、 boost :: bindを使用しているときに、コードにバグが発生しました。
boost :: bind docsから:
bindが取る引数は、返された関数オブジェクトによってコピーされ、内部的に保持されます。
保持されていたコピーのタイプは、関数のシグネチャに基づいていると思いました。ただし、実際には、渡された値のタイプに基づいています。
私の場合、バインド式で使用される型を関数が受け取る型に変換するために、暗黙の変換が行われていました。この変換はバインドのサイトで発生すると予想していましたが、結果の関数オブジェクトが使用されたときに発生します。
振り返ってみると、boost :: bindを使用すると、型が結合部位ではなく呼び出し部位でのみ互換性がない場合にエラーが発生するという事実から、これを理解できたはずです。
私の質問は:なぜboost :: bindがこのように機能するのですか?
- コンパイラのエラーメッセージが悪化しているようです
- 暗黙の変換が発生し、ファンクターへの呼び出しが複数ある場合は、効率が低下するようです。
しかし、Boostがどれだけうまく設計されているかを考えると、理由があると思います。std :: bind1st / bind2ndから継承された動作でしたか?これを実装するのが難しい/不可能であるという微妙な理由はありますか?完全に他に何か?
その2番目の理論をテストするために、機能しているように見える小さなコードスニペットを作成しましたが、それは単なるフラグメントであるため、説明していないバインドの機能がある可能性があります。
namespace b = boost;
template<class R, class B1, class A1>
b::_bi::bind_t<R, R (*) (B1), typename b::_bi::list_av_1<B1>::type>
mybind(R (*f) (B1), A1 a1)
{
typedef R (*F) (B1);
typedef typename b::_bi::list_av_1<B1>::type list_type;
return b::_bi::bind_t<R, F, list_type> (f, list_type(B1(a1)));
}
struct Convertible
{
Convertible(int a) : b(a) {}
int b;
};
int foo(Convertible bar)
{
return 2+bar.b;
}
void mainFunc()
{
int x = 3;
b::function<int()> funcObj = mybind(foo, x);
printf("val: %d\n", funcObj());
}