Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模拟模板化数据成员是否合适?_C++_Templates_Observer Pattern - Fatal编程技术网

C++ 模拟模板化数据成员是否合适?

C++ 模拟模板化数据成员是否合适?,c++,templates,observer-pattern,C++,Templates,Observer Pattern,我正在尝试实现一种观察者模式的变体,它缓冲了不同的事件类型,并陷入了僵局 这就是我想要的: class Foo { /* ..... */ std::vector<Base*> buf; template<typename T> void newEvent(T ev) { /* I give the list of observers to each event. * There are bill

我正在尝试实现一种观察者模式的变体,它缓冲了不同的事件类型,并陷入了僵局

这就是我想要的:

class Foo
{
    /* ..... */
    std::vector<Base*> buf;

    template<typename T>
    void newEvent(T ev)
    {
        /* I give the list of observers to each event.
         * There are billions of events coming in for
         * each run of the application 
         */
        buf.push_back(new Event<T>(ev, &observers<T>));
    }

    /* Illegal, templated data members */
    template<typename T>
    std::vector<Observer<T>*> observers;

    template<typename T>
    void attach(Observer<T> obs)
    {
        /* Each type has its own list of observers */
        observers<T>.push_back(obs);
    }
    /* ..... */
};
class-Foo
{
/* ..... */
std::载体buf;
模板
无效新事件(ev)
{
/*我给每个活动的观察员名单。
*有数以十亿计的事件即将发生
*应用程序的每次运行
*/
buf.推回(新事件(ev和观察员));
}
/*非法的、模板化的数据成员*/
模板
向量观测器;
模板
无效附加(观察员obs)
{
/*每种类型都有自己的观察者列表*/
观察员:推回(obs);
}
/* ..... */
};
稍后刷新缓冲区时

void Foo::flush()
{
    for (Base* ev : buf) 
    {
        ev->notifyAll();
        delete ev;
    }
}

template <typename T>
class Event : public Base
{
    /* ..... */
    Event(T t, const std::vector<Observer*>& o):observers(o),payload(t){}
    void notifyAll() 
    {
        for (Observer* obs : observers)
            obs->onNotify(this->payload);
    }
};
void Foo::flush()
{
用于(基准*ev:buf)
{
ev->notifyAll();
删除电动汽车;
}
}
模板
班级活动:公共基地
{
/* ..... */
事件(T,const std::vector&o):观察者(o),有效载荷(T){}
void notifyAll()
{
用于(观察员*obs:观察员)
obs->onNotify(此->有效负载);
}
};
模板中的类型只是从外部传入的一个POD。当它打包好后,我会给它一份观察员名单。现在,我可以在Foo中手动定义每种类型的观察者向量,但我希望能够支持未定义数量的“事件”类型

我知道类的模板化数据成员是非法的,即使在c++14中有更多的支持模板化变量

继续走这条路有意义吗?最初,我在每个“事件”类型中静态地使用了“观察者”部分,但为了可测试性,我正在尝试尽可能多地去掉全局状态

我只是想把东西移到一个类模板中,但是我也遇到了麻烦

template <typename T>
class EventHandler //can't think of a good name for this demon baby
{
    public Base* create(T t); //when I create a new event, I need the observer list
    public void attach(Observer<T>);
    private std::vector<Observer<T>*> observers;
};

class Buffer
{
    /* ..... */
    EventHandler<EventType1> thing1;
    EventHandler<EventType2> thing2;
    EventHandler<EventType3> thing3;

    template<typename T>
    public newEvent(T ev) //I could just explicitly say the type here
    {
        buf.push_back(thing?.create(ev)); //how to know which one to use?
    }
};
模板
类EventHandler//想不出这个恶魔宝宝的好名字
{
public Base*create(T);//创建新事件时,需要观察者列表
公众(观察员);
私人std::病媒观察者;
};
类缓冲区
{
/* ..... */
事件处理程序1;
事件处理程序2;
事件处理程序3;
模板
public newEvent(T ev)//我可以在这里显式地说类型
{
buf.push_back(thing?.create(ev));//如何知道使用哪一个?
}
};
我从另一个角度遇到了同样的问题:/。我也想过只打开类型id,但觉得很混乱。

一种方法是使用:

类事件处理程序\u基{
公众:
虚拟~event_handler_base(){}
};
模板
类事件处理程序:公共事件处理程序{
公众:
无效句柄(ev){/*句柄事件*/}
};
上课我的特别课{
公众:
~my_special_class(){
用于(自动和p:处理程序)
删除第二页;
}
模板
无效新事件(T ev){
get_handler().handle(ev);
}
模板
事件处理程序&获取处理程序(){
静态std::type_索引ti(typeid(T));
autoit=handlers.find(ti);
if(it==handlers.end())
it=handlers.emplace(ti,newevent_handler())。首先;
返回动态_cast(*it->second);
}
std::无序的_映射处理程序;
};

如果您能找到编译时的答案,我不喜欢这种方法,但它仍然很有趣。总是喜欢编译时成本而不是运行时成本。

听起来像是一个
std::unordered_map
使用
std::type_index
作为键。@T.C.有趣的是,我写的答案和你评论时说的一模一样
class event_handler_base{
    public:
        virtual ~event_handler_base(){}
};

template<typename T>
class event_handler: public event_handler_base{
    public:
        void handle(T ev){ /* handle event */ }
};

class my_special_class{
    public:
        ~my_special_class(){
            for(auto &&p : handlers)
                delete p.second;
        }

        template<typename T>
        void new_event(T ev){
            get_handler<T>().handle(ev);
        }

        template<typename T>
        event_handler<T> &get_handler(){
            static std::type_index ti(typeid(T));
            auto it = handlers.find(ti);
            if(it == handlers.end())
                it = handlers.emplace(ti, new event_handler<T>()).first;

            return dynamic_cast<event_handler<T>&>(*it->second);
        }

        std::unordered_map<std::type_index, event_handler_base*> handlers;
};