tipo de retorno de std::bind implícitamente convertible a dos constructores explícitos diferentes

Dado dos explicit constructor overloads (based on different std::function<...> types), the return value of std::bind es capaz de seleccionar ya sea (thereby making the call ambiguous)

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

If I comment out either, then the code compiles!

I would have thought making the constructors explicit would have either selected the correct overload, or prevented both from being selected?

Por supuesto explícitamente creando un std::function at the point I bind works:

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

However, I'm puzzled as to why type deduction doesn't work?

  • If the return value from std::bind matches neither of the two constructor signatures, the fact they are explicit should prevent both from being selected.
  • If the return value from std::bind matches one of the two constructor signatures, the fact they are explicit should cause the correct one to be selected.

¿Qué está pasando realmente aquí?

Full working code below:

#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;

preguntado el 22 de septiembre de 13 a las 01:09

1 Respuestas

Haciendo el constructor explicit has nothing to do with the arguments having to match exactly! The affect of making a constructor explicit means that it won't be used to implicitly convert an object of a different type the type Bar using this constructor. However, if you try to initialize a Bar object using direct initialization (i.e., Bar(x)), both constructors will be considered.

El resultado de std::bind() ciertamente no es un std::function<Signature>, i.e., it doesn't match either of your constructors exactly. Since there is a non-explicit constructor para std::function<Signature> which works for function objects, both signatures do match: the produced bind expression doesn't require any parameter but it can take arguments, i.e., any argument type also cannot be used to distinguish which of the two constructors of Bar should match. Even if the bind expression would require one argument, I don't think it would be used to prefer one constructor over another.

Respondido el 22 de Septiembre de 13 a las 01:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.