3

Consider I have a bunch pointers to to different objects of different classes

class1* obj1;
class2* obj2;
class3* obj3;

and they all have one method getArray() which returns a vector for post processing.

if all of these pointers are stored in some sort of a list (a list of void pointers say)

while I am iterating the list is there a way to figure what type of a pointer cast can be used?

I understand this can be solved by class hierarchy and deriving the above classes from a single class. Since a lot of it is legacy code can something like what is mentioned be done?

Folly dynamic does not let me store pointers, thats one thing that is tried

ajax_velu
  • 286
  • 3
  • 16

2 Answers2

1

If getArray() always has the same signature (or similar enough to cast to the same type) - what you could do is create a class hierarchy for a decorator of the duck-typed legacy objects/classes. You can use a template derived class of a non-template interface to wrap without too much typing work.

Something along these lines (with more defensive coding, possibly smart pointers to the legacy object, etc. etc.):

class IDecorator {
  public:
    virtual std::vector<ubyte> GetArray() = 0;
};

template<typename TLegacyType>
class TDecorator : public IDecorator {
   public:
     TDecorator(const TLegacyType *ip_legacy_object)
       : mp_legacy_object(ip_legacy_object) {}
     std::vector<ubyte> GetArray() override {
        return mp_legacy_object->GetArray();
     }

   private:
     const TLegacyType *mp_legacy_object;        
};
Joris Timmermans
  • 10,814
  • 2
  • 49
  • 75
0
template<class R, class Op>
struct any_ptr {
  void* ptr=0;
  R(*f)( void* ) = 0;

  R operate() const { return f(ptr); }
  explicit operator bool() const { return ptr; }
  template<class T>
  T* as() const { return static_cast<T*>(ptr); }

  any_ptr(any_ptr const&)=default;
  any_ptr& operator=(any_ptr const&)=default;
  any_ptr()=default;

  template<class T>
  any_ptr(T* p_in):ptr(p_in),
    f( [](void* ptr)->R{ return Op{}( ptr ); } )
  {}
};

any_ptr supports storing any pointer that supports Op, where Op is a stateless function object type returning R.

struct get_array_t{
  template<class T>
  auto operator()(T* t)const{ return t->getArray(); }
};
using any_ptr_get_array = any_ptr< std::vector<int>, get_array_t >;

now any_ptr_get_array can store a pointer to any type that supports .getArray() that returns vector<int>.

To call getArray:

void test(any_ptr_get_array ptr){
  if(ptr){
    auto vec = ptr.operation();
  }
}

This technique could be called manual type erasure using a template generated vtable.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524