Как предполагает Джалф в комментариях, вы, вероятно, захотите использовать вариант любопытно повторяющегося шаблона (CRTP). То есть, сделать MyHashingSolution
шаблоном класса, параметризованным производным классом:
template <typename D>
struct MyHashingSolution {
typedef D Derived;
void UpdateHash(int idx, int val) {
...
}
void RecalcHash() {
...
UpdateHash(idx, derived().GetState(idx));
...
}
private:
// Just for convenience
Derived& derived() { return *static_cast<Derived*>(this); }
};
В этом случае, поскольку вы хотите, чтобы производный класс State
также был шаблоном, вам нужно сделать несколько необычный шаг - объявить State
в качестве шаблона класса, который принимает параметр шаблона шаблона :
template <template <class T> class HashingSolution>
struct State : public HashingSolution<State<HashingSolution> > {
typedef HashingSolution<State<HashingSolution> > Parent;
void Update(int idx, int val) {
Parent::UpdateHash(idx, val); // g++ requires "Parent::"
}
int GetState(int idx) {
return ...;
}
};
Ключевым моментом является то, что при условии, что State
наследуется от HashingSolution<State<HashingSolution> >
, Derived
является производным классом HashingSolution<State<HashingSolution> >
, поэтому static_cast<Derived*>(this)
downcast в HashingSolution<State>::derived()
компилируется и работает правильно. (Если вы запутаетесь и извлечете State
из HashingSolution<SomeOtherType>
вместо этого, а затем попробуете что-то, связанное с вызовом derived()
, компилятор будет жаловаться, поскольку требования для static_cast<>
не выполнены.)
Затем объявите конкретный класс State
, который вы хотите использовать, следующим образом:
typedef State<MyHashingSolution> MyState;
К сожалению, у этого решения есть побочный эффект, который вам нужно будет заменить DummyHashingSolution
(и любые другие подобные типы) на шаблоны, которые игнорируют один аргумент шаблона, чтобы сделать их пригодными для использования в качестве аргументов шаблона.