Let say we have a base class and its two derived classes; The base class owns a method execute and each derived class implements a different version of this method with different types and number of arguments; I can't use a virtual method because signature should be then exactly the same for each derived class; My goal is to offer a base execute method which accepts any kind of arguments, deducts their types, and dispatch them to the right method in the right derived class; I took a look at the Visitor pattern, but I'm looking for a more flexible and elegant solution;
edit : I want to store those classes in a vector, so I need a base class
Here is my try (I don't know what to put in the body of base execute) under gcc 4.5:
class Base {
public:
Base();
~Base();
template<typename ...Args>
void execute(Args... arg)
{
//calls the right method
//execute(int i) or execute(int i, float f)
//as Args are int or int and float
}
};
class DerivedA : public Base
{
public:
DerivedA();
~DerivedA();
void execute(int i){ /*do something with i*/}
};
class DerivedB : public Base
{
public:
DerivedB();
~DerivedB();
void execute(int i, float f){/*do something with i and f*/}
};
void test()
{
Base* b1 = new DerivedA();
Base* b2 = new DerivedB();
int i = 5;
b1->execute(i); //should call DerivedA.execute(int i)
float f = 5.0f;
b2->execute(i, f); //should call DerivedB.execute(int i, float f)
}
The following uses an intermediate class in between the base and the derived class:
#include <utility>
#include <iostream>
#include <stdexcept>
template<typename... Args> class Intermediate;
class Base
{
public:
virtual ~Base() {}
template<typename ...Args>
void execute(Args... args)
{
typedef Intermediate<Args...>* pim;
if (pim p = dynamic_cast<pim>(this))
{
p->execute(std::forward<Args>(args)...);
}
else
{
throw std::runtime_error("no suitable derived class");
}
}
};
template<typename... Args> class Intermediate:
public Base
{
public:
virtual void execute(Args ... arg) = 0;
};
class DerivedA:
public Intermediate<int>
{
public:
void execute(int i)
{
std::cout << "DerivedA: i = " << i << "\n";
}
};
class DerivedB:
public Intermediate<int, float>
{
public:
void execute(int i, float f)
{
std::cout << "DerivedB: i = " << i << ", f = " << f << "\n";
}
};
int main()
{
Base* b1 = new DerivedA();
Base* b2 = new DerivedB();
int i = 5;
b1->execute(i); //should call DerivedA.execute(int i)
float f = 5.0f;
b2->execute(i, f); //should call DerivedB.execute(int i, float f)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With