Trouble with offsetof

E

Exits Funnel

Consider this code which is a very trimmed down version of some I've
inherited and am trying to port from windows to g++:

//Begin test1.cpp
class foo { int i; int j; };

class bar
{
bar (int foo::* dataMember)
:eek:ffsetof (foo, *dataMember) //Call this Line (A)
{
// int i = offsetof (foo, *dataMember); //Call this Line (B)
}
};
//End test1.cpp

when I try to compile test1.cpp with g++, the compiler has this to say:

test2.cpp: In constructor `bar::bar(int foo::*)':
test2.cpp:6: syntax error before `;' token

A couple of questions then:

(1) Should the compiler complain? I don't have much experience with
using the 'pointer to data member' stuff, but based on the research I've
just done on the net, the code seems reasonable.

(2) If I move the call from the initializer list to the ctor body by
commenting out line (A) and uncommenting line (B), the compiler error
becomes:

test2.cpp: In constructor `bar::bar(int foo::*)':
test2.cpp:8: syntax error before `;' token
test2.cpp:8: declaration of `dataMember' shadows a parameter
test2.cpp:8: syntax error before `;' token

So, it seems the original problem persists which is reasonable but now
there's this additional shadowing issue. It's not clear to me what
parameer 'dataMember' is shadowing here? If anyone could explain this
to me it would be great.

Thanks in advance for any feedback!

-exits
 
V

Victor Bazarov

Exits Funnel said:
Consider this code which is a very trimmed down version of some I've
inherited and am trying to port from windows to g++:

//Begin test1.cpp
class foo { int i; int j; };

class bar
{
bar (int foo::* dataMember)
:eek:ffsetof (foo, *dataMember) //Call this Line (A)
{
// int i = offsetof (foo, *dataMember); //Call this Line (B)
}
};
//End test1.cpp

when I try to compile test1.cpp with g++, the compiler has this to say:

test2.cpp: In constructor `bar::bar(int foo::*)':
test2.cpp:6: syntax error before `;' token

A couple of questions then:

(1) Should the compiler complain? I don't have much experience with using
the 'pointer to data member' stuff, but based on the research I've just
done on the net, the code seems reasonable.

(2) If I move the call from the initializer list to the ctor body by
commenting out line (A) and uncommenting line (B), the compiler error
becomes:

test2.cpp: In constructor `bar::bar(int foo::*)':
test2.cpp:8: syntax error before `;' token
test2.cpp:8: declaration of `dataMember' shadows a parameter
test2.cpp:8: syntax error before `;' token

So, it seems the original problem persists which is reasonable but now
there's this additional shadowing issue. It's not clear to me what
parameer 'dataMember' is shadowing here? If anyone could explain this to
me it would be great.

'offsetof' is reserved and defined only when used with POD. Your class
is not POD, so using 'offsetof' with it is essentially prohibited.

Use pointers to members, if you have to, but you'll probably be better off
if you rewrite the algorithm that was written to require 'offsetof'.

As to your particular code, 'offsetof' is a macro that usually expands into
a constant integral expression. What is the constant integral expression
doing in the initialiser list of that constructor? It's like writing

class bar {
bar(int blah) : 42 {}
};

What's the "42" for? What are you trying to do with it?

Victor
 
J

Jerry Coffin

'offsetof' is reserved and defined only when used with POD. Your
class
is not POD, so using 'offsetof' with it is essentially prohibited.

That was my first reaction too, but it's incorrect. He's calling
offsetof _in_ the ctor of bar (and having an explicit ctor means bar
isn't a POD type), but the argument he's passing is foo -- and foo IS a
POD type.

The problem is that he's passing a _pointer_ to a member where offsetof
expects the _name_ of the member. In C++, offsetof is really more
tolerated than fully supported -- it doesn't work with new-fangled
things like pointers to members.
 
E

Exits Funnel

Thanks for taking the time to reply, Victor.
'offsetof' is reserved and defined only when used with POD. Your class
is not POD, so using 'offsetof' with it is essentially prohibited.

This is good to know; I couldn't find much info on offsetof anywhere.
It's not clear to me though what makes foo not a POD. Is it just that
the members are private? I just modified the code to make them public
but I get the same error.
Use pointers to members, if you have to, but you'll probably be better off
if you rewrite the algorithm that was written to require 'offsetof'.

Hopefully, I'll be able to go this route but it's ALOT of code and I'd
like to get it running sooner rather than later.
As to your particular code, 'offsetof' is a macro that usually expands into
a constant integral expression. What is the constant integral expression
doing in the initialiser list of that constructor?

Good point. Actually, I always try to trim as much of the code away as
possible while still retaining the error before posting to USENET.
Maybe I went a bit too far this time :) The actual code was, of course,
something like this:

bar (int foo::* dataMember)
:myVal (offsetof (foo, *dataMember)) //Call this Line (A)

-exits
 
V

Victor Bazarov

Jerry Coffin said:
That was my first reaction too, but it's incorrect. He's calling
offsetof _in_ the ctor of bar (and having an explicit ctor means bar
isn't a POD type), but the argument he's passing is foo -- and foo IS a
POD type.

How is it POD if it's a class and the members are private?

V
 
V

Victor Bazarov

Exits Funnel said:
[...] Actually, I always try to trim as much of the code away as possible
while still retaining the error before posting to USENET. Maybe I went a
bit too far this time :) The actual code was, of course, something like
this:

bar (int foo::* dataMember)
:myVal (offsetof (foo, *dataMember)) //Call this Line (A)

Well, a pointer to member cannot be used without the object.
The expression (*blah) where 'blah' is a pointer to member is
meaningless in C++.

V
 
J

Jack Klein

Consider this code which is a very trimmed down version of some I've
inherited and am trying to port from windows to g++:

//Begin test1.cpp
class foo { int i; int j; };

class bar
{
bar (int foo::* dataMember)
:eek:ffsetof (foo, *dataMember) //Call this Line (A)
{
// int i = offsetof (foo, *dataMember); //Call this Line (B)
}
};
//End test1.cpp

when I try to compile test1.cpp with g++, the compiler has this to say:

test2.cpp: In constructor `bar::bar(int foo::*)':
test2.cpp:6: syntax error before `;' token

A couple of questions then:

(1) Should the compiler complain? I don't have much experience with
using the 'pointer to data member' stuff, but based on the research I've
just done on the net, the code seems reasonable.

(2) If I move the call from the initializer list to the ctor body by
commenting out line (A) and uncommenting line (B), the compiler error
becomes:

test2.cpp: In constructor `bar::bar(int foo::*)':
test2.cpp:8: syntax error before `;' token
test2.cpp:8: declaration of `dataMember' shadows a parameter
test2.cpp:8: syntax error before `;' token

So, it seems the original problem persists which is reasonable but now
there's this additional shadowing issue. It's not clear to me what
parameer 'dataMember' is shadowing here? If anyone could explain this
to me it would be great.

Thanks in advance for any feedback!

-exits

offsetof, defined in <stdlib.h> and <cstdlib>, is a macro, not a
function. It does not work on objects at all, but on compile-time
symbols.

The offsetof() macro requires two arguments, the NAME of a structure
(or in C++, POD class) type, and the NAME of a member of that
structure or class. The macro generates, _at compile time_ a value of
type size_t that represents the difference in bytes between the
address of any valid object of that type, and the address of the
specified member within that object.

It is evaluated completely at compile time based on names, never at
run time and can never involve a pointer. The concept of pointers,
let alone dereferencing pointers, does not exist at the early phase of
compilation where macros are expanded.
 
D

David Harmon

On Sat, 08 Jan 2005 16:21:52 -0500 in comp.lang.c++, Exits Funnel
It's not clear to me though what makes foo not a POD. Is it just that
the members are private? I just modified the code to make them public
but I get the same error.

In your stripped example, it is just the private members, but I
guess there may be a lot of other things in the real code.

Plain Old Data is any built in or user-defined type that has:

- no user-defined constructor
- no user-defined copy assignment operator
- no user defined destructor
- no virtual functions
- no base class (i.e. it is not a derived class)
- no private or protected non-static data members
- no non-static members of type pointer to member
- no non-static members that are references
- no non-static data members that are not also POD types

But that has little to do with the current problem.
Good point. Actually, I always try to trim as much of the code away as
possible while still retaining the error before posting to USENET.
Maybe I went a bit too far this time :) The actual code was, of course,
something like this:

bar (int foo::* dataMember)
:myVal (offsetof (foo, *dataMember)) //Call this Line (A)

Different compilers can be expected to implement 'offsetof' in
slightly different ways, to match their differing object model.
Here is an example of a definition of 'offsetof' ripped from a
compiler that I happened to have handy:

#define offsetof(t,i) ((size_t)((char *)&((t *)0)->i - (char *)0))

You notice the second parameter appears in the context '->i'. When
you substitute the macro argument, you get '->*datamember', invoking
the ->* operator almost by accident and luck. If the macro had been
written with '-> i' it would still work with a member name, but not
the pointer.

If foo is a POD your luck may hold. If the *datamember pointer
involves any of the magic that is needed to implement member
pointers when an inheritance hierarchy is involved, etc., then it
becomes less likely that '(t *)0' will slide to success.

Either way, '*datamember' is not what 'offsetof' was designed to
support.
 
J

Jerry Coffin

This is good to know; I couldn't find much info on offsetof anywhere.
It's not clear to me though what makes foo not a POD. Is it just that
the members are private? I just modified the code to make them public
but I get the same error.

Being private _does_ keep them from being POD (I'm not sure what I was
thinking when I said otherwise) but my original point about the problem
remains -- the real problem is that you're supplying a pointer to a
member but it needs the name of a member instead. The bottom line is
that this technique simply can't work, whether it's applied to a POD
type or not.
 
E

Exits Funnel

David, thanks for taking the time to reply.
#define offsetof(t,i) ((size_t)((char *)&((t *)0)->i - (char *)0))

In which header did you find this? It's not clear to me what the point
of the ' - (char *)0' bit is. The only macro definition I could find on
my platform (RedHat Linux) was in stddef.h and looked like this:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

Actually, I wasn't #including stddef.h which is obviously part of my
problem. I thought that offsetof( ) was a built in part of the language
similar to sizeof. Would one expect to have to explicitly include some
header file to use offsetof?
You notice the second parameter appears in the context '->i'. When
you substitute the macro argument, you get '->*datamember', invoking
the ->* operator almost by accident and luck. If the macro had been
written with '-> i' it would still work with a member name, but not
the pointer.

If foo is a POD your luck may hold. If the *datamember pointer
involves any of the magic that is needed to implement member
pointers when an inheritance hierarchy is involved, etc., then it
becomes less likely that '(t *)0' will slide to success.

Either way, '*datamember' is not what 'offsetof' was designed to
support.

This is all very helpful information, thanks again.

-exits
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top