返回类型的std :: bind可以隐式转换为两个不同的显式构造函数

时间:2013-09-22 00:29:05

标签: c++ c++11 std-function stdbind

鉴于两个 explicit 构造函数重载(基于不同的std::function<...>类型),std::bind的返回值可以选择 (从而使调用模糊不清)

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

如果我注释掉,则代码编译!

我原本以为构造函数explicit会选择正确的重载,还是阻止两者被选中?

当然显式在我绑定的点上创建std::function

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

然而,我很困惑为什么类型扣除不起作用?

  • 如果std::bind的返回值与两个构造函数签名都不匹配,则它们为explicit的事实应该阻止两者都被选中。
  • 如果std::bind的返回值与两个构造函数签名中的一个匹配,则它们为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;
}

1 个答案:

答案 0 :(得分:4)

使构造函数explicit与必须完全匹配的参数无关!使构造函数显式化的影响意味着它不会被用于使用此构造函数隐式转换类型Bar的不同类型的对象。但是,如果您尝试使用直接初始化(即Bar)初始化Bar(x)对象,则将考虑两个构造函数。

std::bind()的结果肯定不是std::function<Signature>,即它与您的任何一个构造函数完全匹配。由于explicit的非std::function<Signature>构造函数适用于函数对象,因此两个签名都匹配:生成的绑定表达式不需要任何参数,但它可以带参数,即任何参数参数类型也不能用于区分Bar的两个构造函数中的哪一个应该匹配。即使绑定表达式需要一个参数,我也不认为它会被用来偏好一个构造函数而不是另一个构造函数。