我注意到lambdas使用函数指针以及使用function
的专用g++
类型。
#include <functional>
typedef int(*fptr)(int, int);
int apply_p(fptr f, int a, int b) {
return f(a, b);
}
int apply_f(std::function<int(int, int)> f, int a, int b) {
return f(a, b);
}
void example() {
auto add = [](int a, int b) -> int {
return a + b;
};
apply_p(add, 2, 3); // doesn't give an error like I'd expect it to
apply_f(add, 2, 3);
}
我的问题是:哪些是最惯用的?使用一个而不是另一个有什么危险和/或好处?
答案 0 :(得分:10)
我注意到lambdas都使用函数指针和专用的
function
类型
如果lambda没有捕获任何东西,那么它可以衰减为函数指针。
使用哪一种最惯用?
都不是。如果要存储任意可调用对象,请使用function
。如果您只想创建并使用它,请保持通用:
template <typename Function>
int apply(Function && f, int a, int b) {
return f(a,b);
}
您可以更进一步,使返回和参数类型通用;我将此作为练习。
使用一个而不是另一个有什么危险和/或好处?
函数指针版本仅适用于(非成员或静态)函数和非捕获lambdas,并且不允许传递任何状态;只有函数本身及其参数。 function
类型可以包含任何可调用的对象类型,有或没有状态,因此通常更有用。但是,这有一个运行时成本:隐藏包装类型,调用它将涉及虚函数调用(或类似);并且可能需要动态内存分配来保存大型类型。
答案 1 :(得分:4)
我想说(C ++ 14)
template <class Functor, class... Args>
decltype(auto) apply_functor(Functor&& f, Args&&... args) {
return std::forward<Functor>(f)(std::forward<Args>(args)...);
}
或C ++ 11:
template <class Functor, class... Args>
auto apply_functor(Functor&& f, Args&&... args) ->decltype(std::forward<Functor>(f)(std::forward<Args>(args)...)) {
return std::forward<Functor>(f)(std::forward<Args>(args)...);
}
答案 2 :(得分:2)
如果有疑问,请选择std::function
:
语法更简单,与其他类型一致,例如
typedef std::function<int (int, int)> MyAddFunction;
和
typedef int (*MyAddFunction)( int, int );
它更通用(它实际上可以采用lambda或普通C函数或仿函数)
它更安全类型
apply_p(0, 0, 0); // probably crashes at runtime, dereferences null pointer
apply_f(0, 0, 0); // doesn't even compile