I'm new to c++ but have set my mind on a specific task that needs me to enable adding a specific chunk of code to be execute whenever any list item is attempted to be changed or read.
The resulting list should behave and look as much as as possible to std::list except for this small exception that would enable me to execute a specific tasks whenever this list is about to be read/written to.
From what i have found out so far, all i could think of is deriving a class from list::iterator and overloading it's operator* and operator= to implement these specific tasks.
Then i should derive a class from std::list and make it use my new iterator type by overloading begin() and end() methods. Or is there a better way of making it use a custom iterator?
That would handle the iterator access but I can see lists can even return pointers to it's members. I guess there is nothing i can do about them and will have to remove this feature from my new list class.
I would appreciate your oppinion on this subject.
Deriving from std::list is almost certainly not the answer. The collections in stl are simply not meant to be derived from and doing so will cause you problems down the road.
The classic example of why is the destructor problem. The destructors in stl collections are not virtual. This will break any logic you place in your derived class destructor if an object is deleted via a reference to the std::list. For example
std::list* pList = new YourNewListClass();
delet pList; // runs std::list::~list()
You'd also need to override much more than the methods on the iterator. It would require changing every method which can possibly mutate the collection.
A more stable approach would be to implement your own std::list style class which follows the standard stl container behavior. You could then include use this list in the places you wanted events without running into the problems with deriving from std::list.
Look at the way that std::deque implements it's functionality as an adaptor of another standard collection. This is the way to go -- use composition not inheritance and wrap the underlying collection to provide your new facilities. For bonus points template your implementation on the underlying collection. For many uses a std::vector will outperform a std::list and your additions should be able to work equally well with whichever of these the user chooses.
First things first..NEVER derive a class from STL containers as they are not meant to be derived. For starters their destructor is not virtual.
The easiest way would be contain a std::list in your own class and providing list like interfaces. In these list like interfaces you can provide any additional tasks you want to perform before/updating the list.
Also, take a look at this design pattern: Decorator
Take a look at boost::transform_iterator<>. It seems to be close to what you're looking for. It calls a functor whenever the operator*() function of the transform_iterator<> is called. The intended use is to transform the object the iterators points to, but there's nothing that says the functor can't do something else and simply return the original value of the pointed to object.
Even if it's not quite what you want, it will probably provide ideas to how you might approach your problem.
Related
Should a user-defined container that is a wrapper for std::vector, inherit or contain std::vector?
I have a class that is supposed to be a container. I see two options:
1) inherit from vector
2) have a private member vector and override all the vector functions to make my container act as vector
I am not sure if it is only a question of style, or one way is fundamentally better
than the other?
The extra functionality I want to add is small, few data members and functions here
and there. Mostly it will be convenient functions to work with the data in the vector.
First of all, STL containers are not supposed to be inherited. They even don't have virtual destructors.
Second, it's always preferable to choose composition/aggregation in favor of inheritance, as this is a lower coupling technique that puts less restrictions/requirements on the code.
See this answer for more details, this question has been raised a lot of times.
Interesting read about this topic here - Thou shalt not inherit from std::vector
Unlike what the title suggests, it's OK to inherit from std::vector, in the end it's more an architectural issue. Does it help reuse or code complexity? By doing that, does it make it easier to understand, maintain and debug the code?
I need a container, that wraps other containers and makes them traversible like a zip_iterator, but also wraps their other functions (like push_back(), size(), ...). Is there something like this in the stdlib or boost?
Background:
I have a class that stores a polymorphic base class in a boost::ptr_list<BaseClass> but needs some more information to be stored alongside this. With an normal std::list I would just do std::list<std:pair<BaseClass, OtherInformation> > and am done, but I want the pointer management of boost::ptr_list.
The obvious solution I came up with is: Have two containers boost::ptr_list<BaseClass> and std::list<OtherInformation>. This solves the problem but leaves me with always handling two containers instead of one (which also invites inconsistencies between the containers).
So I am searching for a wrapper that will wrap two (or an arbitrary number of) containers and makes them accessible like one, that stores a tuple of the data.
To summarize:
Either I need a container that does this, then I would like to know if there is already one or if I have to implement it my self (which I would consider some fun :).
Or the solution I thought of is the wrong way to go, then please tell me the alternatives.
I am extending an already existing C++ code.
One of the class members is of type vector of another class objects:
class Road
{
....
vector<Link*> links; //Link is just another class
}
The other modules use this class and its member through a lot of sequence iterators.
Now, while extending the code, I need to add a member to Link class called linkID, and use this linkID to find/access my "Link" objects.
Problem:
I am not going to search for a Link object(using LinkID) in the vector by iterating through the millions of items, just to find a specific Link object. The best solution is "map"! right?
....
map<linkID,*link> links
....
lnk=links[linkID]
.........
But the problem is that i cannot modify the current source code except very minor modifications lik adding linkID etc.
So my obvious question is:
is it possible to use map in place of vector(any how).
In the other words, I want to create a map, fill it up, and later treat it as a vector. possible?
Thank you for your comments
The best solution is "map"! right?
Yes, sounds like the map is the simplest solution to your problem. But instead of using operator[], I'd use find and insert methods.
Initially, you can change the code to use the map of this type std::map< unsigned int, link* >, because that is the most similar to a vector< link* >. Then you can easily switch to std::map< LinkId, link* >.
I think what you might be able to do is make an augmented data structure: a vectormap which allows you to have keyed access to the items by linkID and which also supports the operations of std::vector. The [] operator of this object could be overloaded so that links[3] gives you positional access to the vector and links[linkID] looks up a link ID in the map. Things like push_back can be supported, if the code needs them: push_back would have to push the element into the vector, and then also do a map[item->linkID] = item to enter it into the map. You probably get the picture.
Disguising a map as vector is not possible as such.
In theory, you could try to implement a new class that is derived from vector (i.e. uses std::vector as base class). Internally it could use a map, and to the outside it would have the interface of a vector (and it would be accepted as a replacement for the vector because it is derived of it).
In practice you might encounter a number of problems, though. You would obviously inherit the internal data structures of the vector, too, so you would have to ignore them in your implementation, i.e. leave them empty. Deriving from STL classes (except basic_ ones) is also against recommended practice and possibly risky, as #Als points out in the comment below.
If there is a chance to avoid this by rewriting a larger portion of the existing code, you should do that. But if unavoidable, using inheritance might work.
I did this many moons ago for the rail network. The base classes were link and node. The actual rail and eventually routes were based on top of these. IIRC I used std::list to contain links and nodes and used vectors of vectors for containing the actual tracks.
The proper solution, if linkID is a member of Link, would be std::set<Link*, OrderByLinkID>. The OrderByLinkID predicate would take two Link* and return true iff the first has a smaller linkID member.
The result is that the std::set still contains Link*, and you can iterate over them just like std::vector. In comparison, with std::map you'd end up iterating over std::pair<Link*, LinkID> which is a much bigger change.
I'd like to manage a bunch of objects of classes derived from a shared interface class in a common container.
To illustrate the problem, let's say I'm building a game which will contain different actors. Let's call the interface IActor and derive Enemy and Civilian from it.
Now, the idea is to have my game main loop be able to do this:
// somewhere during init
std::vector<IActor> ActorList;
Enemy EvilGuy;
Civilian CoolGuy;
ActorList.push_back(EvilGuy);
ActorList.push_back(CoolGuy);
and
// main loop
while(!done) {
BOOST_FOREACH(IActor CurrentActor, ActorList) {
CurrentActor.Update();
CurrentActor.Draw();
}
}
... or something along those lines. This example obviously won't work but that is pretty much the reason I'm asking here.
I'd like to know: What would be the best, safest, highest-level way to manage those objects in a common heterogeneous container? I know about a variety of approaches (Boost::Any, void*, handler class with boost::shared_ptr, Boost.Pointer Container, dynamic_cast) but I can't decide which would be the way to go here.
Also I'd like to emphasize that I want to stay away as far as possible from manual memory management or nested pointers.
Help much appreciated :).
To solve the problem which you have mentioned, although you are going in right direction, but you are doing it the wrong way. This is what you would need to do
Define a base class (which you are already doing) with virtual functions which would be overridden by derived classes Enemy and Civilian in your case.
You need to choose a proper container with will store your object. You have taken a std::vector<IActor> which is not a good choice because
Firstly when you are adding objects to the vector it is leading to object slicing. This means that only the IActor part of Enemy or Civilian is being stored instead of the whole object.
Secondly you need to call functions depending on the type of the object (virtual functions), which can only happen if you use pointers.
Both of the reason above point to the fact that you need to use a container which can contain pointers, something like std::vector<IActor*> . But a better choice would be to use container of smart pointers which will save you from memory management headaches. You can use any of the smart pointers depending upon your need (but not auto_ptr)
This is what your code would look like
// somewhere during init
std::vector<some_smart_ptr<IActor> > ActorList;
ActorList.push_back(some_smart_ptr(new Enemy()));
ActorList.push_back(some_smart_ptr(new Civilian()));
and
// main loop
while(!done)
{
BOOST_FOREACH(some_smart_ptr<IActor> CurrentActor, ActorList)
{
CurrentActor->Update();
CurrentActor->Draw();
}
}
Which is pretty much similar to your original code except for smart pointers part
My instant reaction is that you should store smart pointers in the container, and make sure the base class defines enough (pure) virtual methods that you never need to dynamic_cast back to the derived class.
As you have guessed you need to store the objects as pointers.
I prefer to use the boost pointer containers (rather than a normal container of smart pointers).
The reason for this is the boost ptr container access the objects as if they were objects (returning references) rather than pointers. This makes it easier to use standard functors and algorithms on the containers.
The disadvantage of smart pointers is that you are sharing ownership.
This is not what you really want. You want ownership to be in a single place (in this case the container).
boost::ptr_vector<IActor> ActorList;
ActorList.push_back(new Enemy());
ActorList.push_back(new Civilian());
and
std::for_each(ActorList.begin(),
ActorList.end(),
std::mem_fun_ref(&IActor::updateDraw));
If you want the container to exclusively own the elements in it, use a Boost pointer container: they're designed for that job. Otherwise, use a container of shared_ptr<IActor> (and of course use them properly, meaning that everyone who needs to share ownership uses shared_ptr).
In both cases, make sure that the destructor of IActor is virtual.
void* requires you to do manual memory management, so that's out. Boost.Any is overkill when the types are related by inheritance - standard polymorphism does the job.
Whether you need dynamic_cast or not is an orthogonal issue - if the users of the container only need the IActor interface, and you either (a) make all the functions of the interface virtual, or else (b) use the non-virtual interface idiom, then you don't need dynamic_cast. If the users of the container know that some of the IActor objects are "really" civilians, and want to make use of things which are in the Civilian interface but not IActor, then you will need casts (or a redesign).
class MyContainedClass {
};
class MyClass {
public:
MyContainedClass * getElement() {
// ...
std::list<MyContainedClass>::iterator it = ... // retrieve somehow
return &(*it);
}
// other methods
private:
std::list<MyContainedClass> m_contained;
};
Though msdn says std::list should not perform relocations of elements on deletion or insertion, is it a good and common way to return pointer to a list element?
PS: I know that I can use collection of pointers (and will have to delete elements in destructor), collection of shared pointers (which I don't like), etc.
I don't see the use of encapsulating this, but that may be just me. In any case, returning a reference instead of a pointer makes a lot more sense to me.
In a general sort of way, if your "contained class" is truly contained in your "MyClass", then MyClass should not be allowing outsiders to touch its private contents.
So, MyClass should be providing methods to manipulate the contained class objects, not returning pointers to them. So, for example, a method such as "increment the value of the umpteenth contained object", rather than "here is a pointer to the umpteenth contained object, do with it as you wish".
It depends...
It depends on how much encapsulated you want your class to be, and what you want to hide, or show.
The code I see seems ok for me. You're right about the fact the std::list's data and iterators won't be invalidated in case of another data/iterator's modification/deletion.
Now, returning the pointer would hide the fact you're using a std::list as an internal container, and would not let the user to navigate its list. Returning the iterator would let more freedom to navigate this list for the users of the class, but they would "know" they are accessing a STL container.
It's your choice, there, I guess.
Note that if it == std::list<>.end(), then you'll have a problem with this code, but I guess you already know that, and that this is not the subject of this discussion.
Still, there are alternative I summarize below:
Using const will help...
The fact you return a non-const pointer lets the user of you object silently modify any MyContainedClass he/she can get his/her hands on, without telling your object.
Instead or returning a pointer, you could return a const pointer (and suffix your method with const) to stop the user from modifying the data inside the list without using an accessor approved by you (a kind of setElement ?).
const MyContainedClass * getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return &(*it);
}
This will increase somewhat the encapsulation.
What about a reference?
If your method cannot fail (i.e. it always return a valid pointer), then you should consider returning the reference instead of the pointer. Something like:
const MyContainedClass & getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return *it;
}
This has nothing to do with encapsulation, though..
:-p
Using an iterator?
Why not return the iterator instead of the pointer? If for you, navigating the list up and down is ok, then the iterator would be better than the pointer, and is used mostly the same way.
Make the iterator a const_iterator if you want to avoid the user modifying the data.
std::list<MyContainedClass>::const_iterator getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return it;
}
The good side would be that the user would be able to navigate the list. The bad side is that the user would know it is a std::list, so...
Scott Meyers in his book Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library says it's just not worth trying to encapsulate your containers since none of them are completely replaceable for another.
Think good and hard about what you really want MyClass for. I've noticed that some programmers write wrappers for their collections just as a matter of habit, regardless of whether they have any specific needs above and beyond those met by the standard STL collections. If that's your situation, then typedef std::list<MyContainedClass> MyClass and be done with it.
If you do have operations you intend to implement in MyClass, then the success of your encapsulation will depend more on the interface you provide for them than on how you provide access to the underlying list.
No offense meant, but... With the limited information you've provided, it smells like you're punting: exposing internal data because you can't figure out how to implement the operations your client code requires in MyClass... or possibly, because you don't even know yet what operations will be required by your client code. This is a classic problem with trying to write low-level code before the high-level code that requires it; you know what data you'll be working with, but haven't really nailed down exactly what you'll be doing with it yet, so you write a class structure that exposes the raw data all the way to the top. You'd do well to re-think your strategy here.
#cos:
Of course I'm encapsulating
MyContainedClass not just for the sake
of encapsulation. Let's take more
specific example:
Your example does little to allay my fear that you are writing your containers before you know what they'll be used for. Your example container wrapper - Document - has a total of three methods: NewParagraph(), DeleteParagraph(), and GetParagraph(), all of which operate on the contained collection (std::list), and all of which closely mirror operations that std::list provides "out of the box". Document encapsulates std::list in the sense that clients need not be aware of its use in the implementation... but realistically, it is little more than a facade - since you are providing clients raw pointers to the objects stored in the list, the client is still tied implicitly to the implementation.
If we put objects (not pointers) to
container they will be destroyed
automatically (which is good).
Good or bad depends on the needs of your system. What this implementation means is simple: the document owns the Paragraphs, and when a Paragraph is removed from the document any pointers to it immediately become invalid. Which means you must be very careful when implementing something like:
other objects than use collections of
paragraphs, but don't own them.
Now you have a problem. Your object, ParagraphSelectionDialog, has a list of pointers to Paragraph objects owned by the Document. If you are not careful to coordinate these two objects, the Document - or another client by way of the Document - could invalidate some or all of the pointers held by an instance of ParagraphSelectionDialog! There's no easy way to catch this - a pointer to a valid Paragraph looks the same as a pointer to a deallocated Paragraph, and may even end up pointing to a valid - but different - Paragraph instance! Since clients are allowed, and even expected, to retain and dereference these pointers, the Document loses control over them as soon as they are returned from a public method, even while it retains ownership of the Paragraph objects.
This... is bad. You've end up with an incomplete, superficial, encapsulation, a leaky abstraction, and in some ways it is worse than having no abstraction at all. Because you hide the implementation, your clients have no idea of the lifetime of the objects pointed to by your interface. You would probably get lucky most of the time, since most std::list operations do not invalidate references to items they don't modify. And all would be well... until the wrong Paragraph gets deleted, and you find yourself stuck with the task of tracing through the callstack looking for the client that kept that pointer around a little bit too long.
The fix is simple enough: return values or objects that can be stored for as long as they need to be, and verified prior to use. That could be something as simple as an ordinal or ID value that must be passed to the Document in exchange for a usable reference, or as complex as a reference-counted smart pointer or weak pointer... it really depends on the specific needs of your clients. Spec out the client code first, then write your Document to serve.
The Easy way
#cos, For the example you have shown, i would say the easiest way to create this system in C++ would be to not trouble with the reference counting. All you have to do would be to make sure that the program flow first destroys the objects (views) which holds the direct references to the objects (paragraphs) in the collection, before the root Document get destroyed.
The Tough Way
However if you still want to control the lifetimes by reference tracking, you might have to hold references deeper into the hierarchy such that Paragraph objects holds reverse references to the root Document object such that, only when the last paragraph object gets destroyed will the Document object get destructed.
Additionally the paragraph references when used inside the Views class and when passed to other classes, would also have to passed around as reference counted interfaces.
Toughness
This is too much overhead, compared to the simple scheme i listed in the beginning. It avoids all kinds of object counting overheads and more importantly someone who inherits your program does not get trapped in the reference dependency threads traps that criss cross your system.
Alternative Platforms
This kind-of tooling might be easier to perform in a platform that supports and promotes this style of programming like .NET or Java.
You still have to worry about memory
Even with a platform such as this you would still have to ensure your objects get de-referenced in a proper manner. Else outstanding references could eat up your memory in the blink of an eye. So you see, reference counting is not the panacea to good programming practices, though it helps avoid lots of error checks and cleanups, which when applied the whole system considerably eases the programmers task.
Recommendation
That said, coming back to your original question which gave raise to all the reference counting doubts - Is it ok to expose your objects directly from the collection?
Programs cannot exist where all classes / all parts of the program are truly interdependent of each other. No, that would be impossible, as a program is the running manifestation of how your classes / modules interact. The ideal design can only minimize the dependencies and not remove them totally.
So my opinion would be, yes it is not a bad practice to expose the references to the objects from your collection, to other objects that need to work with them, provided you do this in a sane manner
Ensure that only a few classes / parts of your program can get such references to ensure minimum interdependency.
Ensure that the references / pointers passed are interfaces and not concrete objects so that the interdependency is avoided between concrete classes.
Ensure that the references are not further passed along deeper into the program.
Ensure that the program logic takes care of destroying the dependent objects, before cleaning up the actual objects that satisfy those references.
I think the bigger problem is that you're hiding the type of collection so even if you use a collection that doesn't move elements you may change your mind in the future. Externally that's not visible so I'd say it's not a good idea to do this.
std::list will not invalidate any iterators, pointers or references when you add or remove things from the list (apart from any that point the item being removed, obviously), so using a list in this way isn't going to break.
As others have pointed out, you may want not want to be handing out direct access to the private bits of this class. So changing the function to:
const MyContainedClass * getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return &(*it);
}
may be better, or if you always return a valid MyContainedClass object then you could use
const MyContainedClass& getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return *it;
}
to avoid the calling code having to cope with NULL pointers.
STL will be more familiar to a future programmer than your custom encapsulation, so you should avoid doing this if you can. There will be edge cases that you havent thought about which will come up later in the app's lifetime, wheras STL is failry well reviewed and documented.
Additionally most containers support somewhat similar operations like begin end push etc. So it should be fairly trivial to change the container type in your code should you change the container. eg vector to deque or map to hash_map etc.
Assuming you still want to do this for a more deeper reason, i would say the correct way to do this is to implement all the methods and iterator classes that list implements. Forward the calls to the member list calls when you need no changes. Modify and forward or do some custom actions where you need to do something special (the reason why you decide to this in the first place)
It would be easier if STl classes where designed to be inherited from but for efficiency sake it was decided not to do so. Google for "inherit from STL classes" for more thoughts on this.