Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I cycle on instances of heterogenous classes to call methods with identical name and parameters?

Tags:

c++

methods

c++98

If I have:

class A {
    void foo();
};

class B {
    void foo();
};

Is there a way to collect instances of type A and B to cycle on them to call the foo() method? For example using some macro or pointers and some special data type? Or collecting function pointers?

The following pseudocode might give an idea of what I mean.

int main () {
    A a;
    B b;

    hypothetical_container_t hypothetical_container; 
    hypothetical_container.push_back(a);
    hypothetical_container.push_back(b);

    [...]//Do stuff with a, do other stuff with b

    for (hypothetical_container_t::iterator ii = hypothetical_container.begin(); ii != hypothetical_container.end(); ++ii) {
        ii->foo();
    }
}

The use case is having a bunch of boost::shared_ptr variables with different type T and call .reset() on all of them. (I know in this example calling reset wouldn't be necessary).

like image 269
Antonio Avatar asked Mar 17 '23 10:03

Antonio


2 Answers

If you have the option of changing the classes A and B, I would recommend going with the answer by @mstbaum.

If you don't have that option, I have the following suggestion.

#include <memory>
#include <iostream>
#include <vector>

struct A {
    void foo(){}
};

struct B {
    void foo(){}
};

struct Wrapper
{
   virtual void foo() = 0;
};

template <typename T> struct WrapperImpl : Wrapper
{
   WrapperImpl(T& obj) : obj_(obj) {}
   void foo() {obj_.foo();}
   T& obj_;
};

template <typename T>
std::unique_ptr<Wrapper> makeWrapper(T& t)
{
   return std::unique_ptr<Wrapper>(new WrapperImpl<T>(t));
}

int main()
{
   std::vector<std::unique_ptr<Wrapper>> v;
   A a;
   B b;
   v.push_back(makeWrapper(a));
   v.push_back(makeWrapper(b));

   for ( auto& item : v )
   {
      item->foo();
   }
}
like image 106
R Sahu Avatar answered Apr 07 '23 19:04

R Sahu


You should be able to use a virtual class:

virtual class C {
    public:
        virtual void foo() = 0;
}

class A : public C {
    virtual void foo();
};

class B : public C {
    virtual void foo();
};

Then in main you can have:

A a;
B b;

std::vector<C*> vec;
vec.push_back(&a);
vec.push_back(&b);

And then you can iterate and call the foo method, which all members of the vector are guaranteed to implement.

WRT boost::shared_ptr, I'm not as familiar with but I would imagine you could do something like:

boost::shared_ptr<C> a(new A);
boost::shared_ptr<C> b(new B);

std::vector<boost::shared_ptr<C>> vec;
like image 21
mstbaum Avatar answered Apr 07 '23 19:04

mstbaum