473,508 Members | 2,088 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Pointer to member-of-member???

I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?

Obviously I can point at the b with

int S2:*p = &S2::b;

But the seemingly obvious syntax

int S2::*p = &S2::s.a;

doesn't work - because S2::s.a is not a /qualified-id/ - and neither
does anything else I can think of.

After all, if I have an S2 structure, there's absolutely no difference
from the compiler's POV between s2.s.a and s2.b, so why should I not be
able to have a construct s2.*p equivalent to the former case?

At the moment, the only thing I have found is a rather yucky workaround
with offsetof() macros and lots of casts. That is,

size_t offset = offsetof (S2, s.a);

*(int *) ((char *) &s2 + offset) = 123;

Ugh :-(((

Any better suggestions gratefully received!
Feb 16 '06 #1
40 2975
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?

Obviously I can point at the b with

int S2:*p = &S2::b;

But the seemingly obvious syntax

int S2::*p = &S2::s.a;


void f()
{
int S1::*p = &S1::a;
S2 s2;

(s2.s).*a = 7; // parens because I can never remember .* precedence
}
Feb 16 '06 #2
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?
Well, a is an int, so what's wrong with an int*?
Obviously I can point at the b with

int S2:*p = &S2::b;
Can you?
But the seemingly obvious syntax

int S2::*p = &S2::s.a;
Not so obvious to me. There's aren't member functions.
doesn't work - because S2::s.a is not a /qualified-id/ - and neither
does anything else I can think of.

After all, if I have an S2 structure, there's absolutely no difference
from the compiler's POV between s2.s.a and s2.b, so why should I not be
able to have a construct s2.*p equivalent to the former case?

At the moment, the only thing I have found is a rather yucky workaround
with offsetof() macros and lots of casts. That is,

size_t offset = offsetof (S2, s.a);

*(int *) ((char *) &s2 + offset) = 123;

Ugh :-(((

Any better suggestions gratefully received!


What's wrong with:

int* s2s1a = &s2.s.a;

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Feb 16 '06 #3
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?

Obviously I can point at the b with

int S2:*p = &S2::b;
This isn't valid C++ syntax.
But the seemingly obvious syntax

int S2::*p = &S2::s.a;

?

Data members of a class/struct an only be accesses through an instance
of that object:

S2 s2;

int* p = &s2.s.a;

Are you confused with pointers to member functions?

--
Ian Collins.
Feb 16 '06 #4
"red floyd" <no*****@here.dude> wrote in message
news:AF*******************@newssvr11.news.prodigy. com
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?

Obviously I can point at the b with

int S2:*p = &S2::b;

But the seemingly obvious syntax

int S2::*p = &S2::s.a;


void f()
{
int S1::*p = &S1::a;
S2 s2;

(s2.s).*a = 7; // parens because I can never remember .* precedence
}

You mean

(s2.s).*p = 7;

--
John Carson
Feb 16 '06 #5
red floyd wrote:
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?

Obviously I can point at the b with

int S2:*p = &S2::b;

But the seemingly obvious syntax

int S2::*p = &S2::s.a;


void f()
{
int S1::*p = &S1::a;
S2 s2;

(s2.s).*a = 7; // parens because I can never remember .* precedence
}


Thanks, but that's not what I want. I want a pointer to an int
/somewhere/ in S2, not one that makes me specify exactly what bit of S2
it's in.
Feb 16 '06 #6
Ben Pope wrote:
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?


Well, a is an int, so what's wrong with an int*?


It's not a pointer-to-member!
Feb 16 '06 #7
"Ben Pope" <be***************@gmail.com> wrote in message
news:43**********************@taz.nntpserver.com
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?


Well, a is an int, so what's wrong with an int*?


If you have only one S1 object, then probably nothing. If you have 1,000,
then you would need 1,000 pointers. With a pointer to member, by contrast,
you only need one pointer to member.
Obviously I can point at the b with

int S2:*p = &S2::b;


Can you?


Yes, he can.
But the seemingly obvious syntax

int S2::*p = &S2::s.a;


Not so obvious to me. There's aren't member functions.


That particular syntax is wrong, but you can have pointers to data members,
just as you can have pointers to member functions. A pointer to member is
essentially an offset into the class, e.g.,

struct Foo
{
int x, y;
};

int Foo::*px = &Foo::x;
int Foo::*py = &Foo::y;

Now, given:

Foo f1;

you can use

f1.*px and f1.*py

in place of

f1.x and f1.y

respectively. More significantly, given:

Foo array[1000];

you can use

array[i].*px and array[i].*py

for i=0 to 999 in place of

array[i].x and array[i].y

respectively. What is the point? Suppose you wanted to swap the roles of x
and y (because, e.g., they represent coordinates and you are doing a
coordinate transformation). Then you just need to change the pointer
assignments to:

px = &Foo::y;
py = &Foo::x;

and now

array[i].*px will affect the y value and array[i].*py will affect the x
value.
--
John Carson

Feb 16 '06 #8
Ian Collins wrote:
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?

Obviously I can point at the b with

int S2:*p = &S2::b;
This isn't valid C++ syntax.


Whoops, missing ':'

int S2::*p = &S2::b;

But with that typo fixed, it's definitely proper C++.
Are you confused with pointers to member functions?


Pointers to data members are perfectly valid. In any case, the same
problem applies with pointers to function members. IOW, if I replaced
the declarations 'int a' and 'int b' with 'int a()' and 'int b()',
there'd still be no obvious way of specifying a pointer to member a;
Feb 16 '06 #9
"Steve Rencontre" <re******@valid.address> wrote in message
news:6J******************************@pipex.net
red floyd wrote:
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?

Obviously I can point at the b with

int S2:*p = &S2::b;

But the seemingly obvious syntax

int S2::*p = &S2::s.a;


void f()
{
int S1::*p = &S1::a;
S2 s2;

(s2.s).*a = 7; // parens because I can never remember .*
precedence }


Thanks, but that's not what I want. I want a pointer to an int
/somewhere/ in S2, not one that makes me specify exactly what bit of
S2 it's in.

Then I believe you are out of luck. You only get that sort of flexibility
with a regular pointer, not with a pointer to member.
--
John Carson
Feb 16 '06 #10
Steve Rencontre wrote:


Thanks, but that's not what I want. I want a pointer to an int
/somewhere/ in S2, not one that makes me specify exactly what bit of S2
it's in.


That doesn't make sense, poners point to exact things.

--
Ian Collins.
Feb 16 '06 #11
Steve Rencontre wrote:
Ben Pope wrote:
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?


Well, a is an int, so what's wrong with an int*?

It's not a pointer-to-member!


It is when the member is an int. You have pointers to member functions
mixed up with normal pointers.

--
Ian Collins.
Feb 16 '06 #12
"Ian Collins" <ia******@hotmail.com> wrote in message
news:11***************@drone2-svc-skyt.qsi.net.nz
Steve Rencontre wrote:
Ben Pope wrote:
Steve Rencontre wrote:

I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?

Well, a is an int, so what's wrong with an int*?

It's not a pointer-to-member!


It is when the member is an int.


A data member that is an int can be pointed to in two ways: by a regular
pointer to int and by a pointer to a member int. You don't seem to believe
in the existence of the second category of pointers. They do exist
nevertheless. See my reply to Ben Pope.

--
John Carson
Feb 16 '06 #13
"Ian Collins" <ia******@hotmail.com> wrote in message
news:11***************@drone2-svc-skyt.qsi.net.nz
Steve Rencontre wrote:


Thanks, but that's not what I want. I want a pointer to an int
/somewhere/ in S2, not one that makes me specify exactly what bit of
S2 it's in.


That doesn't make sense, poners point to exact things.


It does make sense. You can define

int * ptr;

and make it point to any int (only one int at a time, of course).

In a similar way, Steve wants a pointer to member int that can be made to
point to many different int members, although only one at a time. Alas, he
wants it to be able to point to both direct members and indirect members
(i.e., members of members). This is not possible, as far as I know.

--
John Carson
Feb 16 '06 #14
John Carson wrote:
"red floyd" <no*****@here.dude> wrote in message

void f()
{
int S1::*p = &S1::a;
S2 s2;

(s2.s).*a = 7; // parens because I can never remember .* precedence
}

You mean

(s2.s).*p = 7;


Yes. I did. Oops. :)
Feb 16 '06 #15
John Carson wrote:

A data member that is an int can be pointed to in two ways: by a regular
pointer to int and by a pointer to a member int. You don't seem to believe
in the existence of the second category of pointers. They do exist
nevertheless. See my reply to Ben Pope.

Oh I do, I was just a little confused by the question....

--
Ian Collins.
Feb 16 '06 #16

Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?


You can't. In order to have a pointer to a member, the pointer must be
to a member of the class designated by the pointer. Since a is a member
of S1, and not a member of S2, it can only be designated with an S1
pointer-to-member variable.

It is however possible to to apply two member pointers, one S2 member
pointer and one S1 member pointer to specify an int member of an S1
struct that is a data member of an S2 struct. For instance, declaring:

S1 S2::*p1;
int S1::*p2;

and then initializing both appropriately (for example, p1 = &S1::s; p2
= &S2::a) makes it possible to reach S1's "a" data member from an S2
struct by applying p1 to an instance of an S2 struct, and then applying
p2 to the result of that operation.

Greg

Feb 16 '06 #17
John Carson wrote:

struct Foo
{
int x, y;
};

int Foo::*px = &Foo::x;
int Foo::*py = &Foo::y;

Now, given:

Foo f1;

you can use

f1.*px and f1.*py

in place of

f1.x and f1.y

respectively. More significantly, given:

Foo array[1000];

you can use

array[i].*px and array[i].*py

for i=0 to 999 in place of

array[i].x and array[i].y

respectively. What is the point? Suppose you wanted to swap the roles of x
and y (because, e.g., they represent coordinates and you are doing a
coordinate transformation). Then you just need to change the pointer
assignments to:

px = &Foo::y;
py = &Foo::x;

and now

array[i].*px will affect the y value and array[i].*py will affect the x
value.


That's cunning, I like it.

Thanks for the explanation and example. Not something you see every day
(not for me, anyway!).

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Feb 16 '06 #18
Greg wrote:
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?
You can't.


So I gather...
In order to have a pointer to a member, the pointer must be
to a member of the class designated by the pointer. Since a is a member
of S1, and not a member of S2, it can only be designated with an S1
pointer-to-member variable.
Well, yes, but that seems to me an arbitrary limitation. Although a is
not a member of S2, I contend that s.a is, the only problem being the .
operator which is not allowed in a /qualified-name/.

Since the thing with offsetof() and casts works perfectly well and is
completely portable, I am a bit frustrated I can't do it with a decent
syntax.
It is however possible to to apply two member pointers


Yuk. Sorry.

But as it happens, this is now all a bit academic. I've managed to
rearrange the code in question so that it now decides which member to
point to /after/ it gets the actual object reference, which means I can
just use a straight int *. I still wish it were possible, though,
because it would be slightly more elegant that way. (Although it's still
better than the hideous offsetof() bodge!)
Feb 16 '06 #19
Steve Rencontre wrote:
Greg wrote:
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?


You can't.


So I gather...
In order to have a pointer to a member, the pointer must be
to a member of the class designated by the pointer. Since a is a member
of S1, and not a member of S2, it can only be designated with an S1
pointer-to-member variable.


Well, yes, but that seems to me an arbitrary limitation. Although a is
not a member of S2, I contend that s.a is, the only problem being the .
operator which is not allowed in a /qualified-name/.


Because that operator is for accessing _objects_ only. It can't be applied
to types. It's not just a limitation of the syntax.

An int S2::* can only point to int members of S2. S1 is a different
structure, and S1::a is obviously not a member of S2, so if you want to
point to an int member of S1 (no matter where the actual object you want to
acces lives), you need an int S1::*.
There is no such thing as "members of members". That's because on one side,
you're talking about types, on the other side there are objects. While S1
and S2 are types, S2::s is not.
It is however possible to to apply two member pointers


Yuk. Sorry.


Well, you can wrap that into a class (or even a class template) that does
what you want.

Feb 16 '06 #20
Rolf Magnus wrote:
An int S2::* can only point to int members of S2. S1 is a different
structure, and S1::a is obviously not a member of S2, so if you want to
point to an int member of S1 (no matter where the actual object you want to
acces lives), you need an int S1::*.


I don't accept that.

Consider this:

struct S2A { struct { int a; }; };
struct S2B { struct { int a; } s; };
struct S2C { struct S1C { int a; }; };

int S2A::*pa = &S2A::a; // works
int S2B::*pb = &S2B::a; // fails
int S2C::*pc = &S2C::a; // fails

The structures are all physically identical; I contend that it is purely
a syntactical issue that there is no way of expressing the obvious
semantic intent in cases B and C.
Feb 16 '06 #21

Steve Rencontre wrote:
Rolf Magnus wrote:
An int S2::* can only point to int members of S2. S1 is a different
structure, and S1::a is obviously not a member of S2, so if you want to
point to an int member of S1 (no matter where the actual object you want to
acces lives), you need an int S1::*.


I don't accept that.

Consider this:

struct S2A { struct { int a; }; };
struct S2B { struct { int a; } s; };
struct S2C { struct S1C { int a; }; };

int S2A::*pa = &S2A::a; // works
int S2B::*pb = &S2B::a; // fails
int S2C::*pc = &S2C::a; // fails

The structures are all physically identical; I contend that it is purely
a syntactical issue that there is no way of expressing the obvious
semantic intent in cases B and C.


No, it's a storage issue. The problem is that a pointer to a member of
a member would need to store two offsets: the offset to the immediate
member and then a second offset to the member within that member. In
other words this kind of member pointer would somehow have to be able
to store twice the information in the same amount of space (and each
additional level would of course each add an additional offset that
would also need to be stored in this über member pointer). Since there
is no room to store multiple offsets in a pointer large enough to hold
only one offset, only member pointers to immediate members of a class
are supported in C++.

Greg

Feb 16 '06 #22
"Greg" <gr****@pacbell.net> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com
Steve Rencontre wrote:
Rolf Magnus wrote:
An int S2::* can only point to int members of S2. S1 is a different
structure, and S1::a is obviously not a member of S2, so if you
want to point to an int member of S1 (no matter where the actual
object you want to acces lives), you need an int S1::*.


I don't accept that.

Consider this:

struct S2A { struct { int a; }; };
struct S2B { struct { int a; } s; };
struct S2C { struct S1C { int a; }; };

int S2A::*pa = &S2A::a; // works
int S2B::*pb = &S2B::a; // fails
int S2C::*pc = &S2C::a; // fails

The structures are all physically identical; I contend that it is
purely a syntactical issue that there is no way of expressing the
obvious semantic intent in cases B and C.


No, it's a storage issue. The problem is that a pointer to a member of
a member would need to store two offsets: the offset to the immediate
member and then a second offset to the member within that member. In
other words this kind of member pointer would somehow have to be able
to store twice the information in the same amount of space (and each
additional level would of course each add an additional offset that
would also need to be stored in this über member pointer). Since there
is no room to store multiple offsets in a pointer large enough to hold
only one offset, only member pointers to immediate members of a class
are supported in C++.

Greg

You may be right --- I know close to zero about compilers --- but it is not
obvious that you couldn't simply sum the two offsets and store the sum in a
single location.

--
John Carson
Feb 16 '06 #23
"Steve Rencontre" <re******@valid.address> wrote in message
news:9b********************@pipex.net
Rolf Magnus wrote:
An int S2::* can only point to int members of S2. S1 is a different
structure, and S1::a is obviously not a member of S2, so if you want
to point to an int member of S1 (no matter where the actual object
you want to acces lives), you need an int S1::*.


I don't accept that.

Consider this:

struct S2A { struct { int a; }; };
struct S2B { struct { int a; } s; };
struct S2C { struct S1C { int a; }; };

int S2A::*pa = &S2A::a; // works
int S2B::*pb = &S2B::a; // fails
int S2C::*pc = &S2C::a; // fails

The structures are all physically identical; I contend that it is
purely a syntactical issue that there is no way of expressing the
obvious semantic intent in cases B and C.


Actually, S2A is illegal (though Microsoft allows it as an extension) and
S2C has no members --- it is simply a type definition that contains another
type definition.

However,

struct S {int a;};

and struct S2B are physically identical, so we can use those to represent
your point.

Pointers to data members are rarely used. Pointers to data members of data
members are extremely rarely used. Doing what you want would complicate the
task of compiler writers --- by how much I am in no position to say --- and
I expect that it hasn't been thought worth the trouble --- to the extent
that it has been thought of at all.
--
John Carson

Feb 16 '06 #24
Steve Rencontre wrote:
Rolf Magnus wrote:
An int S2::* can only point to int members of S2. S1 is a different
structure, and S1::a is obviously not a member of S2, so if you want to
point to an int member of S1 (no matter where the actual object you want
to acces lives), you need an int S1::*.
I don't accept that.

Consider this:

struct S2A { struct { int a; }; };
struct S2B { struct { int a; } s; };
struct S2C { struct S1C { int a; }; };

int S2A::*pa = &S2A::a; // works
int S2B::*pb = &S2B::a; // fails
int S2C::*pc = &S2C::a; // fails

The structures are all physically identical;


S2B doesn't have a member named a. Only the anonymous struct within it has
one. S2C doesn't have any member variables at all. Regarding S2A, I'm
actually surprised that this works. Maybe some obscure C++ rule because
that anonymous struct member wouldn't be useful otherwise.
I contend that it is purely a syntactical issue that there is no way of
expressing the obvious semantic intent in cases B and C.


They aren't obvious.

Feb 16 '06 #25
John Carson wrote:
"Steve Rencontre" <re******@valid.address> wrote in message
struct S2A { struct { int a; }; };
struct S2B { struct { int a; } s; };
struct S2C { struct S1C { int a; }; };

int S2A::*pa = &S2A::a; // works
int S2B::*pb = &S2B::a; // fails
int S2C::*pc = &S2C::a; // fails

The structures are all physically identical; I contend that it is
purely a syntactical issue that there is no way of expressing the
obvious semantic intent in cases B and C.


Actually, S2A is illegal (though Microsoft allows it as an extension)


So does gcc unless you specify -pedantic. When MS and Gnu agree on
something, it's probably fairly uncontroversial :-)
S2C has no members --- it is simply a type definition that contains another
type definition.
Whoops, silly me, I do know that really...
Pointers to data members are rarely used.
True...
Pointers to data members of data members are extremely rarely used.
Err, /never/ AFAICT, 'cos there ain't no syntax to create them!
Doing what you want would complicate the
task of compiler writers
OTTOMH, I think the additional complexity would be lost in the noise
given what a C++ compiler has to do overall!
I expect that it hasn't been thought worth the trouble --- to the extent
that it has been thought of at all.


Yes, judging by the number of people (not just here) who at least
initially completely failed to grasp what I was trying to do!
Feb 16 '06 #26
John Carson wrote:
"Greg" <gr****@pacbell.net> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com
Steve Rencontre wrote:
Rolf Magnus wrote:

An int S2::* can only point to int members of S2. S1 is a different
structure, and S1::a is obviously not a member of S2, so if you
want to point to an int member of S1 (no matter where the actual
object you want to acces lives), you need an int S1::*.

I don't accept that.

Consider this:

struct S2A { struct { int a; }; };
struct S2B { struct { int a; } s; };
struct S2C { struct S1C { int a; }; };

int S2A::*pa = &S2A::a; // works
int S2B::*pb = &S2B::a; // fails
int S2C::*pc = &S2C::a; // fails

The structures are all physically identical; I contend that it is
purely a syntactical issue that there is no way of expressing the
obvious semantic intent in cases B and C.


No, it's a storage issue. The problem is that a pointer to a member of
a member would need to store two offsets: the offset to the immediate
member and then a second offset to the member within that member. In
other words this kind of member pointer would somehow have to be able
to store twice the information in the same amount of space (and each
additional level would of course each add an additional offset that
would also need to be stored in this über member pointer). Since there
is no room to store multiple offsets in a pointer large enough to hold
only one offset, only member pointers to immediate members of a class
are supported in C++.

Greg

You may be right --- I know close to zero about compilers --- but it is
not obvious that you couldn't simply sum the two offsets and store the sum
in a single location.


Well, things may get a bit more complicated once you start using non-pod
types and multiple and virtual inheritance.

Feb 16 '06 #27
Rolf Magnus wrote:
Steve Rencontre wrote:
struct S2A { struct { int a; }; };
struct S2B { struct { int a; } s; };
S2B doesn't have a member named a. Only the anonymous struct within it has
one. S2C doesn't have any member variables at all. Regarding S2A, I'm
actually surprised that this works. Maybe some obscure C++ rule because
that anonymous struct member wouldn't be useful otherwise.


As noted elsewhere, S2C was just me being stupid, but while S2A is not
strict ISO standard C++, it is a common extension.
I contend that it is purely a syntactical issue that there is no way of
expressing the obvious semantic intent in cases B and C.


They aren't obvious.


Ok, let's look at it from a different angle, forgetting non-standard
extensions:

struct S2A {
int x1;
int x2;
int x3;
};

struct S1 { int x1; int x2; }
struct S2B {
S1 s;
int x3;
};

struct S2C {
struct {
int x1;
int x2;
} s;
int x3;
};

Each and every one of these has exactly the same memory representation
(modulo alignment issues).

I trust we all agree that the meaning of

int S2A::*pa = &S2A::x2;

is straightforward and well-defined; given an S2A object, I can pick out
the middle int from it. The pointer-to-member is basically an
encapsulation of "Add offsetof(S2A,x2) to the object base". The same
concept is just as meaningful for S2B and S2C objects, but there's no
way of expressing it.

Finally, what about

struct S2D {
int x [3];
};

Now there's no confusion with nested structures, name scopes or anything
like that at all, but &S2D::x[1] doesn't work either. Yes, the pedantic
argument is that 'x' is a member of S2D and 'x[1]' isn't, but that
doesn't mean it's not a meaningful and reasonable thing to want to do.
Feb 16 '06 #28
Rolf Magnus wrote:
John Carson wrote:
You may be right --- I know close to zero about compilers --- but it is
not obvious that you couldn't simply sum the two offsets and store the sum
in a single location.


Well, things may get a bit more complicated once you start using non-pod
types and multiple and virtual inheritance.


There are already lots of things that are restricted to POD types.

However, I don't think pointer-to-member-of-member introduces any new
complexity beyond that of ordinary pointer-to-member in the presence of
multiple/virtual inheritance.
Feb 16 '06 #29

Steve Rencontre wrote:
At the moment, the only thing I have found is a rather yucky workaround
with offsetof() macros and lots of casts. That is,

size_t offset = offsetof (S2, s.a);

*(int *) ((char *) &s2 + offset) = 123;


That is the only way but you don't need so many casts and you should
use C++ casts.

I also had such a problem. A redesign of what I was doing resulted in
a better solution. The offset thing was a necessity to do OO in C but
it isn't in C++. If you have such an issue where the offset macro is
needed you should be looking for a better solution, not just a better
way to get the offset.

Feb 16 '06 #30
Steve Rencontre wrote:

Ok, let's look at it from a different angle, forgetting non-standard
extensions:

struct S2A {
int x1;
int x2;
int x3;
};

struct S1 { int x1; int x2; }
struct S2B {
S1 s;
int x3;
};

struct S2C {
struct {
int x1;
int x2;
} s;
int x3;
};

Each and every one of these has exactly the same memory representation
(modulo alignment issues).
Ignoring possible differences, they're the same, yes.
I trust we all agree that the meaning of

int S2A::*pa = &S2A::x2;

is straightforward and well-defined; given an S2A object, I can pick out
the middle int from it. The pointer-to-member is basically an
encapsulation of "Add offsetof(S2A,x2) to the object base". The same
concept is just as meaningful for S2B and S2C objects, but there's no
way of expressing it.
C++ is a type safe language, so I beg to differ. And you can't just
throw away alignment issues, those are not guaranteed. So in a
hypothetical situation, I might be persuaded to agree, but that's not
relevant.

If you don't see the difference between pointer to member and pointer to
member of member as relevant, flatten your hierarchy.
Finally, what about

struct S2D {
int x [3];
};

Now there's no confusion with nested structures, name scopes or anything
like that at all, but &S2D::x[1] doesn't work either. Yes, the pedantic
argument is that 'x' is a member of S2D and 'x[1]' isn't, but that
doesn't mean it's not a meaningful and reasonable thing to want to do.


If you want to leave the realms of defined behaviour, feel free to use
reinterpret_cast or a union.

If it can't be done in the language rules, and you want more of an
explanation why, then may I suggest:

comp.std.c++

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Feb 16 '06 #31
ro**********@gmail.com wrote:
Steve Rencontre wrote:
At the moment, the only thing I have found is a rather yucky workaround
with offsetof() macros and lots of casts. That is,

size_t offset = offsetof (S2, s.a);

*(int *) ((char *) &s2 + offset) = 123;
That is the only way but you don't need so many casts


How do I do it with fewer casts, unless I do something equally horrible
like,

*((int *) &s2 + offset / sizeof (int))
and you should use C++ casts.


Ok,

*reinterpret_cast <int *> (reinterpret_cast <char *> (*s2) +
offset)

Better? I don't really think so :-)
Feb 16 '06 #32
Ben Pope wrote:
Steve Rencontre wrote:

Each and every one of these has exactly the same memory representation
(modulo alignment issues).
Ignoring possible differences, they're the same, yes.


The differences are not relevant differences. I'm not trying to lay one
structure on top of another, just pointing out that every one of them
contains three ints at knowable (the compiler knows them even if I
don't), fixed offsets from the base of the enclosing struct.
C++ is a type safe language, so I beg to differ.
In what way is it not type-safe to have a thing which purports to point
to an int in an object of class X pointing to an int in an object of
class X?
And you can't just throw away alignment issues, those are not guaranteed.
I don't need any guarantee of alignment. I'm not asking to be able to
use an S2A::* pointer with an S2B object. What you're saying sounds like
you think that two objects of the same type aren't guaranteed to have
the same memory layout!
If you want to leave the realms of defined behaviour, feel free to use
reinterpret_cast or a union.
They won't do the job in this case. There is no syntax which lets me
specify the pointer I want in any form whatsoever unless I figure out
the compiler's internal representation of pointer-to-member and create
it entirely by hand. Since the offsetof() version is legal and portable,
I see no benefit in doing so!
comp.std.c++


I may well do so.

However, what I originally wanted was not to know why it couldn't be
done, but how to do it! More precisely, I was looking for a way to do it
in the spirit of C++, given that I already have a way of doing it in
classic C hacker style :-)
Feb 16 '06 #33
Steve Rencontre wrote:
Ben Pope wrote:
Steve Rencontre wrote:
Each and every one of these has exactly the same memory representation
(modulo alignment issues). Ignoring possible differences, they're the same, yes.


The differences are not relevant differences. I'm not trying to lay one
structure on top of another, just pointing out that every one of them
contains three ints at knowable (the compiler knows them even if I
don't), fixed offsets from the base of the enclosing struct.
C++ is a type safe language, so I beg to differ.


In what way is it not type-safe to have a thing which purports to point
to an int in an object of class X pointing to an int in an object of
class X?


You're asking for a pointer to an int member of S2, if it's a member of
a member of S2, it's not a member of S2.
And you can't just throw away alignment issues, those are not guaranteed.


I don't need any guarantee of alignment. I'm not asking to be able to
use an S2A::* pointer with an S2B object. What you're saying sounds like
you think that two objects of the same type aren't guaranteed to have
the same memory layout!


But they're not the same type! A pointer to an int member of S2 is not
the same as a pointer to an int member of instance of S1 as a member of S2.

I think I may have your original requirements confused:
how can I get a pointer to the a in an S2?


The a isn't in S2, it's in S1, so:

int S1::*p1 = &S1::a;
s2.s.*p1 = 2;
I've summarised some options below (mostly for my own sanity!)
struct S1 { int a; };
struct S2 { S1 s; int b; };
struct S3 {
struct S1 { int a; } s;
int b;
};

int main() {
int S1::*p1 = &S1::a;
int S2::*p2 = &S2::b;
int S3::S1::*p3 = &S3::S1::a;

S1 s1;
S2 s2;
S3 s3;

s1.*p1 = 1; // s1.a
s2.s.*p1 = 2; // s2.s.a
s2.*p2 = 2; // s2.b
s3.s.*p3 = 3; // s3.s.a
}

Or did you want to be able to point to a or b with the same pointer?

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Feb 16 '06 #34
Ben Pope wrote:
Or did you want to be able to point to a or b with the same pointer?


Yes! I'm sorry if I didn't make that clear enough from the start.
Feb 16 '06 #35
Steve Rencontre wrote:
Ben Pope wrote:
Or did you want to be able to point to a or b with the same pointer?


Yes! I'm sorry if I didn't make that clear enough from the start.


That's what I had assumed (along with everybody else I think!).

Wondered if I was going off track.

Can't be done :P

Sorry!

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Feb 16 '06 #36
Steve Rencontre wrote:
Ben Pope wrote:
Steve Rencontre wrote:

Each and every one of these has exactly the same memory representation
(modulo alignment issues).


Ignoring possible differences, they're the same, yes.


The differences are not relevant differences. I'm not trying to lay one
structure on top of another, just pointing out that every one of them
contains three ints at knowable (the compiler knows them even if I
don't), fixed offsets from the base of the enclosing struct.
C++ is a type safe language, so I beg to differ.


In what way is it not type-safe to have a thing which purports to point
to an int in an object of class X pointing to an int in an object of
class X?


Considering this example:

struct S1 { int x1; int x2; }
struct S2B {
S1 s;
int x3;
};

What you want is an int S2B::* that points to a member of S1, i.e. of
another struct. That means it would weaken type safety.
What if you only have a pointer or reference to the S1 instance? Still allow
an int S2B::* to point to x1, which would be logical? After all, the object
pointed to could be a member of an S2B object. But what if it's not?
And you can't just throw away alignment issues, those are not guaranteed.


I don't need any guarantee of alignment. I'm not asking to be able to
use an S2A::* pointer with an S2B object.


It looks to me as if that's exactly what you are asking.

Feb 16 '06 #37
Rolf Magnus wrote:
Considering this example:

struct S1 { int x1; int x2; }
struct S2B {
S1 s;
int x3;
};

What you want is an int S2B::* that points to a member of S1, i.e. of
another struct. That means it would weaken type safety.
What if you only have a pointer or reference to the S1 instance?
Then I need an S1::* pointer, not an S2B::* pointer.
Still allow an int S2B::* to point to x1, which would be logical?
Why is that logical?
After all, the object
pointed to could be a member of an S2B object. But what if it's not?


I don't see why you're trying to make out that I want something I don't.

Look, if I have an S2B object, s2b, we all agree that I can write,

s2b.s.x1 = 1;
s2b.x3 = 2;

On any Earthlike planet, the compiler is going to generate structurally
identical code for both cases - add a fixed offset to the object base
address to get the destination address, load a value into that address.

All I'm after is to be able to have a pointer, p, which can duplicate
the effect of either of those statements via the expression 's2b.*p'.

If I also have,

S1 *ps1 = &s2b.s;

I neither expect nor want to be able to use the expression 'ps1->*p' and
I don't understand why you seem to be insisting I do.
Feb 17 '06 #38
Steve Rencontre wrote:
Rolf Magnus wrote:
Considering this example:

struct S1 { int x1; int x2; }
struct S2B {
S1 s;
int x3;
};

What you want is an int S2B::* that points to a member of S1, i.e. of
another struct. That means it would weaken type safety.
What if you only have a pointer or reference to the S1 instance?


Then I need an S1::* pointer, not an S2B::* pointer.
Still allow an int S2B::* to point to x1, which would be logical?


Why is that logical?
After all, the object
pointed to could be a member of an S2B object. But what if it's not?


I don't see why you're trying to make out that I want something I don't.

Look, if I have an S2B object, s2b, we all agree that I can write,

s2b.s.x1 = 1;
s2b.x3 = 2;

On any Earthlike planet, the compiler is going to generate structurally
identical code for both cases - add a fixed offset to the object base
address to get the destination address, load a value into that address.

All I'm after is to be able to have a pointer, p, which can duplicate
the effect of either of those statements via the expression 's2b.*p'.

If I also have,

S1 *ps1 = &s2b.s;

I neither expect nor want to be able to use the expression 'ps1->*p' and
I don't understand why you seem to be insisting I do.


I would suggest focussing on the capabilities of the pointer you are
asking for - and not on the relatively simple manner with which you
intend to use it. You're essentially asking for a yacht which you
intend to use as a rowboat. The capabililties of a member pointer (and
by extension a member member pointer) have no relation to the actual
definition of the class to which it belongs. So even though there may
be only one data member to which a particular type of member pointer
can legitimately point to, the member pointer has to assume that there
are any number of matching members that it could point to and plan its
storage accordingly.

The pointer which you are asking for is one that must be able to point
to any int member anywhere in an S2B member located anywhere in an S1
struct. Those two "anywhere" requirements are twice the one "anywhere"
requirement for a standard member pointer. And while it is true that
your use of this member member pointer doesn't do justice to its
wideranging addressing capability, there is no way for the compiler to
slim down this type of pointer simply due to that fact. These pointers
can have only one format, and that format must be able to handle the
full requirements for that pointer type.

So the disconnect in this discussion I would say stems from the fact
that your relatively simple use of the pointer does not adequately
demonstrate the more complex cases which the same type of pointer must
(unfortunately) also be able to handle.

Greg

Feb 19 '06 #39
Greg wrote:
I would suggest focussing on the capabilities of the pointer you are
asking for - and not on the relatively simple manner with which you
intend to use it.


In an ultimate sense, yes, but my requirement is strictly in the context
of a POD struct, and I can't conceive of any situation in which what I
want doesn't boil down to a simple numerical offset. This may be a
failure of my imagination, but I don't think so.

TBH, I can't think of /any/ situation in which the address of a data
item relative to the base address of its containing object is not a
compile-time constant, and I'd be fascinated if you could give me an
example.

Sure, there are (non-ISO) concepts like MSVC++ properties, which /look/
like simple data items but aren't, but I'm not asking for that. A
pointer-to-data-member that actually referenced a property in that sense
would be a weird and wonderful thing. Sticking within the normal
definition of data members, though, I really don't see where the problem
lies.
Feb 19 '06 #40
LR
Steve Rencontre wrote:
I can't for the life of me see how to do pointer-to-member when the
member is actually part of an embedded structure.

That is, if I have:

struct S1 { int a; };
struct S2 { S1 s; int b; };

how can I get a pointer to the a in an S2?
I don't think that can be done with a single variable.


Obviously I can point at the b with

int S2:*p = &S2::b;

But the seemingly obvious syntax

int S2::*p = &S2::s.a;

doesn't work - because S2::s.a is not a /qualified-id/ - and neither
does anything else I can think of.

After all, if I have an S2 structure, there's absolutely no difference
from the compiler's POV between s2.s.a and s2.b, so why should I not be
able to have a construct s2.*p equivalent to the former case?
I think for the same reason that you can't use a pointer to a pointer to
an int to get the int. You have to get the thing that the pointer to a
pointer points to first, then you can get the int.


At the moment, the only thing I have found is a rather yucky workaround
with offsetof() macros and lots of casts. That is,

size_t offset = offsetof (S2, s.a);

*(int *) ((char *) &s2 + offset) = 123;

Ugh :-(((

Any better suggestions gratefully received!


I don't know that it's better, and it's not really an answer to your
question but more in the way of a work around.
struct S1 { int a; };
struct S2 {
private:
static int S1::*px_;
public:
S1 s;
int b;

static void s(int S1::*px) { px_ = px; }
int &px() { return s.*px_; }
};

int S1::*S2::px_;

You can use it like this:

// better make sure it's initialized before you use it.
S2::s(&S1::a);

S2 w;
w.px() = 14;

There may be some details to be worked out and there's probably a better
way to do it.

LR

Mar 10 '06 #41

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2118
by: Carsten Spieß | last post by:
Hello all, i have a problem with a template constructor I reduced my code to the following (compiled with gcc 2.7.2) to show my problem: // a base class class Base{}; // two derived...
20
6525
by: __PPS__ | last post by:
Hello everybody in a quiz I had a question about dangling pointer: "What a dangling pointer is and the danger of using it" My answer was: "dangling pointer is a pointer that points to some...
10
25998
by: Denis Palmeiro | last post by:
Hello eveyone. What exactly is a NULL Pointer Dereference? I tried searching google but the only results that returned were bug reports. Some example code, if possible, would also be...
20
6168
by: joe | last post by:
Hi all! I just have quick, possibly stupid question.... is it possible to do the following: int func(){ int *pointer; foo(pointer); } int foo(int *pointer){
16
2484
by: aegis | last post by:
Given the following: int a = 10; int *p; void *p1; unsigned char *p2; p = &a;
33
4836
by: dough | last post by:
Is it possible in C to declare and initialize a pointer that points to itself? Why or why not?
6
17058
by: murgan | last post by:
Hi people, i am new to this group,this is my first query, friends i want to know the difference between "function pointer" and "pointer to a function" in c lang, so friends please send the...
10
2242
by: lovecreatesbeauty | last post by:
Why (type*)pointer isn't equal to *(type**)pointer, In the code snippet, it shows that: (int *) == (int **) , (int *) != (*(int **)) . Does type-casting change the address? or...
11
3471
by: TefJlives | last post by:
Can someone please expain what is a NOP pointer, or give a good link? Thanks. Greg
6
2630
by: Mahendra | last post by:
I have two cases - 1. When I have a pointer A pointing to a heap memory - What happens when I dereference the pointer A using free(A). It deallocated the heap memory the pointer was pointing...
0
7328
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7388
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
7049
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7499
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
5055
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4709
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3186
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1561
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
767
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.