std :: function参数的不同重载与bind是不明确的(有时) [英] Different overloads with std::function parameters is ambiguous with bind (sometimes)

查看:236
本文介绍了std :: function参数的不同重载与bind是不明确的(有时)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个函数foo的重载,它们具有不同的std::function,当与std::bind的结果一起使用时,会导致后者的歧义问题.我不明白为什么 only 这是模棱两可的.

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类型上具有多个重载的任何函数都应具有歧义性,但这只是绑定调用的问题.然后我想:也许在处理函数类型和lambda时发生了一些不可思议的事情,它并没有处理实际的类,"但是它也可以处理那些.

en.cppreference上有一条注释,内容为[c ++ 14起]

除非参数类型为Args ...且返回类型为R的f可调用,否则此构造方法不参与重载解析.

解决方案

问题是如何允许绑定被调用.作为 cpp引用状态

如果对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>绑定

I have two overloads of a function foo which take different std::functions which results in an ambiguity issue for the latter when used with the result of a std::bind. I don't understand why only this is ambiguous.

void foo(std::function<void(int)>) {}
void foo(std::function<int()>) {}

void take_int(int) { }
int ret_int() { return 0; }

When using int() with a bind function I get an ambiguity error

foo(std::bind(ret_int)); // ERROR

With the gcc-5.1 error (and similar with 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()>) {}

However all of the following work

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{});

Looking at the std::function constructor

template< class F > 
function( F f );

it would make sense to me that any function with multiple overloads on different std::function types should have ambiguities, but it's only an issue with the call to bind. I then thought "maybe there's some magic happening to handle function types and lambdas and it doesn't deal with actual classes," but it handles those too.

There's a note on en.cppreference that says [since c++14]

This constructor does not participate in overload resolution unless f is Callable for argument types Args... and return type R

解决方案

The problem exists in how bind is allowed to be called. As cppreference states

If some of the arguments that are supplied in the call to g() are not matched by any placeholders stored in g, the unused arguments are evaluated and discarded.

In other words, you need to pass at least as many arguments as the underlying callable expects.

This means that the following is valid

int f();
auto b = std::bind(f);
b(1, 2, 3); // arguments aren't used

So saying

auto b = std::bind(ret_int)
b(1);

Works, with the 1 discarded, therefore the following is valid, and overload selection becomes ambiguous

std::function<void(int)> f = std::bind(ret_int);

The inverse is not true, however

std::function<int()> f = std::bind(take_int);

because take_int cannot be called with no arguments.

Takeaway: lambda > bind

这篇关于std :: function参数的不同重载与bind是不明确的(有时)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆