C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Pointer to member of member

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Tue, 13 Jun 2023 10:46:08 -0400
On Tue, Jun 13, 2023 at 7:10 AM Adrian Hall via Std-Proposals <
std-proposals_at_[hidden]> 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

Received on 2023-06-13 14:46:21