Реализовать их в TaggedObserver
(указать явную специализацию в случае необходимости), в качестве примера:
class Observer {
public:
virtual void Observe(Parameter p) = 0;
};
template<size_t Tag>
class TaggedObserver : public Observer {
public:
void Observe(Parameter p) override { }
};
template<std::size_t... I>
class Thing : public TaggedObserver<I>... {
public:
Thing(): TaggedObserver<I>{}... {}
template<std::size_t N>
void Observe(Parameter p) {
TaggedObserver<N>::Observe(p);
}
};
Тогда, вы можете специализировать Thing
как Thing<0, 1>
и вызвать правильную функцию, используя thing.Observe<1>(p)
.
EDIT
Цель этого редактирования, чтобы показать новый пример кода, который более или менее один выше, даже если слегка изменен.
Надеюсь, это поможет OP. Основная идея - объединить идиому CRTP, виртуальные методы и наследование.
class Observer {
public:
virtual void Observe(Parameter p) = 0;
};
template<template T, size_t Tag>
class TaggedObserver : public Observer {
public:
void Observe(Parameter p) override {
T *t = static_cast<T*>(this);
// Now use whatever you want from T, that is Thing in this example
}
};
template<std::size_t... I>
class Thing : public TaggedObserver<Thing<I...>, I>... {
template<std::size_t J>
friend class TaggedObserver<Thing<I...>, J>;
public:
Thing(): TaggedObserver<Thing<I...>, I>{}... {}
template<std::size_t N>
void Observe(Parameter p) {
TaggedObserver<Thing<I...>, N>::Observe(p);
}
};
Обратите внимание, что friend
декларация позволяет TaggedObserver
ей получить доступ к закрытым членам Thing
.
Таким образом, реализации Observe
в TaggedObserver
s могут получить доступ к общедоступным, защищенным и закрытым членам от Thing
, как указано в комментариях.
Наконец, вы можете специализироваться на TaggedObserver
, если необходимо, чтобы обеспечить различные реализации для Observe
.
В качестве примера:
template<template T, size_t Tag>
class TaggedObserver;
template<template T>
class TaggedObserver<T, 0>: public Observer {
public:
void Observe(Parameter p) override {
T *t = static_cast<T*>(this);
// Now use whatever you want from T, that is Thing in this example
// Put here the code of the specialization for Tag 0
}
};
template<template T>
class TaggedObserver<T, 1>: public Observer {
public:
void Observe(Parameter p) override {
T *t = static_cast<T*>(this);
// Now use whatever you want from T, that is Thing in this example
// Put here the code of the specialization for Tag 1
}
};
'TaggedObserver <0> и' 'TaggedObserver <1> такие же класса. Почему бы не сделать два дочерних класса? –
@ JimV: Это не так. Точка их шаблонов - это дифференциация базовых классов. – Dani
@JimV: 'TaggedObserver <0>' и 'TaggedObserver <1>' может быть основан на том же классе * template *, но они являются разными * экземплярами * классов. Точно так же, как 'std :: vector' и 'std :: vector ' - это разные классы. Значения параметров шаблона являются частью типа класса и производят разные RTTI-результаты. –