为什么第二个例子不起作用?有没有办法让第二个例子工作,同时仍然将lambda或函数类型转换为一个媒介,以便稍后引用?
// Types I'm using
typedef void (*ANY_FUNC)(...);
typedef void (*VOID_FUNC)();
此作品
void call_void( VOID_FUNC func) {
((ANY_FUNC)func)();
};
// ...
call_void([]() { /* do something */ });
这不是
template <typename fn>
void call_any( fn func ) {
((ANY_FUNC)func)();
};
// ...
call_any([]() { /* do something */ });
请忽略这样一个事实,即您永远不需要使用第二个示例现在的样子。它仅用于演示(相对代码)。
这两个示例都使用函数指针而不是lambdas。
答案 0 :(得分:2)
As long as you are declaring a template you can just use the incoming function object。此外,您应该将函数参数声明为引用而不是按值:
template <typename fn>
void call_any(fn&& func) {
func();
};
如果你想用参数调用函数,你可以这样做:
template <typename fn, typename... Args>
void call_any_many(fn&& func, Args&&... args) {
func(std::forward<Args>(args)...);
};
用法示例:
int main ()
{
call_void([]() { std::cout << "Hello, void World!" << std::endl; });
call_any([]() { std::cout << "Hello, any World!" << std::endl; });
call_any_many([](int x) { std::cout << "Hello, any many World-" << x << "!" << std::endl; }, 1234);
return 0;
}
但如果您打算存储一些函数指针而不是直接调用它们,我建议您使用std::function
标题中的<functional>
。您可以在此处查看一些信息和示例:http://en.cppreference.com/w/cpp/utility/functional/function
例如:
#include <iostream>
#include <functional>
int main ()
{
std::function<void()> anyf = []() { std::cout << "Hello, any World!" << std::endl; };
std::function<void(int)> intf = [](int x) { std::cout << "Hello, any many World-" << x << "!" << std::endl; };
anyf();
intf(1234);
return 0;
}
答案 1 :(得分:0)
我不认为他们中的任何一个真的有效,除非是偶然的某些编译器。
与lambda的区别在于它可以转换为函数指针,但它不是一个。模板版本会发现此差异,fn
不会推断为VOID_FUNC
。
答案 2 :(得分:0)
Lambdas可以隐式转换为函数指针(但只有当它们没有捕获任何东西时),所以只需将call_any的参数更改为函数指针:
void call_any(ANY_FUNC func)
{
(*func)();
}
您需要使用适当类型的lambda调用它:
call_any([](...) { /* ... */ });
但是可变长度的参数列表(也称为varargs)很糟糕,因为它们是非类型安全的,因为它们可以获得。与函数指针相同:它们是非面向对象的。您应该考虑一种替代机制,可能涉及可变参数模板和多态(虚拟方法)
答案 3 :(得分:0)
第一个是将lambda转换为具有相应参数和返回类型的函数指针,然后将其转换为vararg函数,而第二个尝试将lambda直接转换为vararg函数(即没有相应参数的函数)类型)。
第一个示例中的两个转换是允许*,但第二个中的单个转换不是。
* 请注意,用于在函数指针类型之间转换的强制转换符号最终像reinterpret_cast
一样工作,它表示:“函数指针可以显式转换为函数指针通过指向函数类型(8.3.5)的函数调用函数的效果与函数定义中使用的类型不同是未定义的。“因此,第一个示例代码具有未定义的行为。