我正在尝试创建一个模板函数,该函数将函数作为参数,参数函数具有模板推导的参数。
示例时间:
这是一个接受固定函数类型并且可以工作的函数
void func_a(void(*func)(int)) {
func(1);
}
int main() {
auto f = [](int x) -> void { printf("%i\n", x); };
func_a(f);
return 0;
}
这是我想要做的,扩展第一个例子(这不会编译)
template <typename... T>
void func_b(void(*func)(T...)) {
func(1);
}
int main() {
auto f = [](int x) -> void { printf("%i\n", x); };
func_b(f); // neither of
func_b<int>(f); // these work
return 0;
}
理想情况下,我希望func_b
同时接受常规函数和func_a
之类的lambda函数,但使用模板魔法。
答案 0 :(得分:7)
不幸的是,模板推导对隐式转换不起作用。但是,您可以将lambda显式转换为函数指针类型。最简单但有点令人困惑的方法是应用一元+运算符:
func_b(+f);
或者您可以使用更直观,但也更详细和干扰DRY的演员操作:
func_b(static_cast<void(*)(int)>(f));
但也许,您可能只想接受任何可调用类型,而不仅仅是函数指针:
template <class Fun>
void func_c(Fun&& func) {
func(1);
}
这对lambda很好用。不涉及转换。
func_c(f);
它还可用于捕获lambdas(无法转换为函数指针),std::function
和函数对象,例如<functional>
中定义的函数对象。
答案 1 :(得分:3)
这里有一些有用的选项:
#include <functional>
template <typename T>
void func_b(T&& func) {
func(1);
}
template <typename... T>
void func_c(std::function<void(T...)> func) {
func(1);
}
template <typename... T>
void func_d1(std::function<void(T...)> func) {
func(1);
}
template<typename... Params>
using fun = std::function<void(Params...)>;
template <typename T, typename... P>
void func_d(T& func) {
func_d1(fun<P...>(func));
}
int main() {
auto f = [](int x) { printf("%i\n", x); };
func_b(f);
func_b(std::function<void(int)>(f));
func_c(std::function<void(int)>(f));
func_d<decltype(f),int>(f);
return 0;
}
问题是:lambda 不是函数指针或std::function
- object。
func_b
使用完美转发,因此T
将是lambda的类型而不是std::function
对象。
func_c
。您不应该将lambda转换为c风格的函数指针。 std::function
对象能够执行此转换,但只能显式(按设计),因此您需要显式转换它们。
func_d
(和func_d1
)结合其他方面。虽然它需要一个额外的模板参数,但它会转发lambda并明确地生成一个std::function
- 对象。