从基础类调用派生类的函数模板

时间:2017-10-31 16:28:55

标签: c++ templates inheritance types

我有ConsequenceEventEventsConsequences个类。 每个Event派生类都有Consequence个对象的列表,它触发存储在EventsConsequences对象中。如果两个Event对象属于同一类型(类),则它们必须触发相同的Consequence s。

所以在EventsConsequences课程中我有:

unordered_map<std::type_index, std::vector<Consequence*>> consequences;

template<typename Event>
void add_trigger_of(Consequence *consequence) {
    consequences[typeid(Event)].push_back(consequence);
}

template<typename Event>
void trigger_consequences_of(Event *event) {
    for (Consequence *consequence : consequences[typeid(Event)]);
        consequence->react_to(event);
}

Event课程中:

EventsConsequences* consequences;

void trigger() {
    consequences->trigger_consequences_of(this);
}

当然,我有很多EventConsequence的派生类。

我想要的是它的工作,但它没有。它总是调用

EventsConsequences::trigger_consequences_of<Event>(Event*)

但不是派生类。

我必须解决这个问题的唯一方法是使Event::trigger() virtual和每个派生类重写它

void DerivedEvent::trigger() override {
    consequences->trigger_consequences_of(this);
}

但我讨厌编写WET代码。还有其他方法吗?

2 个答案:

答案 0 :(得分:3)

使用奇怪的重复模板模式(CRTP):

template <typename Derived>
struct Base {
    void foo() {
        func(static_cast<Derived*>(this));
    }
};

struct A : Base<A> { };
struct B : Base<B> { };

int main() {
    A a;
    B b;
    a.foo();
    b.foo();
}

答案 1 :(得分:2)

您应该使用对象的动态类型的type_index而不是类型模板参数的type_index来访问地图。

consequences[typeid(*event)]

确保Event至少有一个虚拟功能。