On Tue, Jun 13, 2023 at 7:10 AM Adrian Hall via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Hello all.

Proposal:
     Allow casting of Class::*member.submember to Class::*member.

Toy example:

Rewritten to use names that are clearly members or types:
    struct A { int x_, y_, z_; };
    struct B { A a_; };
    struct C { B b_; };
    B C::*pb = &C::b_;  // OK
    int C::*px = &C::b_::a_::x_;  // Proposed
    int C::*py = &C::b_.a_.y_;  // Maybe better syntax?
    int C::*pz = (&C::b_).a_.z_;  // Maybe even better syntax?

It's easy to see that the biggest problem here is with the syntax. Normally when we have ID::, we know that ID is something with members — a namespace or a class type (or in C++11-and-later a strong enum type).  You're proposing that we should also allow a (member) variable name in that position. This is `px` above.
Alternatively, we could say that it should be OK to apply the dot operator to an expression of pointer-to-member type, to yield another pointer-to-member. This is `pz` above.

`pz` is probably the best option, syntax-wise, because it naturally permits us to do things like
    B C::*pb = &C::b_;
    int A::*px = &A::x_;
    int C::*result = pb.a_.*px;  // member pointer to some C's `b_.a_.x_` subobject

The big implementation problem you're going to have to deal with is virtual bases. Today, it is invalid (a hard compiler error) to write this:
    struct A { int x_, y_, z_; };
    struct V : virtual A { };
    int V::*px = &V::x_;
You'll have to come up with Standard wording that correctly rules out any new problems along those lines.

Would it be hard to do?
     As far as I am aware there is nothing in the rules of C++
compilation that would disallow this, since the offset of the submember
Transform.position.x is known within Potato.

This is true except for virtual bases (and subobjects thereof).

Finally, you should think about the two other kinds of subobjects:
    struct W { };
    struct X : W { W w_; W a_[2]; };
    W X::*member_subobject = &X::w_;
    W X::*array_element_subobject = &X::a_[1];  // Seems like we can just support `operator[]` here exactly the same as `.`; is that right?
    W X::*base_subobject = &X::???;  // Seems like we still lack syntax for this; is that right?
Or is the `base_subobject` case a bad idea because normally the result of dereferencing a member pointer is a complete object (in the sense of its static type is the same as its dynamic type)?  Is that true?  This deserves investigation.

struct A { };
struct B : A { };
struct C { B b_; };
B C::*mb = &C::b_;
A C::*ma = mb; // Why is this disallowed? Should it be?

I think this is a good idea, but there's a lot of work to be done first, that all needs to go into the paper.

Cheers,
Arthur