代码之家  ›  专栏  ›  技术社区  ›  Steve Lorimer

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

  •  1
  • Steve Lorimer  · 技术社区  · 11 年前

    给定两个 explicit 构造函数重载(基于不同的 std::function<...> 类型),的返回值 std::bind 能够选择 任何一个 (从而使通话变得模糊不清)

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

    如果我注释掉其中任何一个,那么代码就会编译!

    我本想让建造师 明确的 会选择正确的过载,还是阻止两者都被选择?

    当然 明确地 创建 std::function 在我绑定作品时:

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

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

    • 如果返回值来自 std::绑定 两个构造函数签名都不匹配,事实上它们是 明确的 应防止两者都被选中。
    • 如果返回值来自 std::绑定 匹配两个构造函数签名中的一个,事实上它们是 明确的 应该导致选择正确的一个。

    这里到底发生了什么?

    完整的工作代码如下:

    #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 回复  |  直到 11 年前
        1
  •  4
  •   Dietmar Kühl    11 年前

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

    的结果 std::bind() 当然不是 std::function<Signature> ,也就是说,它与您的任何一个构造函数都不完全匹配。由于存在非- 明确的 的构造函数 std::函数<签名> 对于函数对象有效,两个签名都匹配:生成的绑定表达式不需要任何参数,但可以接受参数,即任何参数类型也不能用于区分的两个构造函数中的哪一个 酒吧 应该匹配。即使绑定表达式需要一个参数,我也不认为它会被用来更喜欢一个构造函数而不是另一个构造函数。