Inheritance Hierarchy from Template Arguments
I need to create a type erasure pattern that would allow all contained objects to be inherited from a given base class. As far as I know, the popular erasure type boost :: any allows fetching an object with any_cast only if the requested and containing classes matches exactly, so it won't suit my needs.
I could solve the problem with a template class that mimics the inheritance relationship of the template argument. For example, it TemplateClass<Derived>
should be a child TemplateClass<Base>
, so the following example will work:
// Suppose all clases have virtual destructors so that vtable and RTTI info are available
class ObjectWrapperBase {
}
template<class DataType>
class ObjectWrapperT: public ObjectWrapperBase {
public:
ObjectWrapperBase(T* ptr): dataObjPtr(ptr){}
DataType *dataObjPtr;
}
class Base{}
class Derived: public Base{}
class NotDerivedFromBase{}
int main(){
std::vector<ObjectWrapperBase*> v;
v.push_back(new ObjectWrapperT<Base>(new Base));
v.push_back(new ObjectWrapperT<Derived>(new Derived));
v.push_back(new ObjectWrapperT<NotDerivedFromBase>(new NotDerivedFromBase));
// Now suppose I want to retrieve all the Base and children objects in v
// If ObjectWrapperT<Derived> is a child of ObjectWrapperT<Base> I can write:
for(int i = 0; i < v.size(); i++){
ObjectWrapperT<Base> *wPtr = dynamic_cast<ObjectWrapperT<Base>*>(v[i]);
if(wPtr){
Base *basePtr = wPtr->dataObjPtr;
}
}
}
Is there a pattern for achieving this behavior? Or, after all, another solution? Thank.
source to share
You can't do exactly what you want, but you can get something a little closer with templates and operators.
As a minimal working example:
#include<type_traits>
template<typename D>
struct S {
S(D *d): d{d} {}
template<typename B, typename = std::enable_if_t<std::is_base_of<B, D>::value>>
operator S<B>() {
return {d};
}
private:
D *d;
};
struct B {};
struct D: B {};
struct A {};
int main() {
S<D> sd{new D};
S<B> sb = sd;
// S<A> sa = sd;
}
If you switch the comment to the last line, it will no longer compile for A
non-baseline B
.
source to share
I don't know if this is what you are looking for, but you can do something like this:
template <typename T>
class Derived : public T
{
};
And then instantiate a class named mothers Base
like this:
Derived<Base> object;
You will finally get this from Base
:
class Derived : public Base
{
};
source to share