"Container-of" in C++

M

marcus hall

Now that g++ is complaining about offset-of() applied to a class, it
raises the issue of how to implement a "container-of" concept in C++.

Specifically, I have a pointer to a class that is aggregated into an
outer class. I know the type of the outer class, and a pointer to the
member of that class. What is the preferred method of producing a pointer
to the outer class?

class A {
public:
...
class B _b;
};

A _a;

I have &_a._b and I want to get &_a.

Is the only legal way now to store a "class A *" within class B?

Marcus Hall
(e-mail address removed)
 
V

Victor Bazarov

marcus said:
Now that g++ is complaining about offset-of() applied to a class, it
raises the issue of how to implement a "container-of" concept in C++.

Specifically, I have a pointer to a class that is aggregated into an
outer class. I know the type of the outer class, and a pointer to the
member of that class. What is the preferred method of producing a pointer
to the outer class?

class A {
public:
...
class B _b;
};

A _a;

I have &_a._b and I want to get &_a.

Is the only legal way now to store a "class A *" within class B?

No. You may store A& there. Or any other value that would help you
identify the containing object. There is nothing automatic, of course.

V
 
W

wkaras

marcus said:
Now that g++ is complaining about offset-of() applied to a class, it
raises the issue of how to implement a "container-of" concept in C++.

Specifically, I have a pointer to a class that is aggregated into an
outer class. I know the type of the outer class, and a pointer to the
member of that class. What is the preferred method of producing a pointer
to the outer class?

class A {
public:
...
class B _b;
};

A _a;

I have &_a._b and I want to get &_a.

Is the only legal way now to store a "class A *" within class B?

Marcus Hall
(e-mail address removed)

This:

(A *) (((char *) addrBinA) - (((char *) &(((A *) 0)->_b)) - ((char *)
0)))

Seems to be very portable, although I'm not sure the Standard guaratees
it
will always work, except perhaps with POD.

(BTW, I believe identifiers that start with _ are reserved for use by
the compiler and standard libraries.)
 
A

Alipha

This:

(A *) (((char *) addrBinA) - (((char *) &(((A *) 0)->_b)) - ((char *)
0)))

use reinterpret_cast so people know at a glance that the code is not
portable, however,
Seems to be very portable, although I'm not sure the Standard guaratees
it
will always work, except perhaps with POD.

is probably an accurate statement.
(BTW, I believe identifiers that start with _ are reserved for use by
the compiler and standard libraries.)

identifiers that begin with _ at global scope are not allowed.
therefore _b is valid and _a may be valid if that code is in a
namespace.
 
V

verec

This:

(A *) (((char *) addrBinA) - (((char *) &(((A *) 0)->_b)) - ((char *)
0)))

Just out of sheer curiosity, what platform/compiler does define

x - ((char *) 0)

as something other than x ?
 
V

Victor Bazarov

verec said:
Just out of sheer curiosity, what platform/compiler does define

x - ((char *) 0)

as something other than x ?

If 'x' is a pointer, then it would seem that the result may actually
be the value of 'x' expressed as a ptrdiff_t, a different type.

V
 
G

Guest

I said:
Now that g++ is complaining about offset-of() applied to a class, it
raises the issue of how to implement a "container-of" concept in C++.

This:

(A *) (((char *) addrBinA) - (((char *) &(((A *) 0)->_b)) - ((char *)
0)))
Seems to be very portable, although I'm not sure the Standard guaratees
it
will always work, except perhaps with POD.

Yes, this is what I have been doing, but around gcc3.3 or so, it has started
complaining:

warning: invalid access to non-static data member ‘...' of NULL object
(perhaps the ‘offsetof’ macro was used incorrectly)

So, that raises my question on what is the "proper" way to get back to
the address of the containing object. I suppose that I could avoid
using "0" as a pointer, as in:

offset_of__b_within_A == (char *)&((A*)this)->_b - (char *)this

which avoids "dereferencing 0", but it seems even uglier.

Marcus Hall
(e-mail address removed)
 
M

msalters

marcus hall schreef:
Now that g++ is complaining about offset-of() applied to a class, it
raises the issue of how to implement a "container-of" concept in C++.

Specifically, I have a pointer to a class that is aggregated into an
outer class. I know the type of the outer class, and a pointer to the
member of that class.

In general, this may be impossible. Going from A to A.B may be
implemented
similar to dereferencing a B* in A. Obviously, that is a one-way
operation.
When you only have the B*, there is no way to get back the containing
A.
This may seem weird, but I could imagine something like this in the
presence of multiple/virtual inheritance, where the B* points to a base
class member.

Regards,
Michiel Salters
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,135
Latest member
VeronaShap
Top