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

Viewed 5881

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;
3 Answers

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.

The InnerStruct you care about happens to be contained in an instance of a MyStruct, but that doesn't affect how you get a pointer to the member of the InnerStruct.

bool InnerStruct::* toto2 = &InnerStruct::c;

Edit: Rereading your question, I'm guessing you want to define a pointer to member of the outer struct, and have it point directly at a member of the inner struct. That's simply not allowed. To get to the member of the inner struct that's contained in the outer struct, you'd have to create a pointer to the inner struct itselft, then to its member. To use it, you'd dereference both pointers to members:

// Pointer to inner member of MyStruct:
InnerStruct MyStruct::* toto = &MyStruct::inner;

// Pointer to c member of InnerStruct:
bool InnerStruct::* toto2 = &InnerStruct::c;

// Dereference both to get to the actual bool:
bool x = mystruct.*toto.*toto2;
Related