benoitj benoitj - 26 days ago 14
C++ Question

Is Pointer-to- " inner struct" member forbidden?

i have a nested struct and i'd like to have a pointer-to-member to one of the nested member:

is it legal?

struct InnerStruct
{
bool c;
};
struct MyStruct {
bool t;
bool b;
InnerStruct inner;
};


this:

MyStruct mystruct;
//...
bool MyStruct::* toto = &MyStruct::b;


is ok but:

bool MyStruct::* toto = &MyStruct::inner.c;


is not. any idea?

thanks

Here are some details
Yes it is &MyStruct::b and not mystruct::b;
The code is from a custom RTTI/Property system.
For each specified class we keep an array of "Property", including a Ptr-to-member
It is used like this:

//somewhere else in code...
( myBaseClassWithCustomRTTIPointer)->* toto = true;

AnT AnT
Answer

Yes, it is forbidden. You are not the first to come up with this perfectly logical idea. In my opinion this is one of the obvious "bugs"/"omissions" in the specification of pointers-to-members in C++, but apparently the committee has no interest in developing the specification of pointers-to-members any further (as is the case with most of the "low-level" language features).

Note that everything necessary to implement the feature in already there, in the language. A pointer to a-data-member-of-a-member is in no way different from a pointer to an immediate data member. The only thing that's missing is the syntax to initialize such a pointer. However, the committee is apparently not interested in introducing such a syntax.

From the pure formal logic point of view, this should have been allowed in C++

struct Inner {
  int i;
  int j[10];
};

struct Outer {
  int i;
  int j[10];
  Inner inner;
};

Outer o;
int Outer::*p;

p = &Outer::i; // OK
o.*p = 0; // sets `o.i` to 0

p = &Outer::inner.i; // ERROR, but should have been supported
o.*p = 0; // sets `o.inner.i` to 0

p = &Outer::j[0]; // ERROR, but should have been supported
o.*p = 0; // sets `o.j[0]` to 0
// This could have been used to implement something akin to "array type decay" 
// for member pointers

p = &Outer::j[3]; // ERROR, but should have been supported
o.*p = 0; // sets `o.j[3]` to 0

p = &Outer::inner.j[5]; // ERROR, but should have been supported
o.*p = 0; // sets `o.inner.j[5]` to 0

A typical implementation of pointer-to-data-member is nothing more than just an byte-offset of the member from the beginning of the enclosing object. Since all members (immediate and members of members) are ultimately laid out sequentially in memory, members of members can also be identified by a specific offset value. This is what I mean when I say that the inner workings of this feature are already fully implemented, all that is needed is the initialization syntax.

In C language this functionality is emulated by explicit offsets obtained through the standard offsetof macro. And in C I can obtain offsetof(Outer, inner.i) and offsetof(Outer, j[2]). Unfortunately, this capability is not reflected in C++ pointers-to-data-members.

Comments