std::function & std::forward 可变参数模板
std::function & std::forward with variadic templates
最近我在阅读有关可变参数模板的内容,并根据我在网上看到的一个示例尝试实现一个基本的事件系统。到目前为止它似乎工作正常但我试图更进一步并允许将 N 个参数传递给事件处理函数/回调,不幸的是我得到的构建错误如下,我不确定我做错了什么。我查看了类似的源代码,但仍然无法找出问题所在。
D:\Development\lab\c-cpp\EventEmitter3\src\main.cpp:30:68: error: parameter packs not expanded with '...':
return std::any_cast<std::function<R(Args)>>(eventCallback)(std::forward<Args>(args)...);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
D:\Development\lab\c-cpp\EventEmitter3\src\main.cpp:30:68: note: 'Args'
Build finished with error(s).
这是我目前的情况,如果您删除 ...
事件系统对于 main
.
中的 2 个注册事件工作正常
#include <any>
#include <string>
#include <iostream>
#include <functional>
#include <unordered_map>
class EventEmitter
{
private:
std::unordered_map<std::string, std::any> events;
public:
EventEmitter() {}
void on(const std::string &eventName, const std::any &eventCallback)
{
events[eventName] = eventCallback;
}
template <typename R>
R emit(const std::string &eventName)
{
const std::any &eventCallback = events[eventName];
return std::any_cast<std::function<R(void)>>(eventCallback)();
}
template <typename R, typename... Args>
R emit(const std::string &eventName, Args &&...args)
{
const std::any &eventCallback = events[eventName];
return std::any_cast<std::function<R(Args)>>(eventCallback)(std::forward<Args>(args)...);
}
virtual ~EventEmitter() {}
};
int fun1()
{
std::cout << "fun1" << std::endl;
return 1;
}
double fun2(int i)
{
std::cout << "fun2" << std::endl;
return double(i);
}
double fun3(int x, int y)
{
std::cout << "fun3" << std::endl;
return double(x + y);
}
int main(int argc, char *argv[])
{
EventEmitter e;
e.on("fun1", std::function<int(void)>(fun1));
e.on("fun2", std::function<double(int)>(fun2));
e.emit<int>("fun1");
e.emit<double, int>("fun2", 1);
// Variadic would have been handy right here I guess?
// e.on("fun3", std::function<double(int, int)>(fun3));
// e.emit<double, int>("fun3", 1, 2);
return 0;
}
我该如何解决这个问题?
嗯,你需要扩展它。
return std::any_cast<std::function<R(Args...)>>(eventCallback)(std::forward<Args>(args)...);
^^^^^^^
最近我在阅读有关可变参数模板的内容,并根据我在网上看到的一个示例尝试实现一个基本的事件系统。到目前为止它似乎工作正常但我试图更进一步并允许将 N 个参数传递给事件处理函数/回调,不幸的是我得到的构建错误如下,我不确定我做错了什么。我查看了类似的源代码,但仍然无法找出问题所在。
D:\Development\lab\c-cpp\EventEmitter3\src\main.cpp:30:68: error: parameter packs not expanded with '...':
return std::any_cast<std::function<R(Args)>>(eventCallback)(std::forward<Args>(args)...);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
D:\Development\lab\c-cpp\EventEmitter3\src\main.cpp:30:68: note: 'Args'
Build finished with error(s).
这是我目前的情况,如果您删除 ...
事件系统对于 main
.
#include <any>
#include <string>
#include <iostream>
#include <functional>
#include <unordered_map>
class EventEmitter
{
private:
std::unordered_map<std::string, std::any> events;
public:
EventEmitter() {}
void on(const std::string &eventName, const std::any &eventCallback)
{
events[eventName] = eventCallback;
}
template <typename R>
R emit(const std::string &eventName)
{
const std::any &eventCallback = events[eventName];
return std::any_cast<std::function<R(void)>>(eventCallback)();
}
template <typename R, typename... Args>
R emit(const std::string &eventName, Args &&...args)
{
const std::any &eventCallback = events[eventName];
return std::any_cast<std::function<R(Args)>>(eventCallback)(std::forward<Args>(args)...);
}
virtual ~EventEmitter() {}
};
int fun1()
{
std::cout << "fun1" << std::endl;
return 1;
}
double fun2(int i)
{
std::cout << "fun2" << std::endl;
return double(i);
}
double fun3(int x, int y)
{
std::cout << "fun3" << std::endl;
return double(x + y);
}
int main(int argc, char *argv[])
{
EventEmitter e;
e.on("fun1", std::function<int(void)>(fun1));
e.on("fun2", std::function<double(int)>(fun2));
e.emit<int>("fun1");
e.emit<double, int>("fun2", 1);
// Variadic would have been handy right here I guess?
// e.on("fun3", std::function<double(int, int)>(fun3));
// e.emit<double, int>("fun3", 1, 2);
return 0;
}
我该如何解决这个问题?
嗯,你需要扩展它。
return std::any_cast<std::function<R(Args...)>>(eventCallback)(std::forward<Args>(args)...);
^^^^^^^