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;
};