On Apr 22, 4:20 am, David Harmon <sou...@netcom. comwrote:
On 21 Apr 2007 12:12:51 -0700 in comp.lang.c++, Imre <imr...@pager.h u>
wrote,
Of course, a pointer to the parent Outer object could be passed to F()
as an argument, or as a constructor argument when creating
Outer::inner, but it seems to be unnecessary.
Yes, it's necessary. Otherwise Inner doesn't even know if it is living
inside an Outer object, or created stand-alone.
True, but Inner could know about where it's living without passing in
the parent object; for example, using a template parameter to pass in
the parent _type_. Passing around object instances still seems to be
overkill (and either overhead (storing a parent pointer in Inner) or
inconvenience (always passing in parent to Inner::F())) to me.
Here's a more complete solution using offsetof:
// Empty primary template, see specializations below
template <typename Outer, int Id = 0>
struct InnerOffset
{
};
template <typename Outer, int Id = 0>
class Inner
{
public:
Outer* F();
};
template <typename Outer, int Id>
Outer* Inner<Outer, Id>::F()
{
return (Outer*)(((char *)this) - InnerOffset<Out er, Id>::offset);
}
// ---
class Outer1
{
public:
int i;
Inner<Outer1inn er;
};
template <>
struct InnerOffset<Out er1>
{
enum { offset = offsetof(Outer1 , inner) };
};
//
class Outer2
{
public:
int i, j;
Inner<Outer2, 0inner0;
Inner<Outer2, 1inner1;
};
template <>
struct InnerOffset<Out er2, 0>
{
enum { offset = offsetof(Outer2 , inner0) };
};
template <>
struct InnerOffset<Out er2, 1>
{
enum { offset = offsetof(Outer2 , inner1) };
};
int main(int argc, char* argv[])
{
Outer1 o1;
Outer1* po1 = o1.inner.F();
assert(po1 == &o1);
Outer2 o2;
Outer2* po20 = o2.inner0.F();
assert(po20 == &o2);
Outer2* po21 = o2.inner1.F();
assert(po21 == &o2);
return 0;
}
Here no memory is wasted by storing a pointer to the parent object in
every Inner, and also we don't need to always pass the parent object
to Inner::F(). But still, Inner members can be used in whatever Outer
class we like, and they can find their parent. Even multiple Inner
members in the same Outer class are supported.
The only problem is that this code uses offsetof on classes, and that
isn't guaranteed to work on all compilers.
So the question is: is it possible to do the same in a more portable
way? That is, without offsetof. Using pointers to data members, or
whatever.
Imre