【发布时间】:2017-11-25 05:44:39
【问题描述】:
我正在创建一个通用 C++ EventEmitter。它基于Node.js EventEmitter:
template <typename ...Args>
int16_t EventEmitter::addListener(uint32_t eventId, std::function<void(Args...)> cb)
{
...
}
template <typename... Args>
void EventEmitter::emit(uint32_t eventId, Args... args)
{
...
}
它按预期工作(我可以使用不同的原型注册侦听器)。例如:
auto handler = [](int n) { ... };
listener.addListener(0, std::function<void(int)>(handler));
但我不想每次添加一个(有些参数超过5个)时都将整个监听器原型输入std::function<...>,然后我决定创建一个宏:
#define STDFUNC(fn) std::function<decltype(fn)>(fn)
问题是当我尝试将它与 lambdas 一起使用时:decltype(handler) 不是void(int),而是class lambda []void (int n)->void,会产生错误:
(Clang 3.7.1) -> 错误:未定义模板的隐式实例化 'std::_Get_function_impl
我正在挠头以获得没有 lambda 限定符的原型,但我被困住了。任何帮助将不胜感激。
【问题讨论】:
-
你为什么要添加具有不同签名的监听器?
-
@n.m.每个事件都有自己的参数,emit方法是:
template <typename... Args> void emit(uint32_t eventId, Args... args) -
多么有趣的问题。你知道,lambda 类型必须声明一个
operator ()。你想要的是那个签名。此外,使用预处理器宏是邪恶的,如果可能的话,你应该避免它。在 STDFUNC 的情况下,您可以轻松定义一个模板函数来执行此操作,并且您应该这样做。 -
@Omnifarious 完全正确,但据我所知,lambda 对象被语言“抽象”了。关于宏,我会按照你的建议定义一个模板,一旦我弄清楚了。谢谢。
-
你的问题和这个不同吗? stackoverflow.com/questions/11893141/…