Policy Based Design - Ideomatic way to deal with multitude of types, e.g. storing them in a container, iterating, etc - c++

In the hello world example of policy based design from wikipedia we use a common interface HelloWorld and configure it with different policies through templates - so far so good:
int main() {
// Example 1
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish>
HelloWorldEnglish;
HelloWorldEnglish hello_world;
hello_world.Run(); // Prints "Hello, World!".
// Example 2
// Does the same, but uses another language policy.
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman>
HelloWorldGerman;
HelloWorldGerman hello_world2;
hello_world2.Run(); // Prints "Hallo Welt!".
}
This is all very nice and elegant, but what is the idiomatic way of managing / storing a collection of such configurable objects? For example, one would like to write
std::vector< some_magic_type > seasons_greetings; // What is the common type specifying the public interface only?
seasons_greetings.push_back(hello_world); // which is of type HelloWorldEnglish
seasons_greetings.push_back(hello_world2); // which is of type HelloWorldGerman
for (greeting : seasons_greetings) {
greeting.Run() // access only the public interface
}
In designing interfaces as base classes and deriving specialised implementations from them, I don't have this problem - I can always store pointers to the base class type - but I need to spell out all implementations leading to a whole lot of derived classes.
Policy Based Design promised to alleviate the explosion of derived classes that comes with this by using templates to mix and match behavior. But I pay for this with a whole lot of different types.
There must be an idiomatic way to deal with this. Any insight is greatly appreciated.
P.S.
I admit that I did not buy the book, but you might have guessed already.
This answer suggests storing a collection implies an inheritance based design, but does it really?

If you want to stay with unrelated classes you can use std:variant in combination with std::visit.
Example ( simply extend the main function from the original example )
using Variant = std::variant< HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish>, HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman> >;
std::vector< Variant > seasons_greetings;
seasons_greetings.push_back(hello_world);
seasons_greetings.push_back(hello_world2);
for (auto& greeting : seasons_greetings) {
std::visit( [](auto& what){ what.Run(); }, greeting );
}
The bad side: You have to know all possible combinations of policies which can be really uncomfortable. But you can use some meta template stuff to create all variant types by giving type lists for each used policy and the template will generate all combinations, which is not such a big hack.

So here is a solution I found after pondering the comments again - key seems to combine the best of both worlds, polymorphism and policies - who would have thought ....
By introducing a common base class that defines only the public interface of the behavior class and then deriving the behavior class from that and the policies, I can get exactly what I want:
class HelloWorldInterface {
public:
// Behavior method.
void Run() const {
run();
}
private:
virtual void run() const = 0;
};
template <typename OutputPolicy, typename LanguagePolicy>
class HelloWorld : public HelloWorldInterface, private OutputPolicy, private LanguagePolicy {
private:
using OutputPolicy::Print;
using LanguagePolicy::Message;
void run() const override final {
Print(Message());
}
};
Then, I can write basically what I wanted from the beginning:
int main() {
// Example 1
using HelloWorldEnglish = HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish>;
// Example 2
// Does the same, but uses another language policy.
using HelloWorldGerman = HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman>;
HelloWorldEnglish hello_world;
HelloWorldGerman hello_world2;
std::vector<const HelloWorldInterface*> greetings{&hello_world, &hello_world2};
for (auto x : greetings) {
x -> Run();
}
}
This way, one gets a single public interface that exposes behaviours resulting from an arbitrary combination of policies. Looks trivial now, though.

Related

How to create structs that all implement a trait that have common data members? [duplicate]

I'm trying to implement the Rust equivalent code of the following C++ code which makes use of inheritance, but got stuck. This is my sample code:
class Vehicle {
public:
double lat;
double lon;
double alt;
double speed;
};
class CabVehicle : public Vehicle {
};
class PackerMoverVehicle : public Vehicle {
};
int main() {
CabVehicle cv;
cv.lat = 12.34;
cv.lon = 12.34;
cv.alt = 12.34;
PackerMoverVehicle pmv;
pmv.lat = 12.34;
pmv.lon = 12.34;
pmv.alt = 12.34;
}
How should this be written in Rust?
The general answer is to use composition instead of inheritance. Depending on the application, there can be different ways the composition should go. In most cases, you should start with
struct VehicleState {
lat: f64,
lon: f64,
alt: f64,
speed: f64,
}
The remaining question then is how your different types of vehicles are going to be used.
Way 1: If different parts of the code use the different types of vehicles in distinct, non-overlapping ways, you might simply contain the state struct in the specific structs:
struct Cab {
state: VehicleState,
// ... other fields
}
struct PackerMover {
state: VehicleState,
// ... other fields
}
This is the version most directly analogous to C++ inheritance, particularly in memory layout and in static typing. However, this makes it awkward to access the common state for different vehicles, and it does not support dynamic dispatch, unless you write a trait with a method to access state (which comes with some limitations in the kinds of code you can write). You should generally avoid this approach unless you know you don't need anything else.
Way 2: If there is code which should be generic over which kind of vehicle is in use, but this is statically decided, you might make a generic struct:
struct Vehicle<T> {
state: VehicleState,
details: T,
}
struct Cab { /* ... */ }
struct PackerMover { /* ... */ }
/// This function only works with Cabs
fn foo(vehicle: Vehicle<Cab>) { /* ... */ }
/// This function works with any Vehicle
fn foo<T>(vehicle: Vehicle<T>) { /* ... */ }
This makes it easy to access the state, and all usage is statically dispatched.
It can be dynamically dispatched too if you make one small change to Vehicle and add a trait:
struct Vehicle<T: ?Sized> { /* ... */
// ^^^^^^^^ remove default restriction on the type parameter
trait VehicleDetails { /* add methods here */ }
impl VehicleDetails for Cab { /* ... */ }
impl VehicleDetails for PackerMover { /* ... */ }
This allows you to coerce a reference (or pointer or Box too) &Vehicle<Cab> into &Vehicle<dyn VehicleDetails>, which is a type that a pointer to any Vehicle whose T implements VehicleDetails. This can be used to put a variety of vehicles in a Vec<Box<Vehicle<dyn VehicleDetails>>>, for example. Using dyn causes dispatch through vtables, like C++ virtual methods.
(Info on this language feature. The documentation says that “custom DSTs are a largely half-baked feature for now” but this particular case is exactly the case where they do work without any trouble.)
This is not a good choice if you want to be able to find out which “subclass” is being used and interact with it specifically; it is a good choice if all particular characteristics of the vehicle can be expressed within the VehicleDetails trait.
Way 3: If the application is going to be routinely working with dynamically-chosen vehicle types — especially if it frequently wants to ask the question “is this vehicle a Cab” and then interact with its Cabness — then you should probably use an enum to contain the details.
struct Vehicle {
state: VehicleState,
kind: VehicleKind,
}
enum VehicleKind {
Cab {
seats: u16,
},
PackerMover {
cargo_capacity: u64,
}
}
This is dynamically dispatched in the sense that every Vehicle can be any kind, so you can always mix-and-match vehicle kinds, but without involving any pointers or vtables. The main disadvantage is that extending it to new kinds requires modifying the single enum VehicleKind, so this is not suitable for a library whose users would be writing subclasses in C++. However, this is a lot less fiddly to work with than the Vehicle<dyn VehicleDetails> I mentioned above.
Rust is basically more like a procedural and a functional language with some pseudo-OO features, it’s simultaneously lower-level and more abstract than C++ (closer to C or even to C—, but with ZCA and stronger typing). The answer is: there’s no inheritance in Rust, use composition or just rewrite the whole structure. This may look wild for you, but after some time you will understand that there’s no need in inheritance.

Use templates to clone class types exactly?

I have a series of C++ classes that I wish to all be identical in functionality, but otherwise not related by inheritance. Effectively, these classes would differ in name only. (These classes will be thrown, and I do not want a catch clause for some base class to gobble up thrown derived objects. There will be derived classes, but I wish to create discrete sets of thrown classes that are always segregated, as far as catch blocks are concerned.)
Of course, the downside to this is duplicating source code. I don't want to have to update N copies of the same code, whenever something needs to be changed.
I have already solved the code duplication problem via #define. But I think it would aid debug-ability if I could leverage templates, instead. The only thing parameterized in the template will be the class name itself.
I attempted the following, which did not work in gcc (w/ c++0x support enabled):
template<typename ClassName>
class ClassName
{
public:
ClassName(int foo, float bar) { ... }
~ClassName() { ... }
bool SomePublicMethod() { ... }
private:
...
}
Then I would declare the actual classes with something akin to:
typedef ClassName<UnrelatedClass1> UnrelatedClass1;
typedef ClassName<UnrelatedClass2> UnrelatedClass2;
I already know that the above does not work; I am providing it as a conceptual example of what I would like to accomplish, and am wondering if there is a way to make it work, other than the #define macro method that I am presently using (which suffers from diminished debug-ability.)
Use value specialized template:
template<int ID>
class ClassName
{
public:
ClassName(int foo, float bar) { ... }
~ClassName() { ... }
bool SomePublicMethod() { ... }
private:
...
}
typedef ClassName<1> UnrelatedClass1;
typedef ClassName<2> UnrelatedClass2;
This doesn't sound like a very good idea at all.
Exceptions classes should capture a specific type of error, with inheritance used to more generalise the type of error.
So for example you might have a 'disk crashed exception', which more generally might be a 'disk exception' and more generally and 'io exception' and always at its core an 'std::exception'
If all your exceptions are catching different types/classes of error, then why would they all have the same type of implementation.
Also it's uncommon to see #define mixed in the templates because that invariably makes it less readable when there is a compiler error (even if it seems more readable when it is no causing errors).
Perhaps you could provide more information about what is implemented in your exception classes, and I can see if I can help you further.
I do agree with others when they say that you should use inheritance. It is great for many purposes (one of them being the reason why you would like to have similar classes). It is not compulsory to write derived classes only when the objects are related - it is great even if just the functionality that is matching because your idea really is to put similar code together.
However, since your query was about creating multiple classes and we do not have enough view of your project, I believe it is possible that you may really need separate classes. One way of doing this is through macros. Here's a sample:
#include <iostream>
using std::cout;
using std::endl;
#define CUSTOM_CLASS(_CL) class _CL\
{\
public:\
_CL(int foo, float bar) { cout << "Creating instance with foo=" << foo << ";bar=" << bar << endl;}\
~_CL() { }\
bool SomePublicMethod() { cout << "Class created\n"; }\
};
CUSTOM_CLASS(myclass1);
CUSTOM_CLASS(myclass2);
int main()
{
myclass1 instance1(1, 1.3f);
myclass2 instance2(2, 0.3f);
return 0;
}
If you run this using g++, you will get the following result:
Creating instance with foo=1;bar=1.3
Creating instance with foo=2;bar=0.3

Practical use of dynamic_cast?

I have a pretty simple question about the dynamic_cast operator. I know this is used for run time type identification, i.e., to know about the object type at run time. But from your programming experience, can you please give a real scenario where you had to use this operator? What were the difficulties without using it?
Toy example
Noah's ark shall function as a container for different types of animals. As the ark itself is not concerned about the difference between monkeys, penguins, and mosquitoes, you define a class Animal, derive the classes Monkey, Penguin, and Mosquito from it, and store each of them as an Animal in the ark.
Once the flood is over, Noah wants to distribute animals across earth to the places where they belong and hence needs additional knowledge about the generic animals stored in his ark. As one example, he can now try to dynamic_cast<> each animal to a Penguin in order to figure out which of the animals are penguins to be released in the Antarctic and which are not.
Real life example
We implemented an event monitoring framework, where an application would store runtime-generated events in a list. Event monitors would go through this list and examine those specific events they were interested in. Event types were OS-level things such as SYSCALL, FUNCTIONCALL, and INTERRUPT.
Here, we stored all our specific events in a generic list of Event instances. Monitors would then iterate over this list and dynamic_cast<> the events they saw to those types they were interested in. All others (those that raise an exception) are ignored.
Question: Why can't you have a separate list for each event type?
Answer: You can do this, but it makes extending the system with new events as well as new monitors (aggregating multiple event types) harder, because everyone needs to be aware of the respective lists to check for.
A typical use case is the visitor pattern:
struct Element
{
virtual ~Element() { }
void accept(Visitor & v)
{
v.visit(this);
}
};
struct Visitor
{
virtual void visit(Element * e) = 0;
virtual ~Visitor() { }
};
struct RedElement : Element { };
struct BlueElement : Element { };
struct FifthElement : Element { };
struct MyVisitor : Visitor
{
virtual void visit(Element * e)
{
if (RedElement * p = dynamic_cast<RedElement*>(e))
{
// do things specific to Red
}
else if (BlueElement * p = dynamic_cast<BlueElement*>(e))
{
// do things specific to Blue
}
else
{
// error: visitor doesn't know what to do with this element
}
}
};
Now if you have some Element & e;, you can make MyVisitor v; and say e.accept(v).
The key design feature is that if you modify your Element hierarchy, you only have to edit your visitors. The pattern is still fairly complex, and only recommended if you have a very stable class hierarchy of Elements.
Imagine this situation: You have a C++ program that reads and displays HTML. You have a base class HTMLElement which has a pure virtual method displayOnScreen. You also have a function called renderHTMLToBitmap, which draws the HTML to a bitmap. If each HTMLElement has a vector<HTMLElement*> children;, you can just pass the HTMLElement representing the element <html>. But what if a few of the subclasses need special treatment, like <link> for adding CSS. You need a way to know if an element is a LinkElement so you can give it to the CSS functions. To find that out, you'd use dynamic_cast.
The problem with dynamic_cast and polymorphism in general is that it's not terribly efficient. When you add vtables into the mix, it only get's worse.
When you add virtual functions to a base class, when they are called, you end up actually going through quite a few layers of function pointers and memory areas. That will never be more efficient than something like the ASM call instruction.
Edit: In response to Andrew's comment bellow, here's a new approach: Instead of dynamic casting to the specific element type (LinkElement), instead you have another abstract subclass of HTMLElement called ActionElement that overrides displayOnScreen with a function that displays nothing, and creates a new pure virtual function: virtual void doAction() const = 0. The dynamic_cast is changed to test for ActionElement and just calls doAction(). You'd have the same kind of subclass for GraphicalElement with a virtual method displayOnScreen().
Edit 2: Here's what a "rendering" method might look like:
void render(HTMLElement root) {
for(vector<HTLMElement*>::iterator i = root.children.begin(); i != root.children.end(); i++) {
if(dynamic_cast<ActionElement*>(*i) != NULL) //Is an ActionElement
{
ActionElement* ae = dynamic_cast<ActionElement*>(*i);
ae->doAction();
render(ae);
}
else if(dynamic_cast<GraphicalElement*>(*i) != NULL) //Is a GraphicalElement
{
GraphicalElement* ge = dynamic_cast<GraphicalElement*>(*i);
ge->displayToScreen();
render(ge);
}
else
{
//Error
}
}
}
Operator dynamic_cast solves the same problem as dynamic dispatch (virtual functions, visitor pattern, etc): it allows you to perform different actions based on the runtime type of an object.
However, you should always prefer dynamic dispatch, except perhaps when the number of dynamic_cast you'd need will never grow.
Eg. you should never do:
if (auto v = dynamic_cast<Dog*>(animal)) { ... }
else if (auto v = dynamic_cast<Cat*>(animal)) { ... }
...
for maintainability and performance reasons, but you can do eg.
for (MenuItem* item: items)
{
if (auto submenu = dynamic_cast<Submenu*>(item))
{
auto items = submenu->items();
draw(context, items, position); // Recursion
...
}
else
{
item->draw_icon();
item->setup_accelerator();
...
}
}
which I've found quite useful in this exact situation: you have one very particular subhierarchy that must be handled separately, this is where dynamic_cast shines. But real world examples are quite rare (the menu example is something I had to deal with).
dynamic_cast is not intended as an alternative to virtual functions.
dynamic_cast has a non-trivial performance overhead (or so I think) since the whole class hierarchy has to be walked through.
dynamic_cast is similar to the 'is' operator of C# and the QueryInterface of good old COM.
So far I have found one real use of dynamic_cast:
(*) You have multiple inheritance and to locate the target of the cast the compiler has to walk the class hierarchy up and down to locate the target (or down and up if you prefer). This means that the target of the cast is in a parallel branch in relation to where the source of the cast is in the hierarchy. I think there is NO other way to do such a cast.
In all other cases, you just use some base class virtual to tell you what type of object you have and ONLY THEN you dynamic_cast it to the target class so you can use some of it's non-virtual functionality. Ideally there should be no non-virtual functionality, but what the heck, we live in the real world.
Doing things like:
if (v = dynamic_cast(...)){} else if (v = dynamic_cast(...)){} else if ...
is a performance waste.
Casting should be avoided when possible, because it is basically saying to the compiler that you know better and it is usually a sign of some weaker design decission.
However, you might come in situations where the abstraction level was a bit too high for 1 or 2 sub-classes, where you have the choice to change your design or solve it by checking the subclass with dynamic_cast and handle it in a seperate branch. The trade-of is between adding extra time and risk now against extra maintenance issues later.
In most situations where you are writing code in which you know the type of the entity you're working with, you just use static_cast as it's more efficient.
Situations where you need dynamic cast typically arrive (in my experience) from lack of foresight in design - typically where the designer fails to provide an enumeration or id that allows you to determine the type later in the code.
For example, I've seen this situation in more than one project already:
You may use a factory where the internal logic decides which derived class the user wants rather than the user explicitly selecting one. That factory, in a perfect world, returns an enumeration which will help you identify the type of returned object, but if it doesn't you may need to test what type of object it gave you with a dynamic_cast.
Your follow-up question would obviously be: Why would you need to know the type of object that you're using in code using a factory?
In a perfect world, you wouldn't - the interface provided by the base class would be sufficient for managing all of the factories' returned objects to all required extents. People don't design perfectly though. For example, if your factory creates abstract connection objects, you may suddenly realize that you need to access the UseSSL flag on your socket connection object, but the factory base doesn't support that and it's not relevant to any of the other classes using the interface. So, maybe you would check to see if you're using that type of derived class in your logic, and cast/set the flag directly if you are.
It's ugly, but it's not a perfect world, and sometimes you don't have time to refactor an imperfect design fully in the real world under work pressure.
The dynamic_cast operator is very useful to me.
I especially use it with the Observer pattern for event management:
#include <vector>
#include <iostream>
using namespace std;
class Subject; class Observer; class Event;
class Event { public: virtual ~Event() {}; };
class Observer { public: virtual void onEvent(Subject& s, const Event& e) = 0; };
class Subject {
private:
vector<Observer*> m_obs;
public:
void attach(Observer& obs) { m_obs.push_back(& obs); }
public:
void notifyEvent(const Event& evt) {
for (vector<Observer*>::iterator it = m_obs.begin(); it != m_obs.end(); it++) {
if (Observer* const obs = *it) {
obs->onEvent(*this, evt);
}
}
}
};
// Define a model with events that contain data.
class MyModel : public Subject {
public:
class Evt1 : public Event { public: int a; string s; };
class Evt2 : public Event { public: float f; };
};
// Define a first service that processes both events with their data.
class MyService1 : public Observer {
public:
virtual void onEvent(Subject& s, const Event& e) {
if (const MyModel::Evt1* const e1 = dynamic_cast<const MyModel::Evt1*>(& e)) {
cout << "Service1 - event Evt1 received: a = " << e1->a << ", s = " << e1->s << endl;
}
if (const MyModel::Evt2* const e2 = dynamic_cast<const MyModel::Evt2*>(& e)) {
cout << "Service1 - event Evt2 received: f = " << e2->f << endl;
}
}
};
// Define a second service that only deals with the second event.
class MyService2 : public Observer {
public:
virtual void onEvent(Subject& s, const Event& e) {
// Nothing to do with Evt1 in Service2
if (const MyModel::Evt2* const e2 = dynamic_cast<const MyModel::Evt2*>(& e)) {
cout << "Service2 - event Evt2 received: f = " << e2->f << endl;
}
}
};
int main(void) {
MyModel m; MyService1 s1; MyService2 s2;
m.attach(s1); m.attach(s2);
MyModel::Evt1 e1; e1.a = 2; e1.s = "two"; m.notifyEvent(e1);
MyModel::Evt2 e2; e2.f = .2f; m.notifyEvent(e2);
}
Contract Programming and RTTI shows how you can use dynamic_cast to allow objects to advertise what interfaces they implement. We used it in my shop to replace a rather opaque metaobject system. Now we can clearly describe the functionality of objects, even if the objects are introduced by a new module several weeks/months after the platform was 'baked' (though of course the contracts need to have been decided on up front).

Testing a c++ class for features

I have a set of classes that describe a set of logical boxes that can hold things and do things to them. I have
struct IBox // all boxes do these
{
....
}
struct IBoxCanDoX // the power to do X
{
void x();
}
struct IBoxCanDoY // the power to do Y
{
void y();
}
I wonder what is the 'best' or maybe its just 'favorite' idiom for a client of these classes to deal with these optional capabilities
a)
if(typeid(box) == typeid(IBoxCanDoX))
{
IBoxCanDoX *ix = static_cast<IBoxCanDoX*>(box);
ix->x();
}
b)
IBoxCanDoX *ix = dynamic_cast<IBoxCanDoX*>(box);
if(ix)
{
ix->x();
}
c)
if(box->canDoX())
{
IBoxCanDoX *ix = static_cast<IBoxCanDoX*>(box);
ix->x();
}
d) different class struct now
struct IBox
{
void x();
void y();
}
...
box->x(); /// ignored by implementations that dont do x
e) same except
box->x() // 'not implemented' exception thrown
f) explicit test function
if(box->canDoX())
{
box->x();
}
I am sure there are others too.
EDIT:
Just to make the use case clearer
I am exposing this stuff to end users via interactive ui. They can type 'make box do X'. I need to know if box can do x. Or I need to disable the 'make current box do X' command
EDIT2: Thx to all answerers
as Noah Roberts pointed out (a) doesnt work (explains some of my issues !).
I ended up doing (b) and a slight variant
template<class T>
T* GetCurrentBox()
{
if (!current_box)
throw "current box not set";
T* ret = dynamic_cast<T*>(current_box);
if(!ret)
throw "current box doesnt support requested operation";
return ret;
}
...
IBoxCanDoX *ix = GetCurrentBox<IBoxCanDoX>();
ix->x();
and let the UI plumbing deal nicely with the exceptions (I am not really throwing naked strings).
I also intend to explore Visitor
I suggest the Visitor pattern for double-dispatch problems like this in C++:
class IVisitor
{
public:
virtual void Visit(IBoxCanDoX *pBox) = 0;
virtual void Visit(IBoxCanDoY *pBox) = 0;
virtual void Visit(IBox* pBox) = 0;
};
class IBox // all boxes do these
{
public:
virtual void Accept(IVisitor *pVisitor)
{
pVisitor->Visit(this);
}
};
class BoxCanDoY : public IBox
{
public:
virtual void Accept(IVisitor *pVisitor)
{
pVisitor->Visit(this);
}
};
class TestVisitor : public IVisitor
{
public:
// override visit methods to do tests for each type.
};
void Main()
{
BoxCanDoY y;
TestVisitor v;
y.Accept(&v);
}
Of the options you've given, I'd say that b or d are "best". However, the need to do a lot of this sort of thing is often indicative of a poor design, or of a design that would be better implemented in a dynamically typed language rather than in C++.
If you are using the 'I' prefix to mean "interface" as it would mean in Java, which would be done with abstract bases in C++, then your first option will fail to work....so that one's out. I have used it for some things though.
Don't do 'd', it will pollute your hierarchy. Keep your interfaces clean, you'll be glad you did. Thus a Vehicle class doesn't have a pedal() function because only some vehicles can pedal. If a client needs the pedal() function then it really does need to know about those classes that can.
Stay way clear of 'e' for the same reason as 'd' PLUS that it violates the Liskov Substitution Principle. If a client needs to check that a class responds to pedal() before calling it so that it doesn't explode then the best way to do that is to attempt casting to an object that has that function. 'f' is just the same thing with the check.
'c' is superfluous. If you have your hierarchy set up the way it should be then casting to ICanDoX is sufficient to check if x can do X().
Thus 'b' becomes your answer from the options given. However, as Gladfelter demonstrates, there are options you haven't considered in your post.
Edit note: I did not notice that 'c' used a static_cast rather than dynamic. As I mention in an answer about that, the dynamic_cast version is cleaner and should be preferred unless specific situations dictate otherwise. It's similar to the following options in that it pollutes the base interface.
Edit 2: I should note that in regard to 'a', I have used it but I don't use types statically like you have in your post. Any time I've used typeid to split flow based on type it has always been based on something that is registered during runtime. For example, opening the correct dialog to edit some object of unknown type: the dialog governors are registered with a factory based on the type they edit. This keeps me from having to change any of the flow control code when I add/remove/change objects. I generally wouldn't use this option under different circumstances.
A and B require run time type identification(RTTI) and might be slower if you are doing a lot checks. Personally I don't like the solutions of "canDoX" methods, if situations like this arise the design probably needs an upgrade because you are exposing information that is not relevant to the class.
If you only need to execute X or Y, depending on the class, I would go for a virtual method in IBox which get overridden in subclasses.
class IBox{
virtual void doThing();
}
class IBoxCanDoX: public IBox{
void doThing() { doX(); }
void doX();
}
class IBoxCanDoY: public IBox{
void doThing() { doY(); }
void doY();
}
box->doThing();
If that solution is not applicable or you need more complex logic, then look at the Visitor design pattern. But keep in mind that the visitor pattern is not very flexible when you add new classes regularly or methods change/are added/are removed (but that also goes true for your proposed alternatives).
If you are trying to call either of these classes actions from contingent parts of code, you I would suggest you wrap that code in a template function and name each class's methods the same way to implement duck typing, thus your client code would look like this.
template<class box>
void box_do_xory(box BOX){
BOX.xory();
}
There is no general answer to your question. Everything depends. I can say only that:
- don't use a), use b) instead
- b) is nice, requires least code, no need for dummy methods, but dynamic_cast is a little slow
- c) is similar to b) but it is faster (no dynamic_cast) and requires more memory
- e) has no sense, you still need to discover if you can call the method so the exception is not thrown
- d) is better then f) (less code to write)
- d) e) and f) produce more garbage code then others, but are faster and less memory consuming
I assume that you will not only be working with one object of one type here.
I would lay out the data that you are working with and try to see how you can lay it out in memory in order to do data-driven programming. A good layout in memory should reflect the way that you store the data in your classes and how the classes are layed out in memory. Once you have that basic design structured (shouldn't take more than a napkin), I would begin organizing the objects into lists dependent on the operations that you plan to do on the data. If you plan to do X() on a collection of objects { Y } in the subset X, I would probably make sure to have a static array of Y that I create from the beginning. If you wish to access the entire of X occasionally, that can be arranged by collecting the lists into a dynamic list of pointers (using std::vector or your favorite choice).
I hope that makes sense, but once implemented it gives simple straight solutions that are easy to understand and easy to work with.
There is a generic way to test if a class supports a certain concept and then to execute the most appropriate code. It uses SFINAE hack. This example is inspired by Abrahams and Gurtovoy's "C++ Template Metaprogramming" book. The function doIt will use x method if it is present, otherwise it will use y method. You can extend CanDo structure to test for other methods as well. You can test as many methods as you wish, as long as the overloads of doIt can be resolved uniquely.
#include <iostream>
#include <boost/config.hpp>
#include <boost/utility/enable_if.hpp>
typedef char yes; // sizeof(yes) == 1
typedef char (&no)[2]; // sizeof(no) == 2
template<typename T>
struct CanDo {
template<typename U, void (U::*)()>
struct ptr_to_mem {};
template<typename U>
static yes testX(ptr_to_mem<U, &U::x>*);
template<typename U>
static no testX(...);
BOOST_STATIC_CONSTANT(bool, value = sizeof(testX<T>(0)) == sizeof(yes));
};
struct DoX {
void x() { std::cout << "doing x...\n"; }
};
struct DoAnotherX {
void x() { std::cout << "doing another x...\n"; }
};
struct DoY {
void y() { std::cout << "doing y...\n"; }
};
struct DoAnotherY {
void y() { std::cout << "doing another y...\n"; }
};
template <typename Action>
typename boost::enable_if<CanDo<Action> >::type
doIt(Action* a) {
a->x();
}
template <typename Action>
typename boost::disable_if<CanDo<Action> >::type
doIt(Action* a) {
a->y();
}
int main() {
DoX doX;
DoAnotherX doAnotherX;
DoY doY;
DoAnotherY doAnotherY;
doIt(&doX);
doIt(&doAnotherX);
doIt(&doY);
doIt(&doAnotherY);
}

Storing a list of arbitrary objects in C++

In Java, you can have a List of Objects. You can add objects of multiple types, then retrieve them, check their type, and perform the appropriate action for that type.
For example: (apologies if the code isn't exactly correct, I'm going from memory)
List<Object> list = new LinkedList<Object>();
list.add("Hello World!");
list.add(7);
list.add(true);
for (object o : list)
{
if (o instanceof int)
; // Do stuff if it's an int
else if (o instanceof String)
; // Do stuff if it's a string
else if (o instanceof boolean)
; // Do stuff if it's a boolean
}
What's the best way to replicate this behavior in C++?
boost::variant is similar to dirkgently's suggestion of boost::any, but supports the Visitor pattern, meaning it's easier to add type-specific code later. Also, it allocates values on the stack rather than using dynamic allocation, leading to slightly more efficient code.
EDIT: As litb points out in the comments, using variant instead of any means you can only hold values from one of a prespecified list of types. This is often a strength, though it might be a weakness in the asker's case.
Here is an example (not using the Visitor pattern though):
#include <vector>
#include <string>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
...
vector<variant<int, string, bool> > v;
for (int i = 0; i < v.size(); ++i) {
if (int* pi = get<int>(v[i])) {
// Do stuff with *pi
} else if (string* si = get<string>(v[i])) {
// Do stuff with *si
} else if (bool* bi = get<bool>(v[i])) {
// Do stuff with *bi
}
}
(And yes, you should technically use vector<T>::size_type instead of int for i's type, and you should technically use vector<T>::iterator instead anyway, but I'm trying to keep it simple.)
Your example using Boost.Variant and a visitor:
#include <string>
#include <list>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
using namespace std;
using namespace boost;
typedef variant<string, int, bool> object;
struct vis : public static_visitor<>
{
void operator() (string s) const { /* do string stuff */ }
void operator() (int i) const { /* do int stuff */ }
void operator() (bool b) const { /* do bool stuff */ }
};
int main()
{
list<object> List;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
BOOST_FOREACH (object& o, List) {
apply_visitor(vis(), o);
}
return 0;
}
One good thing about using this technique is that if, later on, you add another type to the variant and you forget to modify a visitor to include that type, it will not compile. You have to support every possible case. Whereas, if you use a switch or cascading if statements, it's easy to forget to make the change everywhere and introduce a bug.
C++ does not support heterogenous containers.
If you are not going to use boost the hack is to create a dummy class and have all the different classes derive from this dummy class. Create a container of your choice to hold dummy class objects and you are ready to go.
class Dummy {
virtual void whoami() = 0;
};
class Lizard : public Dummy {
virtual void whoami() { std::cout << "I'm a lizard!\n"; }
};
class Transporter : public Dummy {
virtual void whoami() { std::cout << "I'm Jason Statham!\n"; }
};
int main() {
std::list<Dummy*> hateList;
hateList.insert(new Transporter());
hateList.insert(new Lizard());
std::for_each(hateList.begin(), hateList.end(),
std::mem_fun(&Dummy::whoami));
// yes, I'm leaking memory, but that's besides the point
}
If you are going to use boost you can try boost::any. Here is an example of using boost::any.
You may find this excellent article by two leading C++ experts of interest.
Now, boost::variant is another thing to look out for as j_random_hacker mentioned. So, here's a comparison to get a fair idea of what to use.
With a boost::variant the code above would look something like this:
class Lizard {
void whoami() { std::cout << "I'm a lizard!\n"; }
};
class Transporter {
void whoami() { std::cout << "I'm Jason Statham!\n"; }
};
int main() {
std::vector< boost::variant<Lizard, Transporter> > hateList;
hateList.push_back(Lizard());
hateList.push_back(Transporter());
std::for_each(hateList.begin(), hateList.end(), std::mem_fun(&Dummy::whoami));
}
How often is that sort of thing actually useful? I've been programming in C++ for quite a few years, on different projects, and have never actually wanted a heterogenous container. It may be common in Java for some reason (I have much less Java experience), but for any given use of it in a Java project there might be a way to do something different that will work better in C++.
C++ has a heavier emphasis on type safety than Java, and this is very type-unsafe.
That said, if the objects have nothing in common, why are you storing them together?
If they do have things in common, you can make a class for them to inherit from; alternately, use boost::any. If they inherit, have virtual functions to call, or use dynamic_cast<> if you really have to.
I'd just like to point out that using dynamic type casting in order to branch based on type often hints at flaws in the architecture. Most times you can achieve the same effect using virtual functions:
class MyData
{
public:
// base classes of polymorphic types should have a virtual destructor
virtual ~MyData() {}
// hand off to protected implementation in derived classes
void DoSomething() { this->OnDoSomething(); }
protected:
// abstract, force implementation in derived classes
virtual void OnDoSomething() = 0;
};
class MyIntData : public MyData
{
protected:
// do something to int data
virtual void OnDoSomething() { ... }
private:
int data;
};
class MyComplexData : public MyData
{
protected:
// do something to Complex data
virtual void OnDoSomething() { ... }
private:
Complex data;
};
void main()
{
// alloc data objects
MyData* myData[ 2 ] =
{
new MyIntData()
, new MyComplexData()
};
// process data objects
for ( int i = 0; i < 2; ++i ) // for each data object
{
myData[ i ]->DoSomething(); // no type cast needed
}
// delete data objects
delete myData[0];
delete myData[1];
};
Sadly there is no easy way of doing this in C++. You have to create a base class yourself and derive all other classes from this class. Create a vector of base class pointers and then use dynamic_cast (which comes with its own runtime overhead) to find the actual type.
Just for completeness of this topic I want to mention that you can actually do this with pure C by using void* and then casting it into whatever it has to be (ok, my example isn't pure C since it uses vectors but that saves me some code). This will work if you know what type your objects are, or if you store a field somewhere which remembers that. You most certainly DON'T want to do this but here is an example to show that it's possible:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int a = 4;
string str = "hello";
vector<void*> list;
list.push_back( (void*) &a );
list.push_back( (void*) &str );
cout << * (int*) list[0] << "\t" << * (string*) list[1] << endl;
return 0;
}
While you cannot store primitive types in containers, you can create primitive type wrapper classes which will be similar to Java's autoboxed primitive types (in your example the primitive typed literals are actually being autoboxed); instances of which appear in C++ code (and can (almost) be used) just like primitive variables/data members.
See Object Wrappers for the Built-In Types from Data Structures and Algorithms with Object-Oriented Design Patterns in C++.
With the wrapped object you can use the c++ typeid() operator to compare the type.
I am pretty sure the following comparison will work:
if (typeid(o) == typeid(Int)) [where Int would be the wrapped class for the int primitive type, etc...]
(otherwise simply add a function to your primitive wrappers that returns a typeid and thus:
if (o.get_typeid() == typeid(Int)) ...
That being said, with respect to your example, this has code smell to me.
Unless this is the only place where you are checking the type of the object,
I would be inclined to use polymorphism (especially if you have other methods/functions specific with respect to type). In this case I would use the primitive wrappers adding an interfaced class declaring the deferred method (for doing 'do stuff') that would be implemented by each of your wrapped primitive classes. With this you would be able to use your container iterator and eliminate your if statement (again, if you only have this one comparison of type, setting up the deferred method using polymorphism just for this would be overkill).
I am a fairly inexperienced, but here's what I'd go with-
Create a base class for all classes you need to manipulate.
Write container class/ reuse container class.
(Revised after seeing other answers -My previous point was too cryptic.)
Write similar code.
I am sure a much better solution is possible. I am also sure a better explanation is possible. I've learnt that I have some bad C++ programming habits, so I've tried to convey my idea without getting into code.
I hope this helps.
Beside the fact, as most have pointed out, you can't do that, or more importantly, more than likely, you really don't want to.
Let's dismiss your example, and consider something closer to a real-life example. Specifically, some code I saw in a real open-source project. It attempted to emulate a cpu in a character array. Hence it would put into the array a one byte "op code", followed by 0, 1 or 2 bytes which could be a character, an integer, or a pointer to a string, based on the op code. To handle that, it involved a lot of bit-fiddling.
My simple solution: 4 separate stacks<>s: One for the "opcode" enum and one each for chars, ints and string. Take the next off the opcode stack, and the would take you which of the other three to get the operand.
There's a very good chance your actual problem can be handled in a similar way.
Well, you could create a base class and then create classes which inherit from it. Then, store them in a std::vector.
The short answer is... you can't.
The long answer is... you'd have to define your own new heirarchy of objects that all inherit from a base object. In Java all objects ultimately descend from "Object", which is what allows you to do this.
RTTI (Run time type info) in C++ has always been tough, especially cross-compiler.
You're best option is to use STL and define an interface in order to determine the object type:
public class IThing
{
virtual bool isA(const char* typeName);
}
void myFunc()
{
std::vector<IThing> things;
// ...
things.add(new FrogThing());
things.add(new LizardThing());
// ...
for (int i = 0; i < things.length(); i++)
{
IThing* pThing = things[i];
if (pThing->isA("lizard"))
{
// do this
}
// etc
}
}
Mike