1

explicit2 つのコンストラクター オーバーロード (異なる型に基づく)が与えられstd::function<...>た場合、の戻り値はどちらかstd::bindを選択できます(それにより、呼び出しがあいまいになります)。

call of overloaded ‘Bar(std::_Bind_helper<false, void (Foo::*)(int), 
    Foo*, int>::type)’ is ambiguous

どちらかをコメントアウトすると、コードがコンパイルされます!

explicitコンストラクターを作成すると、正しいオーバーロードが選択されるか、両方が選択されないようになると思いましたか?

もちろん、バインドした時点で明示的にa を作成すると、次のように機能します。std::function

    Bar b(std::function<void(int)>(std::bind((&Foo::process), &f, 1)));

しかし、なぜ型推論が機能しないのか、私は戸惑っていますか?

  • からの戻り値std::bindが 2 つのコンストラクター シグネチャのいずれにも一致しない場合、それらがexplicit両方とも選択されないようにする必要があります。
  • からの戻り値std::bindが 2 つのコンストラクター シグネチャのいずれかに一致する場合、それらが一致するという事実explicitにより、正しいものが選択されるはずです。

ここで実際に何が起こっているのですか?

以下の完全な作業コード:

#include <functional>

struct Foo
{
    void process(int) { }
};

struct Bar
{
    // comment out either of these to compile
    explicit Bar(std::function<void(int)>) {} 
    explicit Bar(std::function<void(short)>) {}
};

int main()
{
    Foo f;
    Bar b(std::bind(&Foo::process, &f, 1));
    return 0;
}
4

1 に答える 1

4

コンストラクターを作成するexplicitことは、引数が正確に一致する必要があることとは関係ありません! コンストラクターを明示的にすることの影響は、このコンストラクターを使用する型とは異なる型のオブジェクトを暗黙的に変換するために使用されないことを意味しますBar。ただし、Bar直接初期化 (つまりBar(x)) を使用してオブジェクトを初期化しようとすると、両方のコンストラクターが考慮されます。

の結果std::bind()は確かに ではありませんstd::function<Signature>。つまり、どちらのコンストラクタにも正確には一致しません。関数オブジェクトに対して機能する非explicitコンストラクターがstd::function<Signature>あるため、両方のシグネチャが一致します。生成されたバインド式はパラメーターを必要としませんが、引数を取ることができます。つまり、引数の型を使用して 2 つのうちどちらを区別することはできません。のコンストラクターはBar一致する必要があります。バインド式が 1 つの引数を必要とする場合でも、あるコンストラクターを別のコンストラクターよりも優先するために使用されるとは思いません。

于 2013-09-22T00:53:48.427 に答える