当前位置: 首页 > 知识库问答 >
问题:

std::函数参数的不同重载与bind不明确(有时)

闻人嘉颖
2023-03-14

我有两个函数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; }

将< code>int()与< code>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以来]

此构造函数不参与重载解析,除非f对于参数类型Args是可调用的...和返回类型R

共有1个答案

楮自珍
2023-03-14

问题存在于如何允许调用绑定。正如cppreference所说

如果调用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

 类似资料:
  • 假设我们有以下简单的代码: 这段代码使用clang编译并打印“T”,但使用gcc我们有以下错误: 我的问题是哪个编译器有bug,gcc还是叮当声?

  • 请考虑以下人为的代码段: 如果第二个重载被更改为采用至少2种类型的包而不是至少一种类型的包时,gcc和clang都接受这两个调用: 如果未推导出的模板参数被移动到推导出的模板参数,则: 我希望每个版本的所有调用都可以。上面代码示例的预期结果是什么?

  • 问题内容: 使用Java 8,我得到以下代码的编译器错误: 因此,基本上,编译器会说“我知道您会返回,但您不应该返回,如果不知道,我不确定使用哪种方法”,而不是“哦,您将返回,您必须指代该方法的版本” ?如何产生这种混乱? 我知道(如果它们有一个通用的Type),但事实并非如此。 我确实知道如何解决它;如果我这样做很好 但我很好奇是什么原因造成的。 问题答案: 为了清楚起见,可以对此进行一些简化:

  • 我在尝试用std::function和std::bind绑定方法时遇到了一个问题。 在我的通信服务类中: CommunicationService::ManageGetRequest签名: BindGET签名: 请求函数类型定义: BindGET上的错误: 错误C2664:“void RESTServer::BindGET(RequestFunction)”:无法从“std::\u Binder”

  • 在下面的代码中,对< code>foo的第一次调用不明确,因此无法编译。 第二个在lambda前面添加了< code> ,解析为函数指针重载。 符号在这里做什么?