1

给定两个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)));

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

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

1 回答 1

4

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

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

于 2013-09-22T00:53:48.427 回答