C++ C++;:使用void作为模板参数
我有一个最小的类来表示客户端可以订阅的事件。C++ C++;:使用void作为模板参数,c++,c++11,templates,callback,template-meta-programming,C++,C++11,Templates,Callback,Template Meta Programming,我有一个最小的类来表示客户端可以订阅的事件。 该事件可以具有关联的数据类型,因此当发布服务器触发该事件时,该类型的参数将传递给客户端的回调: 模板 班级活动 { 公众: 事件(回调c):mCallback(c){} 无效触发器(常量参数和参数){ mCallback(arg); } 私人: 回调mCallback; }; 现在,我可以创建一个事件或任何其他具体类型,但对我来说,允许“空”事件也非常重要,因为它没有与之关联的数据:事件 但遗憾的是,这不起作用: 静态void FooVoid(){
该事件可以具有关联的数据类型,因此当发布服务器触发该事件时,该类型的参数将传递给客户端的回调:
模板
班级活动
{
公众:
事件(回调c):mCallback(c){}
无效触发器(常量参数和参数){
mCallback(arg);
}
私人:
回调mCallback;
};
现在,我可以创建一个事件
或任何其他具体类型,但对我来说,允许“空”事件也非常重要,因为它没有与之关联的数据:事件
但遗憾的是,这不起作用:
静态void FooVoid(){
cout解决此问题的最快方法是使用(在C++11中添加的)用于模板参数而不是单个类型,并使用空参数包而不是void
。参数包可以均匀地保存任意数量的类型,包括0和1。然后可以使用它生成正确的类型和成员函数。基本上,您只需在的每次使用附近正确添加…
rg
():
请注意,此解决方案需要Event
而不是Event
。您可以通过为Event
添加使用Event
()的简短专门化来解决此问题:
模板
班级活动:公共活动
{
//继承构造函数
使用Event::Event;
};
回调是否可自定义?您需要为void专门化类模板。我认为这应该与可变模板一起工作。@tkausl除了为void完全复制粘贴之外,还有其他方法吗?@Jarod42它不可自定义,但直接取决于Arg,这是一个模板参数。可能是静态\u断言(sizeof…(Args)<2,“!”;
模拟操作限制。
#include <functional>
#include <iostream>
template<typename ... Arg>
class Event
{
public:
using Callback = std::function<void(const Arg&...)>;
Event(Callback c) : mCallback(c){}
void Trigger(const Arg& ... arg) {
mCallback(arg...);
}
private:
Callback mCallback;
};
static void FooVoid() {
std::cout << "Look ma, no args!" << std::endl;
}
static void FooInt(int a) {
std::cout << "int arg " << a << std::endl;
}
int main()
{
/* Compiles */
Event<int> eInt(&FooInt);
eInt.Trigger(42);
Event<> eVoid(&FooVoid);
eVoid.Trigger();
return 0;
}
template<typename ... Arg>
class Event
{
public:
using Callback = std::function<void(const Arg&...)>;
static_assert(sizeof...(Arg) <= 1, "Too many arguments");
Event(Callback c) : mCallback(c){}
void Trigger(const Arg& ... arg) {
mCallback(arg...);
}
private:
Callback mCallback;
};
template<>
class Event<void> : public Event<>
{
// Inherit constructors
using Event<>::Event;
};