iterator to pointer conversion
Need some help with STL containers.
Say you have an STL list of objects of class X:
std::list<X> Xlist;
And you have a const_iterator to the first element of this container:
std::list<X>::const_iterator iter = Xlist.begin();
Now since X inherits from a base class (BaseX), you would like to create another STL list: one that contains base class pointers for all objects in Xlist:
std::list<BaseX*> BaseXlist;
What is the safest machine-independent way to do this? I assume you have to obtain access to the base-class pointer via some dereferencing and convert it via pointer arithmetic. I have developed a function that returns a base class pointer (given an iterator to a derived class) but was told this is not safe. It works though.
Here is the function definition:
BaseX* anyClass::getBasePointer(std::list<X>::const_iterator iter)
{
void* pAction = &iter;
int** ppActionInt = static_cast<int**>(pAction);
int* pActionInt = *ppActionInt;
++(++pActionInt);
pAction = pActionInt;
return static_cast<BaseX*>(pAction);
}
Any help would be appreciated !!
# 1 Re: iterator to pointer conversion
You technique is indeed inherently dangerous and error prone. The short answer is that you can't convert pointers safely, but there are a few general pricnicnples: first, to obtain the address of an element through an iterator, use &*it;
secondly, you need to use a contiguous container such as vector, certainly not list. Finally, I'm not sure I understand the relationship between the base class and its derived classes. Why would you need two containers in the first place? Simply store the derived objects and use their virtual functions to achieve polymorphism.
Danny at 2007-11-11 21:01:43 >

# 2 Re: iterator to pointer conversion
The reason for the second container is as follows:
I am required to introduce a new class (I'll call this Class Y). Class Y will inherit from BaseX as well.
I need to create a "super list" that would contain elements of class X and those of class Y. The only way I could do that was to introduce a base class that X and Y inherit from. Then I could make an STL list of base pointers and achieve polymorphism by iterating thru my super list invoking the pure virtual functions.
Is there an easier way to achieve this?
To summarize, this is what I started with:
std::list<X> Xlist;
X objects have a validate() and apply() function.
A new class then came into existence per requirements.
This new class also need to implement a validate() and apply() function.
I therefore created a base class (BaseX is a bad name at this time, a more appropriate name was BaseXY) with two pure virtual functions, validate() and apply().
Class X and (the new) Class Y both inherit from BaseXY and are required to implement their own validate() and apply() functions.
My ultimate goal was to create an STL list of X and Y objects given two separate containers (an STL list of X objects and an STL list of Y objects). Sort of like merging a list but not really. The elements in the lists are time-ordered and this time-ordering must be preserved in the process of merging the two lists.
The only way to achieve this was thru base class pointers (BaseXY is an abstract base class).
I therefore invented the function to convert an interator to an X object into a BaseXY* that I could insert into:
std::list<BaseXY*> baseXYlist;
Hope that's a little clearer. Thanks again.
# 3 Re: iterator to pointer conversion
I think your design is overkill. You obviously want a heterogeneous container, something quite common in C++. There are several ways to accomplish this, but they all are much simpler than it seems: you use a single container of pointers to base, and store in it pointers to actual objects that may be of type derived1, derived2 and so on. In good OO design, you never inquire an object for its dynamic type, i.e., is it really BaseXY or is it X or Y? You simply assume that all these classes share a common interface of virtual functions that do the right thing. In most cases, this will suffice. If however for some reason you truly need to extract the dynamic type of the object to which the pointer is bound, use RTTI. That's exactly what RTTI is for. You can read more about heterogeneous containers and RTTI here:
http://www.dev-archive.com/cplus/10MinuteSolution/28347 //heter. are discussed at the end
http://www.dev-archive.com/getHelpOn/Article/10202 //RTTI
Danny at 2007-11-11 21:03:53 >

# 5 Re: iterator to pointer conversion
It doesn't like it because shared_ptr isn't in C++ yet, at least not in ISO C++. Expect to find it in a couple of years... Seriously, you can download it from Boost (see the instructions on the Solution) or simply use raw pointers as elements of the vector, as shown in the first Solution about heterogeneous containers: http://www.dev-archive.com/cplus/10MinuteSolution/29757
Danny at 2007-11-11 21:05:53 >
