I'm trying to wrap my head around the order of instantiation and specialization of templates, especially in cases where subclasses are involved.
Please consider the following example:
class A {
int value() { return 42; }
};
class B {
double value() { return 3.1415; }
};
class MyBase {
public:
virtual int value() = 0;
};
template<class T> class MyClass : public MyBase {
protected:
class Cache;
mutable Cache _cache;
public:
MyClass(T t) : _cache(t.value()) {};
virtual int value() override;
};
template<class T> class MyClass<T>::Cache {
public:
int x;
int getVal(){return x;}
};
template<> class MyClass<B>::Cache {
public:
double z;
int getVal(){return 100*z;}
};
template<class T> int MyClass<T>::value() { return _cache.getVal(); }
typedef MyClass<A> MyA;
typedef MyClass<B> MyB;
This results in error: specialization of ‘MyClass<B>::Cache’ after instantiation
, which I don't understand. I would have guessed that MyClass<B>::Cache
is only required once the typedef
happens, but that doesn't seem to be the case. I have tried to move around the specialization a bit, before the general template definition, inside the definition of MyClass
or even before that (using forward declares), but without any luck.
Is there a proper way to achieve something like this, or is this just logically impossible for reasons that I would be delighted to understand better?
I guess I could achieve this by making _cache
a pointer such that a full definition is not required at time of defining MyClass
, but I'd rather avoid doing that unless I understand the underlying issue.