How to extract derived classes from the base-class container? - c++

After storing objects of different types in the same container using common parent class I need to extract them back.
[Tests/test0.c++]:
int main()
{
element wrapper;
wrapper.name = "div";
wrapper.attributes["id"] = "wrapper";
cargo<string> text("Learn from yesterday, live for today, hope for tomorrow.");
wrapper.children.push_back(&text);
cout << "Name:\t" << wrapper.name << endl;
/* I have an explicit cast here,
* but it can't be used this way
* since children may have different types
*/
cout << "Cargo:\t" << ((cargo< string >*) wrapper.children[0])->value << endl;
return 0;
}
[Source/element.h]
struct element
{
std::string name;
std::map< std::string, std::string > attributes;
std::vector< node* > children;
};
[Source/node.h]
struct node
{ };
[Source/cargo.h]
template <typename Type>
struct cargo
: public node
{
Type value;
cargo(Type value)
: value(value)
{ }
};
I need to have some kind of type holder to be associated with real node type and use it in farther casting-extracting operations... Instead of that hard-coded one in my test.
UPDATE:
What I'm trying to do is a simple Document Object Model Data structure to use it as symbol table entry for my xml-like language parser. I don't want to use any existing XML library as they are very large. I think the idea of DOM is simple, so I can easily adopt it for some more complex operations, for example, by allowing generic types for the nodes in DOM tree using cargo<Type>. I recognize that the design I adopted may not be the most adequate! So I'm open to suggestions!
I would be thankful for any help!

This question is probably more about the design than implementation.
Although Boost.Variant and Boost.Any will work, they will be only a workaround. The real problem may be that variable part of responsibility of classes, derived from node class, is not encapsulated.
You could try to use composition instead. One host class used for common interface and appropriate amount of components/delegates/whatever (those are to be born from a solution design :) ).
Or... a totally different solution may fit you. You may want to venture to meta programing word and ditch the common interface. Instead entities like tuples (type lists) may be of help.
Best Regards,
Marcin

if you are simply streaming, you could implement the stream operators in the base class and then delegate to a method in the derived class, else look at the visitor pattern. Without having a real grasp of what kind of operations you are likely to be doing on cargo, it's difficult to make further suggestions...

If you don't plan on treating the container members polymorphically on retrieval, Boost.Variant might be useful to wrap the container members in a deterministic way.
The variant class template is a safe,
generic, stack-based discriminated
union container, offering a simple
solution for manipulating an object
from a heterogeneous set of types in a
uniform manner. Whereas standard
containers such as std::vector may be
thought of as "multi-value, single
type," variant is "multi-type, single
value."
There's some example code in this prior question.

You won't get along something like this without a cast.
But most importantly, this often means that you're going the wrong way. As long as you decided cargo would inherit publicly from node, you provided a very strong relationship between the two classes, and 'being a node' has a much stronger meaning than :
I can be inserted in a container
along with other node derived types
We need to know what is a node and what can be done with it to help you further. However if you really need to stick with your initial solution, boost.variant could help you.

You should design so the code doesn't care about the base class type. Provide an interface that is the same for all. Or add the pure virtual methods you need to the base class and implement in derived class.
Assuming that is some how not possible, have you tried dynamic_cast? It returns null if the cast fails, rather than throwing as your static_cast above will do.
Hope this helps,
Beezler

Related

Calling Templated C++ Method based on Runtime Logic

I often run into the problems associated with SubType Polymorphism, I'm looking for an elegant solution I may not already be aware of.
Here is a simple inheritence hierarchy:
struct BaseClass {
virtual ~BaseClass() = 0;
std::string name;
};
template <T>
struct DerivedClass
{
DerivedClass(const std::string& _name): name(_name) { }
};
Now I might create lots of these DerivedClass instances with different names and template types and store them in an array using their BaseClass.
std::vector<BaseClass*> array;
array.push_back(new DerivedClass<TABC>("abc"));
array.push_back(new DerivedClass<TDEF>("def"));
...
This is pretty standard runtime polymorphism.
However, when I have a new layer of functionality that is type-specific to add and don't want this new layer to be coupled in both directions, I end up having to do something like this:
template <typename T>
void method(DerivedClass<T>* object) { }
void callMethod(BaseClass* object)
{
// this is the logic I'm trying to move up a layer
if (object->name == "abc") method<TABC>(object);
else if (object->name == "def") method<TDEF>(object);
}
Each of these methods has to have the same list of run-time strings to compile-time types to convert, which means adding a new type requires a lot of changes.
If I was to assume the new layer would only support specific options known at compile-time (as is the case here anyway), then it would be feasible to add new types at runtime, but not be able to use them in this layer, which would be fine.
My current thinking is if I was to introduce a virtual method to the class hierarchy that took a function pointer, I could register the function pointers for each method in the second layer based on specific compile-time types (ideally only specified once), kind of like a double dispatch type method.
Any thoughts, suggestions?
You need that link to call the specific template version based on a string, the best you can do is have a dictionary of string->lambda function and use the string as a lookup to get a function<> to call. This avoids the nested ifs and it's relatively easy to maintain, both at compile time (the default list) and at runtime (any changes are just array changes).
Rather than steal Sean Parent's thunder I'll direct you to this talk which will show you how to achieve this cleanly, safely and simply.
The technique is called 'polymorphism as an implementation detail'. It has transformed the way I write code.
https://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil

runtime type comparison

I need to find the type of object pointed by pointer.
Code is as below.
//pWindow is pointer to either base Window object or derived Window objects like //Window_Derived.
const char* windowName = typeid(*pWindow).name();
if(strcmp(windowName, typeid(Window).name()) == 0)
{
// ...
}
else if(strcmp(windowName, typeid(Window_Derived).name()) == 0)
{
// ...
}
As i can't use switch statement for comparing string, i am forced to use if else chain.
But as the number of window types i have is high, this if else chain is becoming too lengthy.
Can we check the window type using switch or an easier method ?
EDIT: Am working in a logger module. I thought, logger should not call derived class virtual function for logging purpose. It should do on its own. So i dropped virtual function approach.
First of all use a higher level construct for strings like std::string.
Second, if you need to check the type of the window your design is wrong.
Use the Liskov substitution principle to design correctly.
It basically means that any of the derived Window objects can be replaced with it's super class.
This can only happen if both share the same interface and the derived classes don't violate the contract provided by the base class.
If you need some mechanism to apply behavior dynamically use the Visitor Pattern
Here are the things to do in order of preference:
Add a new virtual method to the base class and simply call it. Then put a virtual method of the same name in each derived class that implements the corresponding else if clause inside it. This is the preferred option as your current strategy is a widely recognized symptom of poor design, and this is the suggested remedy.
Use a ::std::map< ::std::string, void (*)(Window *pWindow)>. This will allow you to look up the function to call in a map, which is much faster and easier to add to. This will also require you to split each else if clause into its own function.
Use a ::std::map< ::std::string, int>. This will let you look up an integer for the corresponding string and then you can switch on the integer.
There are other refactoring strategies to use that more closely resemble option 1 here. For example,if you can't add a method to the Window class, you can create an interface class that has the needed method. Then you can make a function that uses dynamic_cast to figure out if the object implements the interface class and call the method in that case, and then handle the few remaining cases with your else if construct.
Create a dictionary (set/hashmap) with the strings as keys and the behaviour as value.
Using behaviour as values can be done in two ways:
Encapsulate each behaviour in it's
own class that inherit from an
interface with"DoAction" method that
execute the behavior
Use function pointers
Update:
I found this article that might be what you're looking for:
http://www.dreamincode.net/forums/topic/38412-the-command-pattern-c/
You might try putting all your typeid(...).name() values in a map, then doing a find() in the map. You could map to an int that can be used in a switch statement, or to a function pointer. Better yet, you might look again at getting a virtual function inside each of the types that does what you need.
What you ask for is possible, it's also unlikely to be a good solution to your problem.
Effectively the if/else if/else chain is ugly, the first solution that comes to mind will therefore to use a construct that will lift this, an associative container comes to mind and the default one is obviously std::unordered_map.
Thinking on the type of this container, you will realize that you need to use the typename as the key and associate it to a functor object...
However there are much more elegant constructs for this. The first of all will be of course the use of a virtual method.
class Base
{
public:
void execute() const { this->executeImpl(); }
private:
virtual void executeImpl() const { /* default impl */ }
};
class Derived: public Base
{
virtual void executeImpl() const { /* another impl */ }
};
It's the OO way of dealing with this type of requirement.
Finally, if you find yourself willing to add many different operations on your hierarchy, I will suggest the use of a well-known design pattern: Visitor. There is a variation called Acyclic Visitor which helps dealing with dependencies.

C++ Any way to store different templated object into the same container

Is there any hack I could use to do this:
template <class TYPE>
class Hello
{
TYPE _var;
};
I would like a way to store
Hello<int> intHello and Hello<char*> charHello
into the same Container such as a Queue / List.
No, because they are different and completely unrelated types.
You can, however, use inheritance and smart pointers:
class HelloBase
{
public:
virtual ~HelloBase();
}
template <class TYPE>
class Hello : public HelloBase
{
TYPE _var;
}
std::vector<boost::shared_ptr<HelloBase> > v;
shared_ptr may be supported by your implementation either in the std::tr1 or std namespace; you'd have to check.
Yes, sort of -- but you probably don't want to. Even though they start from the same template, Hello<int> and Hello<char *> are completely separate and unrelated types. A collection that includes both is heterogeneous, with all the problems that entails.
If you insist on doing this anyway, to do it reasonably cleanly, you'd typically create something like a queue/list of Boost::any.
First of all, the real question: what are you trying to achieve (at a higher level) ?
Now, for this peculiar question there is a number of alternative. Containers cannot store heterogeneous data, so you can:
give all Hello<T> a common base class and add virtual methods, then use pointers, take care of memory ownership (unique_ptr or boost::ptr_list would be great)
if there is a precise set of types, use boost::variant, it's statically checked so you have reasonable guarantees
else you should consider wrapping it into a storage class which would use boost::any under the covers
The common base class is the usual approach in this situation. If there is no reason to have polymorphism, then use preferably variant and if nothing else any.

put different class in hierarchy in one container in C++

Some times we have to put different objects in the same hierarchy in one container. I read some article saying there are some tricks and traps. However, I have no big picture about this question. Actually, this happens a lot in the real word.
For example, a parking lot has to contain different types of cars; a zoo has to contain different types of animals; a book store has to contain different types of books.
I remember that one article saying neither of the following is a good design, but I forgot where it is.
vector<vehicle> parking_lot;
vector<*vehicle> parking_lot;
Can anybody offer some basic rules for this kind of question?
I learnt a lot writing my reply to a similar question by the same author, so I couldn't resist to do the same here. In short, I've written a benchmark to compare the following approaches to the problem of storing heterogeneous elements in a standard container:
Make a class for each type of element and have them all inherit from a common base and store polymorphic base pointers in a std::vector<boost::shared_ptr<Base> >. This is probably the more general and flexible solution:
struct Shape {
...
};
struct Point : public Shape {
...
};
struct Circle : public Shape {
...
};
std::vector<boost::shared_ptr<Shape> > shapes;
shapes.push_back(new Point(...));
shapes.push_back(new Circle(...));
shapes.front()->draw(); // virtual call
Same as (1) but store the polymorphic pointers in a boost::ptr_vector<Base>. This is a bit less general because the elements are owned exclusively by the vector, but it should suffice most of the times. One advantage of boost::ptr_vector is that it has the interface of a std::vector<Base> (without the *), so its simpler to use.
boost::ptr_vector<Shape> shapes;
shapes.push_back(new Point(...));
shapes.push_back(new Circle(...));
shapes.front().draw(); // virtual call
Use a C union that can contain all possible elements and then use a std::vector<UnionType>. This is not very flexible as we need to know all element types in advance (they are hard-coded into the union) and also unions are well known for not interacting nicely with other C++ constructs (for example, the stored types can't have constructors).
struct Point {
...
};
struct Circle {
...
};
struct Shape {
enum Type { PointShape, CircleShape };
Type type;
union {
Point p;
Circle c;
} data;
};
std::vector<Shape> shapes;
Point p = { 1, 2 };
shapes.push_back(p);
if(shapes.front().type == Shape::PointShape)
draw_point(shapes.front());
Use a boost::variant that can contain all possible elements and then use a std::vector<Variant>. This is not very flexible like the union but the code to deal with it is much more elegant.
struct Point {
...
};
struct Circle {
...
};
typedef boost::variant<Point, Circle> Shape;
std::vector<Shape> shapes;
shapes.push_back(Point(1,2));
draw_visitor(shapes.front()); // use boost::static_visitor
Use boost::any (which can contain anything) and then a std::vector<boost::any>. That is very flexible but the interface is a little clumsy and error prone.
struct Point {
...
};
struct Circle {
...
};
typedef boost::any Shape;
std::vector<Shape> shapes;
shapes.push_back(Point(1,2));
if(shapes.front().type() == typeid(Point))
draw_point(shapes.front());
This is the code of the full benchmark program (doesn't run on codepad for some reason). And here are my performance results:
time with hierarchy and boost::shared_ptr: 0.491 microseconds
time with hierarchy and boost::ptr_vector: 0.249 microseconds
time with union: 0.043 microseconds
time with boost::variant: 0.043 microseconds
time with boost::any: 0.322 microseconds
My conclusions:
Use vector<shared_ptr<Base> > only if you need the flexibility provided by runtime polymorphism and if you need shared ownership. Otherwise you'll have significant overhead.
Use boost::ptr_vector<Base> if you need runtime polymorphism but don't care about shared ownership. It will be significantly faster than the shared_ptr counterpart and the interface will be more friendly (stored elements not presented like pointers).
Use boost::variant<A, B, C> if you don't need much flexibility (i.e. you have a small set of types which will not grow). It will be lighting fast and the code will be elegant.
Use boost::any if you need total flexibility (you want to store anything).
Don't use unions. If you really need speed then boost::variant is as fast.
Before I finish I want to mention that a vector of std::unique_ptr will be a good option when it becomes widely available (I think it's already in VS2010)
The problem with vector<vehicle> is that the object only holds vehicles. The problem with vector<vehicle*> is that you need to allocate and, more importantly, free the pointers appropriately.
This might be acceptable, depending on your project, etc...
However, one usually uses some kind of smart-ptr in the vector (vector<boost::shared_ptr<vehicle>> or Qt-something, or one of your own) that handles deallocation, but still permits storing different types objects in the same container.
Update
Some people have, in other answers/comments, also mentioned boost::ptr_vector. That works well as a container-of-ptr's too, and solves the memory deallocation problem by owning all the contained elements. I prefer vector<shared_ptr<T>> as I can then store objects all over the place, and move them using in and out of containers w/o issues. It's a more generic usage model that I've found is easier for me and others to grasp, and applies better to a larger set of problems.
The problems are:
You cannot place polymorphic objects into a container since they may differ in size --i.e., you must use a pointer.
Because of how containers work a normal pointer / auto pointer is not suitable.
The solution is :
Create a class hierarchy, and use at least one virtual function in your base class (if you can't think of any function to virtualize, virtualize the destructor -- which as Neil pointed out is generally a must).
Use a boost::shared_pointer (this will be in the next c++ standard) -- shared_ptr handles being copied around ad hoc, and containers may do this.
Build a class hierarchy and allocate your objects on the heap --i.e., by using new. The pointer to the base class must be encapsulated by a shared_ptr.
place the base class shared_pointer into your container of choice.
Once you understand the "whys and hows" of the points above look at the boost ptr_containers -- thanks to Manual for the tip.
Say vehicle is a base class, that has certain properties, then, inheriting from it you have say a car, and a truck. Then you can just do something like:
std::vector<vehicle *> parking_lot;
parking_lot.push_back(new car(x, y));
parking_lot.push_back(new truck(x1, y1));
This would be perfectly valid, and in fact very useful sometimes. The only requirement for this type of object handling is sane hierarchy of objects.
Other popular type of objects that can be used like that are e.g. people :) you see that in almost every programming book.
EDIT:
Of course that vector can be packed with boost::shared_ptr or std::tr1::shared_ptr instead of raw pointers for ease of memory management. And in fact that's something I would recommend to do by all means possible.
EDIT2:
I removed a not very relevant example, here's a new one:
Say you are to implement some kind of AV scanning functionality, and you have multiple scanning engines. So you implement some kind of engine management class, say scan_manager which can call bool scan(...) function of those. Then you make an engine interface, say engine. It would have a virtual bool scan(...) = 0; Then you make a few engines like my_super_engine and my_other_uber_engine, which both inherit from engine and implement scan(...). Then your engine manager would somewhere during initialization fill that std::vector<engine *> with instances of my_super_engine and my_other_uber_engine and use them by calling bool scan(...) on them either sequentially, or based on whatever types of scanning you'd like to perform. Obviously what those engines do in scan(...) remains unknown, the only interesting bit is that bool, so the manager can use them all in the same way without any modification.
Same can be applied to various game units, like scary_enemies and those would be orks, drunks and other unpleasant creatures. They all implement void attack_good_guys(...) and your evil_master would make many of them and call that method.
This is indeed a common practice, and I would hardly call it bad design for as long as all those types actually are related.
You can refer to this Stroustrup's answer to the question Why can't I assign a vector< Apple*> to a vector< Fruit*>?.

C++ alternatives to void* pointers (that isn't templates)

It looks like I had a fundamental misunderstanding about C++ :<
I like the polymorphic container solution. Thank you SO, for bringing that to my attention :)
So, we have a need to create a relatively generic container type object. It also happens to encapsulate some business related logic. However, we need to store essentially arbitrary data in this container - everything from primitive data types to complex classes.
Thus, one would immediately jump to the idea of a template class and be done with it. However, I have noticed C++ polymorphism and templates do not play well together. Being that there is some complex logic that we are going to have to work, I would rather just stick with either templates OR polymorphism, and not try to fight C++ by making it do both.
Finally, given that I want to do one or the other, I would prefer polymorphism. I find it much easier to represent constraints like "this container contains Comparable types" - a la java.
Bringing me to the topic of question: At the most abstract, I imagine that I could have a "Container" pure virtual interface that has something akin to "push(void* data) and pop(void* data)" (for the record, I am not actually trying to implement a stack).
However, I don't really like void* at the top level, not to mention the signature is going to change every time I want to add a constraint to the type of data a concrete container can work with.
Summarizing: We have relatively complex containers that have various ways to retrieve elements. We want to be able to vary the constraints on the elements that can go into the containers. Elements should work with multiple kinds of containers (so long as they meet the constraints of that particular container).
Edit: I should also mention that the containers themselves need to be polymorphic. That is my primary reason for not wanting to use templated C++.
So - should I drop my love for Java type interfaces and go with templates? Should I use void* and statically cast everything? Or should I go with an empty class definition "Element" that declares nothing and use that as my top level class in the "Element" hierarchy?
One of the reasons why I love stack overflow is that many of the responses provide some interesting insight on other approaches that I hadn't not have even considered. So thank you in advance for your insights and comments.
You can look at using a standard container of boost::any if you are storing truly arbitrary data into the container.
It sounds more like you would rather have something like a boost::ptr_container where anything that can be stored in the container has to derive from some base type, and the container itself can only give you reference's to the base type.
The simple thing is to define an abstract base class called Container, and subclass it for each kind of item you may wish to store. Then you can use any standard collection class (std::vector, std::list, etc.) to store pointers to Container. Keep in mind, that since you would be storing pointers, you would have to handle their allocation/deallocation.
However, the fact that you need a single collection to store objects of such wildly different types is an indication that something may be wrong with the design of your application. It may be better to revisit the business logic before you implement this super-generic container.
Polymorphism and templates do play very well together, if you use them correctly.
Anyway, I understand that you want to store only one type of objects in each container instance. If so, use templates. This will prevent you from storing the wrong object type by mistake.
As for container interfaces: Depending on your design, maybe you'll be able to make them templated, too, and then they'll have methods like void push(T* new_element). Think of what you'll know about the object when you want to add it to a container (of an unknown type). Where will the object come from in the first place? A function that returns void*? Do you know that it'll be Comparable? At least, if all stored object classes are defined in your code, you can make them all inherit from a common ancestor, say, Storable, and use Storable* instead of void*.
Now if you see that objects will always be added to a container by a method like void push(Storable* new_element), then really there will be no added value in making the container a template. But then you'll know it should store Storables.
Can you not have a root Container class that contains elements:
template <typename T>
class Container
{
public:
// You'll likely want to use shared_ptr<T> instead.
virtual void push(T *element) = 0;
virtual T *pop() = 0;
virtual void InvokeSomeMethodOnAllItems() = 0;
};
template <typename T>
class List : public Container<T>
{
iterator begin();
iterator end();
public:
virtual void push(T *element) {...}
virtual T* pop() { ... }
virtual void InvokeSomeMethodOnAllItems()
{
for(iterator currItem = begin(); currItem != end(); ++currItem)
{
T* item = *currItem;
item->SomeMethod();
}
}
};
These containers can then be passed around polymorphically:
class Item
{
public:
virtual void SomeMethod() = 0;
};
class ConcreteItem
{
public:
virtual void SomeMethod()
{
// Do something
}
};
void AddItemToContainer(Container<Item> &container, Item *item)
{
container.push(item);
}
...
List<Item> listInstance;
AddItemToContainer(listInstance, new ConcreteItem());
listInstance.InvokeSomeMethodOnAllItems();
This gives you the Container interface in a type-safe generic way.
If you want to add constraints to the type of elements that can be contained, you can do something like this:
class Item
{
public:
virtual void SomeMethod() = 0;
typedef int CanBeContainedInList;
};
template <typename T>
class List : public Container<T>
{
typedef typename T::CanBeContainedInList ListGuard;
// ... as before
};
First, of all, templates and polymorphism are orthogonal concepts and they do play well together. Next, why do you want a specific data structure? What about the STL or boost data structures (specifically pointer containter) doesn't work for you.
Given your question, it sounds like you would be misusing inheritance in your situation. It's possible to create "constraints" on what goes in your containers, especially if you are using templates. Those constraints can go beyond what your compiler and linker will give you. It's actually more awkward to that sort of thing with inheritance and errors are more likely left for run time.
Using polymorphism, you are basically left with a base class for the container, and derived classes for the data types. The base class/derived classes can have as many virtual functions as you need, in both directions.
Of course, this would mean that you would need to wrap the primitive data types in derived classes as well. If you would reconsider the use of templates overall, this is where I would use the templates. Make one derived class from the base which is a template, and use that for the primitive data types (and others where you don't need any more functionality than is provided by the template).
Don't forget that you might make your life easier by typedefs for each of the templated types -- especially if you later need to turn one of them into a class.
You might also want to check out The Boost Concept Check Library (BCCL) which is designed to provide constraints on the template parameters of templated classes, your containers in this case.
And just to reiterate what others have said, I've never had a problem mixing polymorphism and templates, and I've done some fairly complex stuff with them.
You could not have to give up Java-like interfaces and use templates as well. Josh's suggestion of a generic base template Container would certainly allow you do polymorphically pass Containers and their children around, but additionally you could certainly implement interfaces as abstract classes to be the contained items. There's no reason you couldn't create an abstract IComparable class as you suggested, such that you could have a polymorphic function as follows:
class Whatever
{
void MyPolymorphicMethod(Container<IComparable*> &listOfComparables);
}
This method can now take any child of Container that contains any class implementing IComparable, so it would be extremely flexible.