C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Cast pointer to data member to integer type - legit?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Scott Lehman
Guest





PostPosted: Tue May 09, 2006 1:21 pm    Post subject: Cast pointer to data member to integer type - legit? Reply with quote



Hi,

When I first researched this, I read that pointers to data members were
just a byte offset which made sense, and I wanted to store that offset.
Using GCC 3.3 at the time, casting a pointer to a data member to a
offset_t or ptrdiff_t posed no issues and things worked great.

Now I'm moving the project to GCC 4.0, and that cast (and any other type
of cast I try) is no longer valid :(

I've been searching around a bit but haven't found a definitive answer.
Is casting a pointer to a data member to an integer type legal as the
C++ language is concerned?


It seems like it should be possible to do it, though I can certainly see
how it opens up a number of pitfalls that a language designer would want
to avoid.

Thanks,

Scott

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Tomás
Guest





PostPosted: Wed May 10, 2006 12:21 am    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote



Quote:
I've been searching around a bit but haven't found a definitive answer.
Is casting a pointer to a data member to an integer type legal as the
C++ language is concerned?


It seems like it should be possible to do it, though I can certainly see
how it opens up a number of pitfalls that a language designer would want
to avoid.


"reinterpret_cast".


class Monkey {
public:
int some_data_member;
};


int main()
{
Monkey monkey;

int *p = &(monkey.some_data_member);
/* Works just like any other object */

/* If you want to store it in an integral type
(for some weird reason), then do the following: */

unsigned long num = reinterpret_cast<unsigned long>(p);
}


You can even convert back from the "unsigned long" to a pointer type, but
the resulting address will only be reliable if an "unsigned long" has
enough bits to store all the info about an address.

-Tomás

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Scott Lehman
Guest





PostPosted: Wed May 10, 2006 7:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote



In article <WP08g.8900$j7.305056 (AT) news (DOT) indigo.ie>,
"Tomás" <NULL (AT) NULL (DOT) NULL> wrote:

Quote:
I've been searching around a bit but haven't found a definitive
answer.
Is casting a pointer to a data member to an integer type legal as the
C++ language is concerned?


It seems like it should be possible to do it, though I can
certainly see
how it opens up a number of pitfalls that a language designer
would want
to avoid.


"reinterpret_cast".


class Monkey {
public:
int some_data_member;
};


int main()
{
Monkey monkey;

int *p = &(monkey.some_data_member);
/* Works just like any other object */

/* If you want to store it in an integral type
(for some weird reason), then do the following: */

unsigned long num = reinterpret_cast<unsigned long>(p);
}


Sorry, I should have included some sample code. I'm actually looking
for the generic pointer to the class data member (the offset), not a
pointer to a member in a specific instance, i.e.

ptrdiff_t offset = & Monkey::some_data_member;

I was able to do this with GCC 3.3. With GCC 4.0, I haven't found any
way to cast the pointer to an integer type I can store (the class loaded
at runtime so I need a generic representation of the offset).

Today I did find a web page that claimed the ISO C++ spec does not allow
for any offset calculations, and GCC removed that support recently.


Can anyone confirm that? That would be the nail in the coffin (short of
creating an instance and doing some pointer math or requiring specific
compiler versions, which I don't think will be viable).

Thanks,

Scott

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Greg Herlihy
Guest





PostPosted: Wed May 10, 2006 9:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

Tomás wrote:
Quote:
I've been searching around a bit but haven't found a definitive answer.
Is casting a pointer to a data member to an integer type legal as the
C++ language is concerned?


It seems like it should be possible to do it, though I can certainly see
how it opens up a number of pitfalls that a language designer would want
to avoid.


"reinterpret_cast".


class Monkey {
public:
int some_data_member;
};


int main()
{
Monkey monkey;

int *p = &(monkey.some_data_member);
/* Works just like any other object */

/* If you want to store it in an integral type
(for some weird reason), then do the following: */

unsigned long num = reinterpret_cast<unsigned long>(p);
}


You can even convert back from the "unsigned long" to a pointer type, but
the resulting address will only be reliable if an "unsigned long" has
enough bits to store all the info about an address.

The poster appears to be asking about converting a data member pointer
- not an ordinary pointer (that happens to point to a data member) - to
an integral value.

Revising the program accordingly:

class Monkey {
public:
int some_data_member;
};

int main()
{
int Monkey::* p;

p = &Monkey::some_data_member;

unsigned long num = reinterpret_cast<unsigned long>(p);
}

now produces this error when compiled:

Error test.cc:11: error: invalid cast from type 'int Monkey::*' to
type 'long unsigned int'

So the answer is "no". It is not legal to convert a data member pointer
to an integral value. To obtain an offset value for a data member, the
program should use the offsetof macro:

unsigned long num = offsetof(Monkey, some_data_member);

Greg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kanze
Guest





PostPosted: Wed May 10, 2006 9:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

Scott Lehman wrote:

Quote:
When I first researched this, I read that pointers to data
members were just a byte offset which made sense, and I wanted
to store that offset.

That's a frequent implementation technique, but the standard
doesn't guarantee it.

Quote:
Using GCC 3.3 at the time, casting a pointer to a data member
to a offset_t or ptrdiff_t posed no issues and things worked
great.

A g++ undocumented extension? Or a compiler error you were
exploiting?

Quote:
Now I'm moving the project to GCC 4.0, and that cast (and any
other type of cast I try) is no longer valid :(

I've been searching around a bit but haven't found a
definitive answer. Is casting a pointer to a data member to an
integer type legal as the C++ language is concerned?

Yes. It always has been.

Quote:
It seems like it should be possible to do it, though I can
certainly see how it opens up a number of pitfalls that a
language designer would want to avoid.

In general, the type exists for a reason. It allows the
implementation to use anything that works. Even if the type has
the same size as some integral type, that doesn't mean that the
contents represent an offset -- with Sun CC, they actually
correspond to the offest plus 1. (G++ uses 0xFFFFFFFF as the
representation of the null pointer. Presumably, when it
supported the conversions to and from int, converting a constant
0 gave a different result than converting an integer variable
which just happened to contain 0.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Scott Lehman
Guest





PostPosted: Thu May 11, 2006 1:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

In article <1147250651.186247.88760 (AT) i39g2000cwa (DOT) googlegroups.com>,
"Greg Herlihy" <greghe (AT) pacbell (DOT) net> wrote:
Quote:
So the answer is "no". It is not legal to convert a data member pointer
to an integral value. To obtain an offset value for a data member, the
program should use the offsetof macro:

unsigned long num = offsetof(Monkey, some_data_member);

From what I've been reading in the archives for this group, the offsetof
macro is only defined to work for PODs in ISO C++. It might have worked
for non-PODs with some compilers (just as my cast of the pointer to a
data member did), but it does not in GCC 4.0 and should not work based
on what I'm reading.

It seems like the ISO spec explicitly outlawed this kind of low-level
manipulation of non-PODs :(

Scott

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
peter koch larsen
Guest





PostPosted: Thu May 11, 2006 1:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

Scott Lehman skrev:

Quote:
Hi,

When I first researched this, I read that pointers to data members were
just a byte offset which made sense, and I wanted to store that offset.
Using GCC 3.3 at the time, casting a pointer to a data member to a
offset_t or ptrdiff_t posed no issues and things worked great.

While this is a feasible way to do pointer-to-member, it is not
mandated. So in effect you have undefined behaviour.
Quote:

Now I'm moving the project to GCC 4.0, and that cast (and any other type
of cast I try) is no longer valid :(

I've been searching around a bit but haven't found a definitive answer.
Is casting a pointer to a data member to an integer type legal as the
C++ language is concerned?

Nope. I am surprised that you did not find any useful information.

It seems like it should be possible to do it, though I can certainly see
how it opens up a number of pitfalls that a language designer would want
to avoid.

Thanks,

Scott

If you want to have the offset of a data-member, there is a standard
way to get it.
Your current approach is non-portable.

Kind regards
Peter


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Vidar Hasfjord
Guest





PostPosted: Thu May 11, 2006 1:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

Scott Lehman wrote:
Quote:
I'm actually looking for the [...] (the offset),

See the "offsetof" macro defined in <cstddef>:

size_t offsetof (structName, memberName);

Note that its implementation is platform dependent. On my compiler
(VC8) it is defined as:

#ifdef _WIN64
#define offsetof(s,m) (size_t)( (ptrdiff_t)&reinterpret_cast<const
volatile char&>((((s *)0)->m)) )
#else
#define offsetof(s,m) (size_t)&reinterpret_cast<const volatile
char&>((((s *)0)->m))
#endif

Regards,
---
Vidar Hasfjord


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Carl Barron
Guest





PostPosted: Thu May 11, 2006 10:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

In article <slehman-7D31F8.17481409052006 (AT) news (DOT) giganews.com>, Scott
Lehman <slehman@harmony-central.com> wrote:

Quote:
In article <WP08g.8900$j7.305056 (AT) news (DOT) indigo.ie>,
"Tomás" <NULL (AT) NULL (DOT) NULL> wrote:

I've been searching around a bit but haven't found a definitive
answer.
Is casting a pointer to a data member to an integer type legal as the
C++ language is concerned?


It seems like it should be possible to do it, though I can
certainly see
how it opens up a number of pitfalls that a language designer
would want
to avoid.


"reinterpret_cast".


class Monkey {
public:
int some_data_member;
};


int main()
{
Monkey monkey;

int *p = &(monkey.some_data_member);
/* Works just like any other object */

/* If you want to store it in an integral type
(for some weird reason), then do the following: */

unsigned long num = reinterpret_cast<unsigned long>(p);
}


Sorry, I should have included some sample code. I'm actually looking
for the generic pointer to the class data member (the offset), not a
pointer to a member in a specific instance, i.e.

ptrdiff_t offset = & Monkey::some_data_member;

I was able to do this with GCC 3.3. With GCC 4.0, I haven't found any
way to cast the pointer to an integer type I can store (the class loaded
at runtime so I need a generic representation of the offset).

Today I did find a web page that claimed the ISO C++ spec does not allow
for any offset calculations, and GCC removed that support recently.


Can anyone confirm that? That would be the nail in the coffin (short of
creating an instance and doing some pointer math or requiring specific
compiler versions, which I don't think will be viable).


to create and store the offsets you need the class type and the type of
the data member. You don't need an instance of the class to store
pointers to members. To use the pointer to data members need an
instance of the class.
something like this:
#include <iostream>
#include <ostream>
#include <algorithm>

struct Monkey
{
int a;
int b;
Monkey(int x,int y):a(x),b(y){}
};

void foo(const Monkey &m,int Monkey::* p)
{
std::cout << m.*p << ' ';
}

int main()
{
int Monkey::*p1 = &Monkey::a;
int Monkey::*p2 = &Monkey::b;

Monkey m(1,2);
for(int i=0;i != 11;++i)
{
std::swap(p1,p2);
foo(m,p1);
}
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Scott Lehman
Guest





PostPosted: Fri May 12, 2006 12:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

In article <e3v9a5$c2$1 (AT) s1 (DOT) news.oleane.net>,
Falk Tannhäuser <clcppm-poster (AT) this (DOT) is.invalid> wrote:
Quote:
However, if you really need to convert member pointers to offsets,
you can try the following function, for which one can imagine 2
different ways to implement it (I put them in a conditional
compilation directive):

template<typename ClassT, typename MemberT> inline
std::ptrdiff_t offset_off(MemberT ClassT::*memptr)
{
#if 0 // *** [1] ***
ClassT* pc = 0;
return reinterpret_cast<char*>(&(pc->*memptr)) -
reinterpret_cast<char*>(pc);
#else // *** [2] ***
ClassT c;
return reinterpret_cast<char*>(&(c.*memptr)) -
reinterpret_cast<char*>(&c);
#endif
}

Keep in mind that the way [1] relies on Undefined Behaviour,
thus it may work on some implementations and break on others
- especially in presence of multiple or virtual inheritance.

Way [2], while not suffering from this problem, has the
disadvantage of instantiating the class in question -
in particular it requires the presence of an accessible
default constructor.

Thanks. I'll keep this in mind, though it's certainly not optimal and
maybe a bit too risky.

Quote:
So there is no 100% satisfying solution to your problem,
short of proposing an appropriate new feature to the Standard...

Oh well. Guess I'll either just stick with C for this part or change
the API.

I think the matter is closed now. I see what I was doing was
implementation specific and not defined by the language, and unless I'm
dealing with PODs, getting byte offsets isn't quite trivial.

Thanks to all for the assistance - the archives for this group have been
very helpful on multiple occasions.

Scott

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kanze
Guest





PostPosted: Fri May 12, 2006 12:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

Vidar Hasfjord wrote:
Quote:
Scott Lehman wrote:
I'm actually looking for the [...] (the offset),

See the "offsetof" macro defined in <cstddef>:

size_t offsetof (structName, memberName);

Which only works for PODSs.

Quote:
Note that its implementation is platform dependent.

By definition. That's why it's in the library -- there is no
way to implement it yourself.

Quote:
On my compiler
(VC8) it is defined as:

#ifdef _WIN64
#define offsetof(s,m) (size_t)( (ptrdiff_t)&reinterpret_cast<const
volatile char&>((((s *)0)->m)) )
#else
#define offsetof(s,m) (size_t)&reinterpret_cast<const volatile
char&>((((s *)0)->m))
#endif

That's weird (especially the difference -- I don't see what the
cast to ptrdiff_t adds). The historically traditional
definition in C was the much simpler:

#define offsetof(s, m) (size_t)(&(((s *)0)->m))

and I don't see what the added complexity above buys.

Of course, today, one would expect something along the lines of:

#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)

This has the advantage of being able to give a compiler error in
case of undefined behavior.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Tomás
Guest





PostPosted: Sat May 13, 2006 12:21 am    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

Quote:
A standard way to get a byte offset for a data member of a non-POD?
That would be what I'm looking for, and haven't found..

Why not just go the hardcore route?

#include <string>

class Monkey { /* Not a POD */
public:

int i;
std::string str;

char k;
};


/* "Adrs" is an abbreviation for "Address" */

const char* ByteAdrs( const T* const p )
{
return reinterpet_cast<const char*>(p);
}

template<class T>
char* ByteAdrs( T* const p )
{
return reinterpret_cast<char*>(p);
}


int main()
{
Monkey sample_monkey;

unsigned long offset1 =
ByteAdrs(&sample_monkey.i) - ByteAdrs(&sample_monkey);

unsigned long offset2 =
ByteAdrs(&sample_monkey.str) - ByteAdrs(&sample_monkey);

unsigned long offset3 =
ByteAdrs(&sample_monkey.k) - ByteAdrs(&sample_monkey);

}


Then you could use another template to get the members back. Here's some
code:

#include <string>

class Monkey { /* Not a POD */
public:

int i;
std::string str;

char k;
};


/* "Adrs" is an abbreviation for "Address" */

template<class T>
const char* ByteAdrs( const T* const p )
{
return reinterpret_cast<const char*>(p);
}

template<class T>
char* ByteAdrs( T* const p )
{
return reinterpret_cast<char*>(p);
}


template<class MemberType, class ClassType>
MemberType& GetMember( ClassType* const p_object, unsigned long offset)
{
return

reinterpret_cast< MemberType& >
(
*( ByteAdrs(p_object) + offset )
);
}

#include <iostream>
using std::cout;
#include <ostream>
using std::endl;

int main()
{
Monkey sample_monkey;

sample_monkey.str = "Hello! I'm not corrupted!";

unsigned long offset2 =
ByteAdrs(&sample_monkey.str) - ByteAdrs(&sample_monkey);

std::string& str = GetMember<std::string>( &sample_monkey, offset2 );

cout << str;
}


-Tomás

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Francis Glassborow
Guest





PostPosted: Sat May 13, 2006 12:21 am    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

In article <slehman-D00488.21420111052006 (AT) news (DOT) giganews.com>, Scott
Lehman <slehman@harmony-central.com> writes
Quote:
In article <1147287169.186938.52600 (AT) q12g2000cwa (DOT) googlegroups.com>,
"peter koch larsen" <peter.koch.larsen (AT) gmail (DOT) com> wrote:
If you want to have the offset of a data-member, there is a standard
way to get it.
Your current approach is non-portable.

A standard way to get a byte offset for a data member of a non-POD?
That would be what I'm looking for, and haven't found..

Perhaps if you shared with us the problem rather than trying to get us
help you make your solution work you might make more progress.

Almost always when someone asks how to do something the correct response
is 'why do you want to do that?' Sometimes the 'why' is necessary to
give a coherent answer to the original question, sometimes it reveals
that the original question is about a poor solution to the problem.



--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Scott Lehman
Guest





PostPosted: Sat May 13, 2006 12:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

In article <myL2iRMnuHZEFwV+@robinton.demon.co.uk>,
Francis Glassborow <francis (AT) robinton (DOT) demon.co.uk> wrote:
Quote:
Perhaps if you shared with us the problem rather than trying to get us
help you make your solution work you might make more progress.

Almost always when someone asks how to do something the correct response
is 'why do you want to do that?' Sometimes the 'why' is necessary to
give a coherent answer to the original question, sometimes it reveals
that the original question is about a poor solution to the problem.


Fair enough. I usually try and get right to the point though, as I have
a tendency to ramble on :)

My interest in member offsets is for plug-in registration. One goal is
to make creating a plug-in as simple as possible, and by returning
offsets to data members, I could enable to host to directly get/set
values with very little code in the plug-in. Not proper OO design I
know, but I like being able to get a lot for free rather than doing the
same thing over and over.

So being able to simply cast & MyClass :: member to an offset was ideal.
With the C++ helper classes, I know now that won't happen :(


It's not a huge deal. It just means a little more code in the plug-ins
to get/set data which is fine. I had been using offsetof for structs,
and I assumed I should be able to do something similar for classes too,
but now I know better!

I'm a little disappointed that what I want isn't possible, but it is
what it is and I don't want to get sidetracked as to whether the
standard should/n't allow it. It won't change for me ;)

Scott

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Scott Lehman
Guest





PostPosted: Sat May 13, 2006 12:21 pm    Post subject: Re: Cast pointer to data member to integer type - legit? Reply with quote

In article <MQ09g.9080$j7.305487 (AT) news (DOT) indigo.ie>,
"Tomás" <NULL (AT) NULL (DOT) NULL> wrote:

Quote:
A standard way to get a byte offset for a data member of a non-POD?
That would be what I'm looking for, and haven't found..

Why not just go the hardcore route?

Definitely harder core than what I was hoping for, but I might be able
to rework things to utilize it if I continue down this route.

Thanks,

Scott

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.