为什么我的函数重载不如我的模板化函数重载?
Why is my function overload not preferred over my templated one?
根据这个问题的第一个答案:function template overloading,“非模板化(或“较少模板化”)重载优于模板”。
#include <iostream>
#include <string>
#include <functional>
void f1(std::string const& str) {
std::cout << "f1 " << str << "\n";
}
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 << "\n";
};
call(f1, "Hello World!");
call(f2, "Salut Monde !");
return 0;
}
据我所知,call
的第二个定义是“非模板化”的,因此当我做 call(f1, "1")
或 call(f2, "2")
.
事实并非如此,我得到以下输出:
f1 Hello World!
f2 Salut Monde !
如果我删除 call
的模板化版本,我会得到预期的输出。
为什么在这种情况下没有选择我的 call
重载而不是第一个重载?
lambda f2
的类型不是 std::function<void(std::string const&)>
,而是 is a compiler generated type。因此,模板化 call
提供了更好的匹配。
f1
或 f2
都不是 std::function<...>
类型。因此模板是一个更好的匹配。
如果您使用(例如)
std::function<void(std::string const&)> f3(f2);
call(f3, "Salut Monde !");
您的电话已被使用。
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 !");
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 +
当你用特定类型(函数的第二个参数)重载函数时,在这种情况下,当你用特定参数调用函数时,模板函数将不会调用,因为你已经为特定类型编写了函数。除了你的模板函数调用的特定类型,它是编译器作业select特定类型参数,然后是模板函数
根据这个问题的第一个答案:function template overloading,“非模板化(或“较少模板化”)重载优于模板”。
#include <iostream>
#include <string>
#include <functional>
void f1(std::string const& str) {
std::cout << "f1 " << str << "\n";
}
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 << "\n";
};
call(f1, "Hello World!");
call(f2, "Salut Monde !");
return 0;
}
据我所知,call
的第二个定义是“非模板化”的,因此当我做 call(f1, "1")
或 call(f2, "2")
.
事实并非如此,我得到以下输出:
f1 Hello World!
f2 Salut Monde !
如果我删除 call
的模板化版本,我会得到预期的输出。
为什么在这种情况下没有选择我的 call
重载而不是第一个重载?
lambda f2
的类型不是 std::function<void(std::string const&)>
,而是 is a compiler generated type。因此,模板化 call
提供了更好的匹配。
f1
或 f2
都不是 std::function<...>
类型。因此模板是一个更好的匹配。
如果您使用(例如)
std::function<void(std::string const&)> f3(f2);
call(f3, "Salut Monde !");
您的电话已被使用。
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 !");
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 +
当你用特定类型(函数的第二个参数)重载函数时,在这种情况下,当你用特定参数调用函数时,模板函数将不会调用,因为你已经为特定类型编写了函数。除了你的模板函数调用的特定类型,它是编译器作业select特定类型参数,然后是模板函数