"Marcin Kalicinski" <> wrote in
news:c8ajcp$e5d$:
> Hi everybody,
>
> I am creating an intrusive list ('next' and 'prev' pointers are stored
> within an object that is in a list). One method of doing that is to
> inherit all objects from some class that contains these pointers.
> However, it is unacceptable for my problem, because it limits the
> number of lists the object can be in to 1. I must have some objects in
> more than 1 list. Instead of inheriting, I use aggregation:
>
> class Node { // Node of a list
> Node *prev, *next;
> }
>
> class SomeObject { // Object that can be in 3 independent lists
> Node l1, l2, l3;
> }
>
> When I iterate through my list, I get pointer to a Node that is stored
> within SomeObject. But I need to get pointer to SomeObject itself.
> Right now I'm using nonconforming and ugly way:
>
> #define MEMBER_OFFSET(ClassName, FieldName) int(&(((ClassName
> *)0)->FieldName))
>
> ListNode *node;
> SomeObject *so = reinterpret_cast<SomeObject *>((char *)node -
> MEMBER_OFFSET(SomeObject, l2));
>
> My question is, is there a standard conforming way of doing that? For
> example by using pointers to members?
How about going the other way around?
Instead of "embedding" the node pointer in an object, you could use the
aligned storage* trick to hold the memory and place your object there.
* aligned storage as per boost::aligned_storage, or Alexandrescu's
"Discriminated Unions" article.
Very very very oversimplifying:
template <class T>
class Node {
char m_buffer[sizeof(T)];
Node* m_prev;
Node* m_next;
};
You could plant objects directly into node buffers by using placement
new.
As I said, the above is a huge oversimplification. The buffer should be
properly aligned for holding type T (see Alexandrescu's article on
discriminated unions at
http://www.moderncppdesign.com ).
Nonetheless, it's a very interesting technique. It can help get rid of
that one extra level of pointer indirection.
--
:: bartekd [at] o2 [dot] pl