C++ 获取lambda的函数原型
我正在创建一个通用的C++ <代码>事件发射器< />代码>。它基于:C++ 获取lambda的函数原型,c++,templates,C++,Templates,我正在创建一个通用的C++ 事件发射器< />代码>。它基于: 模板 int16\u t EventEmitter::addListener(uint32\u t eventId,std::函数cb) { ... } 模板 void EventEmitter::emit(uint32\u t eventId,Args…Args) { ... } 它按预期工作(我可以用不同的原型注册侦听器)。例如: autohandler=[](int n){…}; addListener(0,std::fun
模板
int16\u t EventEmitter::addListener(uint32\u t eventId,std::函数cb)
{
...
}
模板
void EventEmitter::emit(uint32\u t eventId,Args…Args)
{
...
}
它按预期工作(我可以用不同的原型注册侦听器)。例如:
autohandler=[](int n){…};
addListener(0,std::function(handler));
但我不想每次添加一个监听器原型时都麻烦地将整个监听器原型输入到std::function
,然后我决定创建一个宏:
#define STDFUNC(fn) std::function<decltype(fn)>(fn)
定义STDFUNC(fn)std::function(fn)
问题是当我尝试将其用于lambdas时:decltype(handler)
不是void(int)
,而是class lambda[]void(int n)->void
,生成错误:
(Clang3.7.1)->错误:未定义模板的隐式实例化
'std::_Get_function_impl这是一个为任意lambda生成函数对象的小程序:
#include <functional>
#include <type_traits>
template <typename R, typename... A>
class build_func_type
{
public:
using type = ::std::function<R(A...)>;
};
template <typename R, typename C, typename... A>
typename build_func_type<R, A...>::type mem_func_to_func( R(C::*)(A...) const)
{
return nullptr;
}
template <typename T>
decltype(mem_func_to_func(&T::operator ())) lambda_to_fp(T le)
{
using func_t = decltype(mem_func_to_func(&T::operator ()));
return func_t{le};
}
int test()
{
auto foo = [](int x) -> int { return x * x; };
auto ftype = lambda_to_fp(foo);
return ftype(5);
}
#包括
#包括
模板
类生成函数类型
{
公众:
使用type=::std::函数;
};
模板
typename build_func_type::type mem_func_to_func(R(C::*)(A..)const)
{
返回空ptr;
}
模板
decltype(mem_func_to_func(&T::operator()))lambda_to_fp(tle)
{
使用func_t=decltype(mem_func_to_func(&t::operator());
返回函数{le};
}
int测试()
{
autofoo=[](intx)->int{returnx*x;};
自动ftype=λ到λfp(foo);
返回ftype(5);
}
它使用函数mem_func\u to_func
自动推断lambda的运算符()
的类型。然后,它使用build\u func\u type
模板从lambda的操作符()
类型的组件中构建函数类型。我可能在build\u func\u type
中使用了一个构造函数,并依赖于C++17构造函数类型推导
然后,
lambda_to_fp
将获取一个lambda,使用mem_func_to_func
从指向lambda的运算符()
成员函数的指针创建一个指向适当函数类型的指针。然后它创建一个适当类型的::std::function
,从函数指针的类型构造该类型。然后它用lambda初始化并返回它。为什么要首先添加具有不同签名的侦听器?@n.m.每个事件都有自己的参数,emit方法是:template void emit(uint32\t eventId,Args…Args)
这是一个多么有趣的问题。你知道,lambda类型必须声明一个操作符()
。你要的是那个的签名。此外,使用预处理器宏是有害的,如果可能的话,应该避免使用它。在STDFUNC的例子中,您可以很容易地定义一个模板函数来实现这一点,您应该这样做。@Omnifarious完全正确,但据我所知,lambda对象是由语言“抽象”的。关于宏,我会按照你的建议定义一个模板,只要我弄明白它。谢谢。你的问题和这个不同吗?在lambda_to_fp
中,是否可以不使用自动
返回类型?似乎Clang3.7.1(至少在默认设置下)无法编译它,因为它是C++14扩展。@karliwson-我不确定。这将是一件棘手的事情。您可以给出clang-std=c++14.:-)我会考虑一下如何解决这个问题。你基本上明白这是怎么回事吗?一般来说,我是说,有点。您将获得lambda的操作符()
,并使用一些魔法提取其原型,并使用它创建一个std::function
。顺便说一句,-std=c++14
在Clang 3.7.1中不可用(我正在使用LLVM for Windows)。@karliwson-在那里,我修复了它。lambda函数的操作符()
的地址类型将是R(c::*)(A…)const
其中R是返回类型,c是lambda本身的类型,A。。。是所有参数类型的列表。诀窍是将其转换为::std::function
类型。它必须使用函数来完成,因为编译器只会推导函数的模板参数。在C++17中,编译器将推导构造函数的模板参数,但您甚至不需要C++14.:-)
#define STDFUNC(fn) std::function<decltype(fn)>(fn)
#include <functional>
#include <type_traits>
template <typename R, typename... A>
class build_func_type
{
public:
using type = ::std::function<R(A...)>;
};
template <typename R, typename C, typename... A>
typename build_func_type<R, A...>::type mem_func_to_func( R(C::*)(A...) const)
{
return nullptr;
}
template <typename T>
decltype(mem_func_to_func(&T::operator ())) lambda_to_fp(T le)
{
using func_t = decltype(mem_func_to_func(&T::operator ()));
return func_t{le};
}
int test()
{
auto foo = [](int x) -> int { return x * x; };
auto ftype = lambda_to_fp(foo);
return ftype(5);
}