Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Pointer to data member vs. offsetof

Reply
Thread Tools

Pointer to data member vs. offsetof

 
 
Imre
Guest
Posts: n/a
 
      04-21-2007

Hi

I know that offsetof is basically a C leftover, and only works for POD
types, not classes, so it is recommended that I use pointers to
members instead. However, I have a problem where I don't see how I
should use pointers to members.
Basically, I know how to get a member if I have an object and a
pointer-to-member (obj.*ptr instead of obj + offset), but I don't know
how to do the opposite: getting the object from a member address and a
pointer-to-member (that is, what to write instead of member - offset).

Here's what I need it for:

I have a class, for now let's just call it Outer. It has a member
variable, the type of which is a class called Inner. Inner has a
function F(). In F(), I need to have an Outer* pointer that points to
the Outer object that contains this Inner object.

class Inner
{
public:
virtual ~Inner() {}
void F();
};

class Outer
{
public:
Inner inner;
};

void Inner::F()
{
Outer* parent = ???;
}

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. In every Outer object,
the Inner object is at the same offset (this is guaranteed, isn't
it?), so we should be able to calculate the address of the the parent
Outer in Inner::F().

I can do this on compilers where offsetof is supported for classes as
well as PODs, but I'd like to know if there's a more portable
solution.

Thanks,

Imre

 
Reply With Quote
 
 
 
 
David Harmon
Guest
Posts: n/a
 
      04-22-2007
On 21 Apr 2007 12:12:51 -0700 in comp.lang.c++, Imre <(E-Mail Removed)>
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.

 
Reply With Quote
 
 
 
 
Imre
Guest
Posts: n/a
 
      04-22-2007
On Apr 22, 4:20 am, David Harmon <(E-Mail Removed)> wrote:
> On 21 Apr 2007 12:12:51 -0700 in comp.lang.c++, Imre <(E-Mail Removed)>
> 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<Outer, Id>:ffset);
}

// ---

class Outer1
{
public:
int i;
Inner<Outer1> inner;
};

template <>
struct InnerOffset<Outer1>
{
enum { offset = offsetof(Outer1, inner) };
};

//

class Outer2
{
public:
int i, j;
Inner<Outer2, 0> inner0;
Inner<Outer2, 1> inner1;
};

template <>
struct InnerOffset<Outer2, 0>
{
enum { offset = offsetof(Outer2, inner0) };
};

template <>
struct InnerOffset<Outer2, 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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pointer-to-member data and pointer-to-member functions and access specifiers Stephen Howe C++ 2 11-06-2012 12:32 PM
Using offsetof to create a pointer to the start of a struct? Not Really Me C Programming 2 03-14-2008 04:33 AM
different way of finding out offsetof a member in structure abhimanyu.v@gmail.com C Programming 18 11-10-2007 02:06 AM
What is the correct grammar to make a function call by using static member data which is a pointer to a ordinary class member function? zaeminkr@gmail.com C++ 3 07-06-2007 12:50 PM
pointer to member function and pointer to constant member function Fraser Ross C++ 4 08-14-2004 06:00 PM



Advertisments