Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance hierarchy from template arguments

I'd need to create a type erasure pattern which would allow to retrieve all the contained objects inheriting from a given base class. As far as I know, a popular type erasure like boost::any allows to retrieve an object with any_cast only if the requested and contained classes matches exactly, so it won't fit my needs.

I could solve the problem with template class which mimicks the inheritance relationship of the template argument. For example, TemplateClass<Derived> should be a child of TemplateClass<Base>, so that the following example would 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 to achieve this behavior? Or eventually another solution? Thanks.

like image 800
Nicola Mori Avatar asked Mar 20 '26 04:03

Nicola Mori


1 Answers

You cannot do exactly what you want, but you can get something 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 toggle the comment to the last line, it won't compile anymore for A is not a base of B.

like image 63
skypjack Avatar answered Mar 21 '26 21:03

skypjack



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!