【问题标题】:Why can't the compiler resolve an overload of a std::function parameter? [duplicate]为什么编译器不能解决 std::function 参数的重载? [复制]
【发布时间】:2015-04-23 08:40:55
【问题描述】:

观察下面的例子:

#include <iostream>
#include <functional>
#include <cstdlib>

void Print_Wrapper(std::function<void(int)> function);
void Print(int param);

int main(){

  Print_Wrapper(Print);

  return EXIT_SUCCESS;
}

void Print_Wrapper(std::function<void(int)> function){
  int i = 5;
  function(i);
}
void Print(int param){
  std::cout << param << std::endl;
}

这可以正常工作,并打印5


现在看一下添加了重载函数的相同示例:

#include <iostream>
#include <functional>
#include <cstdlib>

void Print_Wrapper(std::function<void(int)> function);
void Print(int param);
void Print(float param);

int main(){

  Print_Wrapper(Print);

  return EXIT_SUCCESS;
}

void Print_Wrapper(std::function<void(int)> function){
  int i = 5;
  function(i);
}
void Print(int param){
  std::cout << param << std::endl;
}
void Print(float param){
  std::cout << param << std::endl;
}

这会产生以下编译器错误:

main.cpp:11:22:错误:无法解析重载函数“打印” 基于转换为“std::function”类型
Print_Wrapper(打印);

能否解释一下为什么编译器无法解决重载问题?
Print_Wrapper 只需要一个 int 函数——甚至不应该考虑 float 函数。


另外,我应该怎么做才能解决这个问题?

我记得如果遗漏了typename 或其他内容,就会出现类似的问题,但那需要我将Print_Wrapper 设为模板。
Print_Wrapper 需要是函数模板吗?

我想我已经习惯了与此类似的功能,它确实有效。例如:

#include <iostream>
#include <vector>
#include <cstdlib>

void Print_Wrapper(std::vector<int> param);
void Print(std::vector<int> param);
void Print(std::vector<float> param);

int main(){

  std::vector<int> vi{1,2,3};
  std::vector<float> vf{1.0,2.0,3.0};

  Print(vi); //prints int
  Print(vf); //prints float

  Print_Wrapper(vi); //prints int (no overload issue)
  Print_Wrapper(vf); //compiler error (as expected)

  return EXIT_SUCCESS;
}

void Print_Wrapper(std::vector<int> param){
  Print(param);
  return;
}
void Print(std::vector<int> param){
  std::cout << "int" << std::endl;
}
void Print(std::vector<float> param){
  std::cout << "float" << std::endl;
}

所以我认为问题出在实际 C++ 函数的查找规则中,因为此示例仅使用类型。想法?

【问题讨论】:

  • std::vector 无法转换为 std::vector 但 int 可以隐式转换为 float
  • static_cast&lt;void(*)(int)&gt;(&amp;Print)
  • @Sarang 好的,如果我使用无法隐式转换的完全不同的类型,我认为问题仍然存在。

标签: c++ templates c++11 std overloading


【解决方案1】:

在 C++11 中,std::function 的构造函数可以采用任何可调用对象,即使该对象格式不正确且无法调用该对象。在 C++14 中,重载决议是固定的,但两个函数都可以用 int 调用,所以它们都是有效的候选者。

您需要明确请求正确的功能:

Print_Wrapper(static_cast<void(*)(int)>(Print))

【讨论】:

  • 你是说我的例子适用于 C++14 吗?
  • 此解决方案有效。没有演员表,它仍然无法在 C++14 中工作。
  • 嗯,最初我虽然它应该在 C++14 中工作,但在仔细检查 LWG 2132 之后,即使在 C++14 中也存在问题,因为两者都可以用 int 调用。
  • 据我所知,没有简单的方法可以说“此转换是用户定义的首选转换,而不是其他转换”。也许有一个未使用的可变参数包?看起来很脏。
  • 可以通过声明Print_Wrapper的重载版本来选择非转换函数:void Print_Wrapper(void(*func)(int)) { Print_Wrapper(std::function&lt;void(int)&gt;(func)); }
【解决方案2】:

您可以将这两个函数都分配给std::function&lt;void(int)&gt;,因为这两个函数都可以使用 int 调用。

使用 int 版本强制选择正确的重载:Print_Wrapper(static_cast&lt;void(*)(int)&gt;(Print));

【讨论】:

  • 我的问题是否与整数被隐式转换为浮点数有关,或者任何两种类型都会发生这种情况?
猜你喜欢
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
  • 2021-03-11
相关资源
最近更新 更多