为什么编译器无法解析 std::function 参数的重载?

Why can't the compiler resolve an overload of a std::function parameter?

观察以下示例:

#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: error: cannot resolve overloaded function ‘Print’ based on conversion to type ‘std::function’
Print_Wrapper(Print);

能否解释一下为什么编译器无法解析重载?
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::function<void(int)>,因为它们都可以用 int 调用。

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

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

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

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