根据此问题的第一个答案:function template overloading,“非模板化(或”模板化程度较低“)重载优先于模板”。
#include <iostream>
#include <string>
#include <functional>
void f1 (std::string const& str) {
std::cout << "f1 " << str << std::endl;
}
template <typename Callback, typename... InputArgs>
void call (Callback callback, InputArgs ...args) {
callback(args...);
}
void call (std::function<void(std::string const&)> callback, const char *str) {
std::cout << "custom call: ";
callback(str);
}
int main() {
auto f2 = [](std::string const& str) -> void {
std::cout << "f2 " << str << std::endl;
};
call(f1, "Hello World!");
call(f2, "Salut Monde !");
return 0;
}
根据我的理解,call
的第二个定义是“非模板化”,因此当我call(f1, "1")
或{{1}时,应该选择第一个定义。 }。
情况并非如此,我得到以下输出:
call(f2, "2")
如果删除f1 Hello World!
f2 Salut Monde !
的模板版本,我会得到预期的输出。
为什么call
的超载在这种情况下没有超过第一个?
答案 0 :(得分:6)
f1
和f2
的类型不是std::function
,需要用户定义转换,因此会选择模板版本。
如果你确实提供了一个与函数指针完全匹配的函数call
,例如;
void call (void(*callback)(std::string const&), const char *str)
将为f1
选择它。
注意:在lambda上添加了一元+
,在这种情况下你也可以获得一个函数指针(你的捕获列表为空)......
auto f2 = +[](std::string const& str) -> void
// ^ unary +
答案 1 :(得分:3)
lambda f2
的类型不是std::function<void(std::string const&)>
,而是is a compiler generated type。因此,模板call
提供了更好的匹配。
答案 2 :(得分:3)
f1
或f2
都不属于std::function<...>
类型。因此模板更匹配。
如果您使用(例如)
std::function<void(std::string const&)> f3(f2);
call(f3, "Salut Monde !");
您的通话已被使用。
答案 3 :(得分:1)
std::function可以从函数或lambda表达式构造,但其类型不与函数或lambda表达式相同。这些论点完全不符合:
call(f1, "Hello World!");
call(f2, "Salut Monde !");
您可以使用强制转换来完成它:
call(static_cast<std::function<void(std::string const&)>>(f1), "Hello World!");
call(static_cast<std::function<void(std::string const&)>>(f2), "Salut Monde !");
答案 4 :(得分:-1)
当您使用特定类型(函数的第二个参数)重载函数时,在这种情况下,当您使用特定参数调用函数时,模板函数将不会调用,因为您已经为特定类型编写了函数。除了模板函数调用的特定类型之外,首先选择特定类型参数的编译器作业然后是模板函数