【问题标题】:Different overloads with std::function parameters is ambiguous with bind (sometimes)带有 std::function 参数的不同重载与 bind 不明确(有时)
【发布时间】:2015-07-01 22:45:50
【问题描述】:

我有两个函数 foo 的重载,它们采用不同的 std::functions,当与 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 类型上具有多个重载的任何函数都应该有歧义,但这只是绑定调用的问题。然后我想“也许在处理函数类型和 lambdas 时发生了一些神奇的事情,它不处理实际的类”,但它也处理了这些。

在 en.cppreference 上有一个注释,上面写着 [since c++14]

除非 f 对于参数类型 Args... 和返回类型 R 是 Callable 的,否则此构造函数不参与重载决议

【问题讨论】:

标签: c++ overloading c++14 std-function stdbind


【解决方案1】:

问题在于如何允许调用bind。作为cppreference states

如果在调用 g() 时提供的某些参数与存储在 g 中的任何占位符都不匹配,则评估并丢弃未使用的参数。

换句话说,您需要传递至少与底层可调用对象期望的一样多的参数。

这意味着以下是有效的

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 > 绑定

【讨论】:

  • 标准中哪里说多余的参数被丢弃了?我好像没找到。
  • @0x499602D2 我不知道我在这个上停止了 cppreference。我现在也在看
  • 我想我找到了它,虽然它看起来有点牵强:N4431 20.9.2/4。 A forwarding call wrapper is a call wrapper that can be called with an arbitrary argument list and delivers the arguments to the wrapped callable object as references。注释甚至使用了可变参数。
猜你喜欢
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-22
  • 2011-09-13
  • 1970-01-01
相关资源
最近更新 更多