Related question: link.
In one of the answers to the question above, I was recommended to use the visitor pattern to resolve some of the issues with my class inheritance structure. However, I am not sure if it is possible to use it in my context because my derived classes can be non-type templates.
To showcase the problem I used a modified code from this source: http://sourcemaking.com/design_patterns/visitor/cpp/2.
The example below does not compile because it is not possible to define a virtual template method. However, I believe, the code demonstrates what I am trying to achieve. Are there any alternatives solutions to the problem?
// 1. Add an accept(Visitor) method to the "element" hierarchy
class Element
{
public:
virtual void accept(class Visitor &v) = 0;
};
template <unsigned int N>
class This: public Element
{
public:
/*virtual*/void accept(Visitor &v);
string thiss()
{
return "This";
}
};
class That: public Element
{
public:
/*virtual*/void accept(Visitor &v);
string that()
{
return "That";
}
};
// 2. Create a "visitor" base class w/ a visit() method for every "element" type
class Visitor
{
public:
template<unsigned int N>
virtual void visit(This<N> *e) = 0;
virtual void visit(That *e) = 0;
};
template<unsigned int N>
/*virtual*/void This<N>::accept(Visitor &v)
{
v.visit(this);
}
/*virtual*/void That::accept(Visitor &v)
{
v.visit(this);
}
// 3. Create a "visitor" derived class for each "operation" to do on "elements"
class UpVisitor: public Visitor
{
/*virtual*/void visit(This *e)
{
cout << "do Up on " + e->thiss() << '\n';
}
/*virtual*/void visit(That *e)
{
cout << "do Up on " + e->that() << '\n';
}
};
class DownVisitor: public Visitor
{
/*virtual*/void visit(This *e)
{
cout << "do Down on " + e->thiss() << '\n';
}
/*virtual*/void visit(That *e)
{
cout << "do Down on " + e->that() << '\n';
}
};
int main()
{
Element *list[] =
{
new This<3>(), new That()
};
UpVisitor up; // 4. Client creates
DownVisitor down; // "visitor" objects
for (int i = 0; i < 2; i++) list[i]->accept(up);
for (int i = 0; i < 2; i++) list[i]->accept(down);
}
The problem is your Visitor class is tightly coupled with classes that derive from Element. As you expand your design this is going to get in the way more than it already is. You can reduce/eliminate the right coupling by providing a "destination" class that defines all the requirements of a visitable object. Since the name of a derived classes is a common attribute you can place the storage and access to it into the destination class as well.
// 1. Define out visitor and destination interfaces
struct Destination
{
Destination(const std::string& name) : name_(name) {}
virtual std::string ident() const { return name_; }
const std::string name_;
};
struct Visitor
{
virtual void visit(Destination *e) = 0;
};
This keeps the requirements of the visitor separate from the Element class which seems to be your intention. Then your This and That classes inherit from Destination and provide the necessary implementations.
// 2. Define our element and it's derived classes
class Element
{
public:
virtual void accept(class Visitor &v) = 0;
};
template <unsigned int N>
class This: public Element, public Destination
{
public:
This() : Destination("This") {}
virtual void accept(Visitor &v)
{
v.visit(this);
}
};
class That: public Element, public Destination
{
public:
That() : Destination("That") {}
virtual void accept(Visitor &v)
{
v.visit(this);
}
};
Now your up and down visitors are simplified into something like the following
// 3. Create a "visitor" derived class for each "operation" to do on "elements"
class UpVisitor: public Visitor
{
void visit(Destination *e) {
cout << "do Up on " + e->ident() << '\n';
}
};
class DownVisitor: public Visitor
{
void visit(Destination *e) {
cout << "do Down on " + e->ident() << '\n';
}
};
Although I did not change it in the solution above I recommend changing visit to take a reference instead of a pointer. Since C++ has no notion of a null reference this indicates that Destination is required where as a pointer could be considered optional.
Related
I am looking for a workaround to the lack of virtual template functions in C++.
What I want ideally is to be able to store my derived classes in a vector, iterate over those and call the correct function, so in pseudo-code:
template<typename T>
struct Output
{
...
};
struct Base
{
template<typename T>
virtual void doSomething(Output<T>& out) = 0;
};
struct DerivedA : public Base
{
DerivedA(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
struct DerivedB : public Base
{
DerivedB(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
int main()
{
std::vector<Base*> vec;
vec.push_back(new DerivedA("data1.bin"));
vec.push_back(new DerivedB("data2.bin"));
vec.push_back(new DerivedA("data3.bin"));
vec.push_back(new DerivedA("data4.bin"));
Output<float> outF;
Output<double> outD;
Output<int> outI;
for (auto e : vec)
{
e->doSomething(outF);
e->doSomething(outD);
e->doSomething(outI);
}
return 0;
}
I would prefer it if the workaround is as "painless" and non-verbose as possible (since I am using the templates to avoid redefining the same function n times for n different types in the first place). What I had in mind was making myself a vtable with std::map, and doing some dynamic_casts. I am looking for any better ideas, or even for a concise implementation of that idea if you consider it the best in this scenario. I am looking for a solution that is ideally the least intrusive, and that is very easy to add new classes to.
Edit:
I figured a workaround, but it includes some verbosity (but at least avoids non-trivial code duplication):
struct Base
{
virtual void doSomething(Output<int>& out) = 0;
virtual void doSomething(Output<float>& out) = 0;
virtual void doSomething(Output<double>& out) = 0;
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "Base doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedA : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedA doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedB : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedB doSomething called with: " << typeid(T).name() << "\n";
}
};
Does anybody have any better idea how I can go about this without having to redefine the same functions over and over? Ideally it would be defined once in the base class, CRTP doesn't seem to help. Dynamic casts seem like the other sane option.
Try something like this:
struct OutputBase
{
virtual void doSomething() = 0;
};
template<class T >
struct Output : public OutputBase
{
virtual void doSomething()
{
std::cout << typeid(T).name();
}
};
struct Base
{
virtual void doSomething(OutputBase* out) = 0;
};
struct DerivedA : public Base
{
virtual void doSomething(OutputBase* out)
{
std::cout << "DerivedA doSomething called with: ";
out->doSomething();
std::cout<< std::endl;
}
};
struct DerivedB : public Base
{
virtual void doSomething(OutputBase* out)
{
std::cout << "DerivedB doSomething called with: ";
out->doSomething();
std::cout << std::endl;
}
};
int main()
{
OutputBase* out_int = new Output < int > ;
OutputBase* out_double = new Output < double >;
Base* a = new DerivedA;
a->doSomething(out_int);
a->doSomething(out_double);
Base* b = new DerivedB;
b->doSomething(out_int);
b->doSomething(out_double);
return 0;
}
You can use a wrapper around Output if you don't want to change it.
Currently I am learning about the Visitor Pattern and try out various ideas.
Below I have the code of my current setup, which I would like to get functioning somehow.
I would like to have two visitors, one that counts instances of Red and Blu separately and one that counts anything (one can assume, it's a Color)
This is of course solvable by simply implementing the second visitor analogously to the first one, however not using separate variables for counting, but just one.
I think however this is unnecessary - if I had for example many, many different colours, the code would be very repetitive: All functions in that visitor would be same, they would simply increment one variable. Surely, there is an easier way, but how?
According to the standard Visitor Pattern I have to implement for every color class a visit functions, thus this does not seem to be the right approach.
How would someone solve this problem?
#include <iostream>
class Color
{
public:
virtual void accept(class Visitor*) = 0;
};
class Red: public Color
{
public:
/*virtual*/
void accept(Visitor*);
void eye()
{
std::cout << "Red::eye\n";
}
};
class Blu: public Color
{
public:
/*virtual*/
void accept(Visitor*);
void sky()
{
std::cout << "Blu::sky\n";
}
};
class Visitor
{
public:
virtual void visit(Red*) = 0;
virtual void visit(Blu*) = 0;
};
class CountVisitor: public Visitor
{
public:
CountVisitor()
{
m_num_red = m_num_blu = 0;
}
/*virtual*/
void visit(Red*)
{
++m_num_red;
}
/*virtual*/void visit(Blu*)
{
++m_num_blu;
}
void report_num()
{
std::cout << "Reds " << m_num_red << ", Blus " << m_num_blu << '\n';
}
private:
int m_num_red, m_num_blu;
};
class TemplateVisitor: public Visitor
{
public:
TemplateVisitor() : num_of_colours(0) {}
/*virtual*/
template<class C>
void visit(C* c)
{
++num_of_colours;
}
void report_num()
{
std::cout << "Colours " << num_of_colours << '\n';
}
private:
int num_of_colours;
};
void Red::accept(Visitor *v)
{
v->visit(this);
}
void Blu::accept(Visitor *v)
{
v->visit(this);
}
int main()
{
Color *set[] =
{
new Red, new Blu, new Blu, new Red, new Red, nullptr
};
CountVisitor count_operation;
TemplateVisitor template_visitor;
for (int i = 0; set[i]; i++)
{
set[i]->accept(&count_operation);
set[i]->accept(&template_visitor);
}
count_operation.report_num();
template_visitor.report_num();
}
Unfortunately, virtual methods and template methods can't match.
I mean... if your base class Visitor require
virtual void visit(Red*) = 0;
virtual void visit(Blu*) = 0;
the implementation of two virtual methods in derived classes, you can't solve this obligation with a single template method
template<class C>
void visit(C* c)
{
++num_of_colours;
}
You have to write two methods, absolutely not template, with the exact signature. Maybe adding also override, to reduce the risk of mistakes.
void visit (Red * r) override
{ ++num_of_colours; }
void visit (Blu * b) override
{ ++num_of_colours; }
Obviously you can define a template method (maybe with another name, but also visit() if you want) that is called by both virtual overrided methods
template <typename C>
void visit (C * c)
{ ++num_of_colours; }
void visit (Red * r) override
{ visit<Red>(r); }
void visit (Blu * b) override
{ visit<Blu>(b); }
This way, you can implement the logic of the visitor in a single template method and call it by all virtual methods
Why not just use a map and add some function to color to use as an identifier?
class Color
{
public:
virtual void accept(class Visitor*) = 0;
virtual std::string color_name() = 0;
};
class Visitor
{
public:
virtual void visit(Color* c);
};
class CountVisitor: public Visitor
{
std::unordered_map<std::string, int> map;
public:
/*virtual*/
void visit(Color* c)
{
map[c.color_name()]++;
}
};
Let say I've this code with a EnvelopeMultiPoints class template:
#include <iostream>
#include <vector>
class EnvelopeMultiPointsBase
{
// base
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
void Process() {
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch> { };
template<typename T>
unsigned int EnvelopeMultiPoints<T>::mNumPoints = 5;
class Container
{
public:
EnvelopeMultiPointsBase *pAssociatedEnvelope;
Container(EnvelopeMultiPointsBase *associatedEnvelope) : pAssociatedEnvelope(associatedEnvelope) { }
~Container() { }
void Process();
private:
};
int main()
{
EnvelopeMultiPoints<Pitch> pitch;
Container container(&pitch);
container.pAssociatedEnvelope->Process();
}
And I want to pass to the Container any kind of "EnvelopeMultiPoints" types (a generic "pointer"), so later I can access to its own method (in my case, Process()).
Does it means that also Container must be templated? (which is huge in my real scenario; lot of works to transform all of its methods in template, translate header/cpp, and such).
Or is there a trick that I'm missing?
In few words: let say that I want to pass to Container EnvelopeMultiPoints<Pitch>, and than execute Process(). Later, I want to pass EnvelopeMultiPoints<Volume> instead, and than execute Process(). And so on. Is there a way to do this without converting also Container to a template?
The technique you need is called dynamic polymorphism
that is implemented in C++ by virtual functions.
Illustrating using your code:
class EnvelopeMultiPointsBase
{
public:
// Abstract base, no actual implementation
virtual void Process() = 0;
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
// Some specific implementation.
virtual void Process() override
{
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch>
{
};
To call the Process function of the base class, you have to define it in the base class. You can move the implementation to templated child classes:
class EnvelopeMultiPointsBase
{
private:
virtual void ProcessImpl() = 0;
public:
void Process() {
//potential common code...
ProcessImpl();
//more potential common code...
}
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
private:
void ProcessImpl() {
std::cout << "process" << std::endl;
}
};
An example of Strategy Pattern from the book, Head First Design Patterns, was written in C++ at [here]. I'm practicing to transform it into C++11 style according to Effective GoF Patterns with C++11 and Boost as showing below.
The Quack behavior:
struct Quack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
struct MuteQuack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
The Fly behavior:
struct FlyWithWings {
public:
static void fly()
{
std::cout << __FUNCTION__ << std::endl;
}
};
struct FlyNoWay {
public:
static void fly()
{
std::cout << __FUNCTION__ << std::endl;
}
};
The Duck hierarchy:
class Duck
{
public:
typedef std::function<void(void)> QUACK;
typedef std::function<void(void)> FLY;
public:
Duck(const QUACK &q, const FLY &f)
: m_Quack(q), m_Fly(f) {}
virtual ~Duck()
{
}
void perform_quack()
{
m_Quack();
}
void perform_fly()
{
m_Fly();
}
protected:
QUACK m_Quack;
FLY m_Fly;
private:
Duck(const Duck&) = delete;
Duck& operator=(const Duck&) = delete;
};
class MallardDuck
: public Duck
{
public:
MallardDuck()
: Duck(&Quack::quack, &FlyWithWings::fly)
{
}
};
class PaintedDuck
: public Duck
{
public:
PaintedDuck()
: Duck(&MuteQuack::quack, &FlyNoWay::fly)
{
}
};
So far so good, the client works well.
int main()
{
MallardDuck x1;
x1.perform_quack();
x1.perform_fly();
PaintedDuck x2;
x2.perform_quack();
x2.perform_fly();
return 0;
}
Now I would like to extend to a new class RubberDuck to Duck hierarchy, and the RubberDuck uses a new fly behavior FlyWithRocket which has a object state. As following:
A new Fly behavior:
class FlyWithRocket {
public:
FlyWithRocket() : m_Energy(3) {}
void fly()
{
if(m_Energy > 0)
{
fly_with_rocket();
--m_Energy;
}
else
{
fly_out_of_energy();
}
}
private:
void fly_with_rocket()
{
std::cout << __FUNCTION__ << std::endl;
}
void fly_out_of_energy()
{
std::cout << __FUNCTION__ << std::endl;
}
unsigned int m_Energy;
};
A new Duck type:
class RubberDuck
: public Duck
{
public:
RubberDuck()
: Duck(&MuteQuack::quack, std::bind(&FlyWithRocket::fly, std::ref(m_flyrocket)))
, m_flyrocket()
{
}
private:
FlyWithRocket m_flyrocket;
};
From now I'm wondering that the rule of the order of member initialization. The base Duck initializes before the member m_flyrocket, but note that the base Duck is initialized with binding m_flyrocket which is not initialized yet.
As result as I run it in VS2013, this works without something wrong at run-time.
But is the code actually not safe? If not, how could I modify to a better design?
It's not safe, but it's unlikely to break unless you call m_Fly() from the base class constructor.
You can easily avoid this though, by either:
giving the base class constructor a dummy or default-constructed std::function, and re-assigning m_Fly to your bind functor in the derived class constructor
RubberDuck()
: Duck(&MuteQuack::quack, std::function<void()>())
{
m_Fly = std::bind(&FlyWithRocket::fly, std::ref(m_flyrocket));
}
making FlyWithRocket a functor itself (just rename void fly to void operator()) and passing it by value instead of keeping a private member (it will be owned by the m_Fly function object, and you can access it via std::function::target<FlyWithRocket>() if you need)
class FlyWithRocket {
public:
FlyWithRocket() : m_Energy(3) {}
void operator() () {
// ...
RubberDuck()
: Duck(&MuteQuack::quack, FlyWithRocket()) {}
I have a problem which I encounter again and again in a similar way.
For example:
I have an abstract base class which acts as interface for a series of concrete classes which act as, let's say, data containers.
class DataInterface
{
public:
DataInterface();
~DataInterface();
virtual void FetchData(void) = 0;
virtual void ProcessData(void) = 0;
virtual void ClearData(void) = 0;
}
The concrete classes would look like this:
class BinaryData: public DataInterface
{
public:
BinaryData();
~ BinaryData();
virtual void FetchData(void);
virtual void ProcessData(void);
virtual void ClearData(void);
private:
bool m_boolData;
}
class IntegerData: public DataInterface
{
public:
IntegerData();
~ IntegerData();
virtual void FetchData(void);
virtual void ProcessData(void);
virtual void ClearData(void);
private:
int m_intData;
}
The subclasses implement the interface which they inherited from DataInterface. But they have different attributes to hold their data. So far so good.
I can use the classes in the main function like that:
int main()
{
int IntegerData;
bool BoolData;
DataInterface *pData1 = new BinaryData();
DataInterface *pData2 = new IntegerData();
pData1->FetchData();
pData2->FetchData();
pData1->ProcessData();
pData2->ProcessData();
// now I want to get the data of pData1 and pData2, for example to write it into a file, show in visualization, ...
IntegerData = pData2->GetData() ????
BoolData = pData1->GetData() ????
}
Now comes the problem:
How do I get the data from the concrete classes? I have only base class pointers, so I would need to define an abstract getter method in DataInterface. But the signature of the getter method wouold vary from subclass to subclass. For example one time I need to return an integer, one time I need to return a bool type.
Please give me a hint, this problem drives me nuts :/
Make a non-virtual GetData() member on each derived class. Then, if you know for certain the actual class of your objects, you can simply perform a static cast and call GetData():
int intData = static_cast<IntegerData*>(pData2)->GetData();
If you don't know the class, then you need to perform a dynamic cast and check its result:
if (IntegerData* _pData2 = dynamic_cast<IntegerData*>(pData2))
{
int intData = _pData2->GetData();
// Do stuff with the int
}
else if (BinaryData* _pData2 = dynamic_cast<BinaryData*>(pData2))
{
bool binaryData = _pData2->GetData();
// Do stuff with the bool
}
If you want to pass your data to another entity, you need an abstraction of it.
There are 2 common ways to achieve this:
1:
Use void*.
class DataInterface
{
public:
...
virtual void* GetData() = 0;
};
class BinaryData: public DataInterface
{
public:
virtual void* GetData() { return &m_boolData; }
private:
bool m_boolData;
};
In main use it like this:
int main()
{
bool BoolData;
DataInterface *pData1 = new BinaryData();
pData1->FetchData();
pData1->ProcessData();
BoolData = *(bool*))pData1->GetData());
}
Advantage of this approach is in its simplicity.
Disadvantages are direct access to internal of an object (breaking encapsulation) and also misuse of polymorphism (why do you need an interface if you eventually cast to a type related to a concrete derivative?)
2:
A more robust way is to not send the raw data to a client from out of your concrete object but to make a communication with clients an additional role of the object.
class DataInterface
{
public:
...
virtual void SendData() = 0;
};
class BinaryData: public DataInterface
{
public:
...
virtual void SendData()
{
//do your stuff here, you know the exact type of your data
}
};
int main()
{
bool BoolData;
DataInterface *pData1 = new BinaryData();
pData1->FetchData();
pData1->ProcessData();
pData1->SendData();
}
Note, this is a very stripped example but it demonstrates the idea. Normally, in a real use case you would register clients with you class and send the data to them via a defined interface.
I am not really sure this is a "good" practice but here is one way to solve this.
One advantage with this is that if you try to get the wrong type of data you can get custom error messages. And you can avoid casts (I am not a fan of them).
class DataInterface
{
public:
DataInterface();
~DataInterface();
virtual void FetchData(void) = 0;
virtual void ProcessData(void) = 0;
virtual void ClearData(void) = 0;
virtual int getIntData() { // Error message }
virtual bool getBoolData() { // Error message }
};
class BinaryData: public DataInterface
{
public:
BinaryData();
~ BinaryData();
virtual void FetchData(void);
virtual void ProcessData(void);
virtual void ClearData(void);
virtual int getIntData() { // Error message }
virtual bool getBoolData() { return m_boolData; }
private:
bool m_boolData;
}
class IntegerData: public DataInterface
{
public:
IntegerData();
~ IntegerData();
virtual void FetchData(void);
virtual void ProcessData(void);
virtual void ClearData(void);
virtual int getIntData() { return m_intData; }
virtual bool getBoolData() { // Error message }
private:
int m_intData;
}
int main()
{
int IntegerData;
bool BoolData;
DataInterface *pData1 = new BinaryData();
DataInterface *pData2 = new IntegerData();
pData1->FetchData();
pData2->FetchData();
pData1->ProcessData();
pData2->ProcessData();
// now I want to get the data of pData1 and pData2, for example to write it into a file, show in visualization, ...
IntegerData = pData2->GetIntData();
BoolData = pData1->GetBoolData();
BoolData = pData2->GetBoolData() // This will tell you that you are trying to get bool from int class.
}
Here is one way of handling it with templates.
using namespace std;
template<typename T>
class DataInterface
{
public:
DataInterface(T d) : data(d) {}
virtual T GetData() = 0;
protected:
T data;
};
class BinaryData : public DataInterface<bool>
{
public:
BinaryData(bool b) : DataInterface<bool>(b) {}
virtual bool GetData() {return data;}
};
class IntegerData: public DataInterface<int>
{
public:
IntegerData(int i) : DataInterface<int>(i) {}
virtual int GetData() {return data;}
};
int main()
{
int myint;
bool mybool;
DataInterface<bool> *pData1 = new BinaryData(true);
DataInterface<int> *pData2 = new IntegerData(1);
// now I want to get the data of pData1 and pData2, for example to write it into a file, show in visualization, ...
myint = pData2->GetData();
mybool = pData1->GetData();
cout<<myint<<" "<<mybool<<endl;
}
A very simple way of achieving this is to design your base class so that it returns a variant type. A variant is a discriminated union container, which holds an object from an heterogeneous set of types (see http://www.boost.org/doc/libs/1_59_0/doc/html/variant.html). Here is a complete example:
#include <iostream>
#include <algorithm>
#include <boost/variant.hpp>
#include <memory>
using namespace std;
class DataInterface
{
public:
DataInterface(){};
virtual ~DataInterface(){};
virtual void FetchData(void) = 0;
virtual void ProcessData(void) = 0;
virtual void ClearData(void) = 0;
virtual boost::variant<bool,int,double,std::string> GetData()=0;
};
class IntResult : public DataInterface{
public:
IntResult() : resultInt(0){};
~IntResult(){};
virtual void FetchData() override {resultInt = 10;};
virtual void ProcessData() override {resultInt *= 10;}
virtual void ClearData() override {resultInt = 0;};
virtual boost::variant<bool,int,double,std::string> GetData()override{
return resultInt;
};
private:
int resultInt;
};
class StringResult : public DataInterface{
public:
StringResult() : resultString(""){};
~StringResult(){};
virtual void FetchData() {
resultString= "Hello World";
}
virtual void ProcessData() override {
std::transform(resultString.begin(), resultString.end(),resultString.begin(), ::toupper);
}
virtual void ClearData() override {resultString = "";}
virtual boost::variant<bool,int,double,std::string> GetData() override {
return resultString;
};
private:
std::string resultString;
};
int main() {
DataInterface* data;
IntResult* intResult = new IntResult;
StringResult* stringResult = new StringResult;
data = intResult;
data->FetchData();
data->ProcessData();
switch(data->GetData().which()){
case 0:
std::cout << "found bool: " << boost::get<bool>(data->GetData()) << std::endl;
break;
case 1:
std::cout << "found int: " << boost::get<int>(data->GetData()) << std::endl;
break;
case 2:
std::cout << "found double: " << boost::get<double>(data->GetData()) << std::endl;
break;
case 3:
std::cout << "found string: " << boost::get<std::string>(data->GetData()) << std::endl;
break;
default:
break;
}
data = stringResult;
data->FetchData();
data->ProcessData();
switch(data->GetData().which()){
case 0:
std::cout << "found bool: " << boost::get<bool>(data->GetData()) << std::endl;
break;
case 1:
std::cout << "found int: " << boost::get<int>(data->GetData()) << std::endl;
break;
case 2:
std::cout << "found double: " << boost::get<double>(data->GetData()) << std::endl;
break;
case 3:
std::cout << "found string: " << boost::get<std::string>(data->GetData()) << std::endl;
break;
default:
break;
}
delete intResult;
delete stringResult;
return 0;
}
Note that in your case a bool is implicitly convertible to an int so you could simply return ints all the time. The variant approach would work if you need to return truly heterogeneous types. Equivalently you could return a boost any, which can also lets you manipulate a heterogeneous union of types uniformly (see http://www.boost.org/doc/libs/1_59_0/doc/html/any.html). Finally if you don't want any dependencies on boost, it is not terribly difficult to roll out your own variant type, which can hold discriminate set of types.