我有一个函数foo
的两个重载,它采用不同的std::function
s,当与std::bind
的结果一起使用时,导致后者的模糊性问题。我不明白为什么只有这个含糊不清。
void foo(std::function<void(int)>) {}
void foo(std::function<int()>) {}
void take_int(int) { }
int ret_int() { return 0; }
当使用带有int()
函数的bind
时,我会出现歧义错误
foo(std::bind(ret_int)); // ERROR
出现gcc-5.1错误(和clang类似)
error: call to 'foo' is ambiguous
foo(std::bind(ret_int));
^~~
note: candidate function
void foo(std::function<void(int)>) {}
^
note: candidate function
void foo(std::function<int()>) {}
但是以下所有工作
foo(std::bind(take_int, _1));
foo(take_int);
foo(ret_int);
foo([](){ return ret_int(); });
struct TakeInt {
void operator()(int) const { }
};
struct RetInt {
int operator()() const { return 0; }
};
foo(TakeInt{});
foo(RetInt{});
看着std::function
构造函数
template< class F >
function( F f );
对我来说,任何在不同std::function
类型上具有多个重载的函数都应该有歧义,这对我来说是有意义的,但这只是对bind调用的一个问题。然后我想“也许有一些神奇的事情来处理函数类型和lambdas并且它不处理实际的类”,但它也处理它们。
有关en.cppreference的说明[自c ++ 14]
此构造函数不参与重载决策,除非f对于参数类型Args可调用并返回类型R.
问题在于如何允许调用bind。作为cppreference states
如果调用g()时提供的某些参数与存储在g中的任何占位符不匹配,则会评估并丢弃未使用的参数。
换句话说,您需要传递至少与底层callable所期望的一样多的参数。
这意味着以下内容有效
int f();
auto b = std::bind(f);
b(1, 2, 3); // arguments aren't used
所以说
auto b = std::bind(ret_int)
b(1);
工作,丢弃1
,因此以下是有效的,并且过载选择变得模糊
std::function<void(int)> f = std::bind(ret_int);
然而,反之则不然
std::function<int()> f = std::bind(take_int);
因为take_int
不能被调用而没有参数。
外卖:lambda> bind