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 

Pointer to member array slot?
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
lindahlb@hotmail.com
Guest





PostPosted: Thu Oct 06, 2005 8:39 am    Post subject: Pointer to member array slot? Reply with quote



struct Foo
{
int bar[5];
}

int Foo::* ptr_to_3 = &(Foo::bar[0]);

g++ barfs on this, so I'm assuming this isn't standard. Is there anyway
to do this in standard C++? If not, are there any work-arounds for g++?


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

Back to top
Ben Cottrell
Guest





PostPosted: Fri Oct 07, 2005 1:04 pm    Post subject: Re: Pointer to member array slot? Reply with quote



[email]lindahlb (AT) hotmail (DOT) com[/email] wrote:
Quote:
struct Foo
{
int bar[5];
}

int Foo::* ptr_to_3 = &(Foo::bar[0]);

g++ barfs on this, so I'm assuming this isn't standard. Is there anyway
to do this in standard C++? If not, are there any work-arounds for g++?

For the left-hand side, did you mean

int * ptr_to_3 = [...] ?

the right-hand side of this expression is also invalid, since Foo::bar[]
does not exist as a static member of Foo.

Either you mean to instantiate an object of foo, and take the address of
SomeFooObject.bar[0] or you need to make bar[] static.

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


Back to top
Stanimir Kabaivanov
Guest





PostPosted: Fri Oct 07, 2005 1:08 pm    Post subject: Re: Pointer to member array slot? Reply with quote



Hi,
Quote:
struct Foo
{
int bar[5];
}

int Foo::* ptr_to_3 = &(Foo::bar[0]);

g++ barfs on this, so I'm assuming this isn't standard. Is there anyway
to do this in standard C++? If not, are there any work-arounds for g++?

Sorry, but I did not exactly get your idea?

Are you trying to get a pointer to a static type in Foo structure? E.g.
something like that:

struct Foo
{
static int bar[5];
};

int Foo::bar[5] = {0};


Or you want to have a pointer to a member function (perhaps if bar is
not array of ints, but array of function/pointers?)

Best regards,
Stanimir Kabaivanov

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


Back to top
Ron Natalie
Guest





PostPosted: Fri Oct 07, 2005 2:39 pm    Post subject: Re: Pointer to member array slot? Reply with quote

[email]lindahlb (AT) hotmail (DOT) com[/email] wrote:
Quote:
struct Foo
{
int bar[5];
}

int Foo::* ptr_to_3 = &(Foo::bar[0]);

g++ barfs on this, so I'm assuming this isn't standard. Is there anyway
to do this in standard C++? If not, are there any work-arounds for g++?

No, not standard. Before we give a workaround, you'll have to
explain what you are trying to accomplish.

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


Back to top
johnchx2@yahoo.com
Guest





PostPosted: Fri Oct 07, 2005 7:44 pm    Post subject: Re: Pointer to member array slot? Reply with quote

[email]lindahlb (AT) hotmail (DOT) com[/email] wrote:
Quote:
struct Foo
{
int bar[5];
}

int Foo::* ptr_to_3 = &(Foo::bar[0]);

g++ barfs on this, so I'm assuming this isn't standard. Is there anyway
to do this in standard C++? If not, are there any work-arounds for g++?

You've got the right idea...you just need the right syntax.

First, Foo has a member of type "array of 5 ints". This is the sort of
type that's much easier to work with through a typedef:

typedef int array5int [5];

Second, we want the address of the member, not the address of the first
element of the member, so the initializer should just be:

.... &Foo::bar;

Put it all together, and you get the following:

struct Foo {
int bar[5];
};

typedef int array5int [5];

array5int Foo::* p_bar = & Foo::bar;

int main() {
Foo f;
(f.*p_bar)[2] = 3; // parentheses are required
}

....which should compile nicely.

If you really want to do without the typedef, you can write:

int (Foo::* p_bar) [5] = & foo::bar;

....but the typedef'ed version is probably more readable.


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


Back to top
lindahlb@hotmail.com
Guest





PostPosted: Mon Oct 10, 2005 10:17 am    Post subject: Re: Pointer to member array slot? Reply with quote

The above example was great, John. However, that doesn't quite solve
the problem. What I need, if possible, is a single piece of data (a
member pointer) that can access a specific slot in a member array
without requiring any other information (in your example, the array
index).

Obviously the compiler should easily be able to derive a
representation. All it does for a member pointer is calculate the
offset of the member - all it has to do is add the index to the offset
when I take the pointer of the member array slot. Unfortunately, it
appears to be an oversight in the language to not include the syntax in
the specification.

So, are there any workarounds?

This is for a reflection system, and I'd hate to have to include
another attribute (an index) to the 'member' object just to index the
damn array when a pointer to a member array slot is completely trivial
for a compiler to compose.


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

Back to top
johnchx2@yahoo.com
Guest





PostPosted: Wed Oct 12, 2005 3:16 pm    Post subject: Re: Pointer to member array slot? Reply with quote

[email]lindahlb (AT) hotmail (DOT) com[/email] wrote:
Quote:
The above example was great, John. However, that doesn't quite solve
the problem. What I need, if possible, is a single piece of data (a
member pointer) that can access a specific slot in a member array
without requiring any other information (in your example, the array
index).

This is not provided by the language. However, it's not hard to create
a class to bundle the two pieces of information (the member pointer and
the offset) together, along with an overloaded operator ->* to hide the
ugly syntax. Here's an example:

#include <iostream>

template <
class ClassType,
class ArrayElementType,
unsigned ArraySize
Quote:

struct MemArrayElemPtr {

typedef ArrayElementType elem_t;
typedef ArrayElementType (ClassType::* mem_ptr_t)[ ArraySize ];

MemArrayElemPtr( mem_ptr_t mp, unsigned long offset ):
mMemArrayPtr( mp ), mOffset( offset ) {
}

mem_ptr_t mMemArrayPtr;
unsigned long mOffset;
};

template < class T, class U >
typename U::elem_t &
operator->* ( T* lhs, const U& rhs )
{
return (lhs->* rhs.mMemArrayPtr)[rhs.mOffset];
}


//////////////////////////////////////////////////////

struct Foo {
int bar[5];
};

typedef MemArrayElemPtr< Foo, int, 5 > foo_mem_t;


int main() {
Foo f;
f.bar[0] = 25;
foo_mem_t p_bar0 ( &Foo::bar, 0 );
foo_mem_t p_bar2 ( &Foo::bar, 2 );

&f->*p_bar2 = 3;

std::cout << "should be 25: " << &f->*p_bar0 << 'n';
std::cout << "should be 3: " << f.bar[2] << std::endl;
}


[ 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 Oct 12, 2005 4:32 pm    Post subject: Re: Pointer to member array slot? Reply with quote

[email]lindahlb (AT) hotmail (DOT) com[/email] wrote:
Quote:
The above example was great, John. However, that doesn't quite solve
the problem. What I need, if possible, is a single piece of data (a
member pointer) that can access a specific slot in a member array
without requiring any other information (in your example, the array
index).

Obviously the compiler should easily be able to derive a
representation. All it does for a member pointer is calculate the
offset of the member - all it has to do is add the index to the offset
when I take the pointer of the member array slot. Unfortunately, it
appears to be an oversight in the language to not include the syntax in
the specification.

So, are there any workarounds?

This is for a reflection system, and I'd hate to have to include
another attribute (an index) to the 'member' object just to index the
damn array when a pointer to a member array slot is completely trivial
for a compiler to compose.

A data member pointer already has to manage more information than an
ordinary pointer. Layering another level of specifiers - for indexed
access to data member arrays - would further increase their overhead
and complexity for a rarely missed feature.

An obvious workaround would be to dispense with Foo's data member array
altogether:

struct Foo
{
int firstInt;
int secondInt;
int thirdInt;
int fourthInt;
int fifthInt;
};

With the ints declared in this manner, any one of them can be
referenced individually with a int foo::* member pointer.

Of course it's likely that storing the five ints in an array offers
certain conveniences that foo's clients will not be willing to give up.
So perhaps a compromise is possible:

struct Foo
{
union
{
int bar[5];
struct
{
int firstInt;
int secondInt;
int thirdInt;
int fourthInt;
int fifthInt;
};
};
};

With this declaration clients have the convenience provided by an array
of ints while also benefitting from the precise addressability of
having individually-declared data members. Note also that the usual
restriction about accessing stored values in a union does not apply
here. a union generally requires that a value be retrieved by the same
means that was used to store that value. But because the ints in the
bar array are "layout compatible" with the ints in the unnamed struct,
the program is free to store int values in the union through bar, and
then retrieve those values via the unnamed struct (or to do so the
other way around).

Greg


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


Back to top
Allan W
Guest





PostPosted: Wed Oct 12, 2005 10:44 pm    Post subject: Re: Pointer to member array slot? Reply with quote

[email]lindahlb (AT) hotmail (DOT) com[/email] wrote:
Quote:
What I need, if possible, is a single piece of data (a
member pointer) that can access a specific slot in a member array
without requiring any other information (in your example, the array
index).

How about this?

struct Foo {
union {
struct { int bar0,bar1,bar2,bar3,bar4; }; // 5 ints
int bar[5]; // array of 5 ints
};
int baz;
};

Foo::bar0 points to Foo's bar[0], Foo::bar1 points Foo's bar[1],
and so on...

int Foo::*intptr1 = &Foo::bar0; // Points to Foo::bar[0]
int Foo::*intptr2 = &Foo::bar3; // Points to Foo::bar[3]
int Foo::*intptr3 = &Foo::baz; // Points to Foo::baz

You still can't do arithmetic on the pointer-to-members until
AFTER you dereference them on a specific Foo object, but if f
is a Foo, you can do this:
(&(f.*intptr1))[1] = 4
which is equivalent to
f.bar[4]=4;

Hope this helps.


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


Back to top
Valentin Samko
Guest





PostPosted: Thu Oct 13, 2005 12:58 pm    Post subject: Re: Pointer to member array slot? Reply with quote

Allan W wrote:
Quote:
struct Foo {
union {
struct { int bar0,bar1,bar2,bar3,bar4; }; // 5 ints
int bar[5]; // array of 5 ints
};
int baz;
};

Foo::bar0 points to Foo's bar[0], Foo::bar1 points Foo's bar[1],
and so on...

int Foo::*intptr1 = &Foo::bar0; // Points to Foo::bar[0]
int Foo::*intptr2 = &Foo::bar3; // Points to Foo::bar[3]
int Foo::*intptr3 = &Foo::baz; // Points to Foo::baz

This will result in serious bugs if compiler aligns members of your
anonymous struct, adding paddings between them.

Think of
struct { int bar0; /* 4 bytes added by the compiler */ int bar 1; /* 4
bytes added by the compiler */ ... }

Also, I do not think the standard guarantees that there will be no
padding in front of bar0.

--

Valentin Samko - http://val.samko.info

[ 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: Thu Oct 13, 2005 1:35 pm    Post subject: Re: Pointer to member array slot? Reply with quote

Greg Herlihy wrote:
Quote:
lindahlb (AT) hotmail (DOT) com wrote:
The above example was great, John. However, that doesn't
quite solve the problem. What I need, if possible, is a
single piece of data (a member pointer) that can access a
specific slot in a member array without requiring any other
information (in your example, the array index).

Obviously the compiler should easily be able to derive a
representation. All it does for a member pointer is
calculate the offset of the member - all it has to do is add
the index to the offset when I take the pointer of the
member array slot. Unfortunately, it appears to be an
oversight in the language to not include the syntax in the
specification.

So, are there any workarounds?

This is for a reflection system, and I'd hate to have to
include another attribute (an index) to the 'member' object
just to index the damn array when a pointer to a member
array slot is completely trivial for a compiler to compose.

For reflection, wouldn't it be simpler to just support a pointer
to the array, rather than a pointer to each individual element.
Something like:

template< typename C, typename T, size_t N >
struct ArrayElem
{
T (C::* elem)[ N ] ;
// ...
} ;

Quote:
A data member pointer already has to manage more information
than an ordinary pointer.

Such as? Generally, a data member pointer is nothing more than
an offset.

Quote:
Layering another level of specifiers - for indexed access to
data member arrays - would further increase their overhead and
complexity for a rarely missed feature.

What he wants is a simple pointer to member int. The fact that
the int happens to be an element of an array really doesn't
change anything. In this case, I suspect that the absense of
the feature is just an oversight; I can't see any additional
complications which it introduces. (I could have missed some.
But I'm willing to bet that if there are any, they are at the
syntax level, and not the implementation.)

Quote:
An obvious workaround would be to dispense with Foo's data
member array altogether:

struct Foo
{
int firstInt;
int secondInt;
int thirdInt;
int fourthInt;
int fifthInt;
};

With the ints declared in this manner, any one of them can be
referenced individually with a int foo::* member pointer.

If I understand his problem correctly, he doesn't have any
choice concerning the data declarations. At least, that's
usually the case with implementations of reflection.

Quote:
Of course it's likely that storing the five ints in an array
offers certain conveniences that foo's clients will not be
willing to give up.

And how. You need a switch to access the i'th member, if i
isn't a constant. And it's perfectly possible to have arrays
with thousands of members -- you could end up with a pretty big
switch.

Quote:
So perhaps a compromise is possible:

struct Foo
{
union
{
int bar[5];
struct
{
int firstInt;
int secondInt;
int thirdInt;
int fourthInt;
int fifthInt;
};
};
};

With this declaration clients have the convenience provided by
an array of ints while also benefitting from the precise
addressability of having individually-declared data members.

But you've still got the problem: given a variable i, how to do
get a pointer to member for it.

Quote:
Note also that the usual restriction about accessing stored
values in a union does not apply here.

Why not? Where is the exception in the standard? All I see is
that at most one of the data members can be active at any time.
I don't see any exceptions to the rule.

Quote:
a union generally requires that a value be retrieved by the same

s/generally/always/

There are no exceptions, as far as I can see.

Quote:
means that was used to store that value. But because the ints
in the bar array are "layout compatible" with the ints in the
unnamed struct,

What makes you assume that? It may be true in a given
implementation, but I'd like to see where the standard
guarantees it before I'd count on it. As far as I know, an
implementation is free to insert padding between elements in a
struct if it so desires; it is not allowed to do so in an array.

Quote:
the program is free to store int values in the union through
bar, and then retrieve those values via the unnamed struct (or
to do so the other way around).

I'd like to see some justification from the standard for this.
I don't believe it is true. It certainly wasn't for C: even
given
union { int a; int b; } ;
if you assign to a, then read b, it's undefined behavior.
(Admittedly, there are so many programs which do this sort of
thing that I can't imagine any compiler really not making it
work.)

--
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
Yuri Khan
Guest





PostPosted: Thu Oct 13, 2005 1:40 pm    Post subject: Re: Pointer to member array slot? Reply with quote

Greg Herlihy wrote:
Quote:
So perhaps a compromise is possible:

struct Foo
{
union
{
int bar[5];
struct
{
int firstInt;
int secondInt;
int thirdInt;
int fourthInt;
int fifthInt;
};
};
};

With this declaration clients have the convenience provided by an array
of ints while also benefitting from the precise addressability of
having individually-declared data members. Note also that the usual
restriction about accessing stored values in a union does not apply
here. a union generally requires that a value be retrieved by the same
means that was used to store that value. But because the ints in the
bar array are "layout compatible" with the ints in the unnamed struct,
the program is free to store int values in the union through bar, and
then retrieve those values via the unnamed struct (or to do so the
other way around).

If a union contains two or more structs that have a common initial
sequence, it is permitted to use the members of the common initial
sequence through either (any) of the structs. But in your case there is
one struct and one array, and a struct can only be layout-compatible
with another struct.

But even if you were to wrap int bar[5] in a struct, it would not be
layout-compatible with a struct of five ints, as (9.2/14) "Two
POD-struct (clause 9) types are layout-compatible if they have the same
number of nonstatic data members, and corresponding nonstatic data
members (in order) have layout-compatible types (3.9)".


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


Back to top
johnchx2@yahoo.com
Guest





PostPosted: Thu Oct 13, 2005 11:05 pm    Post subject: Re: Pointer to member array slot? Reply with quote

kanze wrote:

Quote:
What he wants is a simple pointer to member int. The fact that
the int happens to be an element of an array really doesn't
change anything. In this case, I suspect that the absense of
the feature is just an oversight; I can't see any additional
complications which it introduces.

I suspect that this may have been "overlooked" because it conflates
membership with recursive containment. Foo has no member of type int,
so it makes no sense (within the C++ type system) to form a
pointer-to-member-of-Foo-of-type-int.

For POD types, of course, it makes little difference whether Foo has a
member of type int or a member with a member or element of type int.
But for non-PODs, where there was an effort to give implementations the
leeway to employ unexpected and strange layout strategies, it could
make a big difference. Requiring a member-of-a-member to be "just
like" a member would seem to impose some sort of constraints on the
implementation's layout.


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


Back to top
Falk Tannhäuser
Guest





PostPosted: Thu Oct 13, 2005 11:06 pm    Post subject: Re: Pointer to member array slot? Reply with quote

Valentin Samko wrote:
Quote:
Think of
struct { int bar0; /* 4 bytes added by the compiler */ int bar 1; /* 4
bytes added by the compiler */ ... }

Also, I do not think the standard guarantees that there will be no
padding in front of bar0.

It does, see § 9.2/17:
"A pointer to a POD-struct object, suitably converted using a
reinterpret_cast, points to its initial member (or if that
member is a bit-field, then to the unit in which it resides)
and vice versa. [Note: There might therefore be unnamed padding
within a POD-struct object, but not at its beginning, as
necessary to achieve appropriate alignment.]"

Falk

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


Back to top
Allan W
Guest





PostPosted: Fri Oct 14, 2005 10:50 am    Post subject: Re: Pointer to member array slot? Reply with quote

Quote:
Allan W wrote:
struct Foo {
union {
struct { int bar0,bar1,bar2,bar3,bar4; }; // 5 ints
int bar[5]; // array of 5 ints
};
int baz;
};

Foo::bar0 points to Foo's bar[0], Foo::bar1 points Foo's bar[1],
and so on...

int Foo::*intptr1 = &Foo::bar0; // Points to Foo::bar[0]
int Foo::*intptr2 = &Foo::bar3; // Points to Foo::bar[3]
int Foo::*intptr3 = &Foo::baz; // Points to Foo::baz

Valentin Samko wrote:
Quote:
This will result in serious bugs if compiler aligns members of your
anonymous struct, adding paddings between them.

Think of
struct {
int bar0;
/* 4 bytes added by the compiler */
int bar1;
/* 4 bytes added by the compiler */
...
};

Also, I do not think the standard guarantees that there will be no
padding in front of bar0.

Without looking it up, I'll assume that you're right from the point
of view of the standard. And I'll even agree that it's important --
you should always be aware if you're violating the standard, and
look for viable alternatives.

But I think that this is one of those things that's portable-in-fact:
although the standard doesn't permit it, and there might even be
some real platform/compiler where it doesn't work, I think it's
very likely to be portable on the VAST majority of real platforms.

#include <cassert>

struct arr5 {
int bar[5];
};
struct scalar5 {
int bar0, bar1, bar2, bar3, bar4;
};

union {
struct { int bar0,bar1,bar2,bar3,bar4; };
int bar[5];
} x;

int main() {
assert(sizeof(arr5) == sizeof(scalar5));
assert(&x.bar0 == &x.bar[0]);
assert(&x.bar1 == &x.bar[1]);
assert(&x.bar2 == &x.bar[2]);
assert(&x.bar3 == &x.bar[3]);
assert(&x.bar4 == &x.bar[4]);
}

Anybody know of a platform where the assert fires?


[ 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, 3  Next
Page 1 of 3

 
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.