Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[conv.mem] p2 should specify the complete conversion path #5493

Open
xmh0511 opened this issue May 26, 2022 · 0 comments
Open

[conv.mem] p2 should specify the complete conversion path #5493

xmh0511 opened this issue May 26, 2022 · 0 comments

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented May 26, 2022

Consider the example in [expr.eq] p4.6

struct B {
  int f();
};
struct L : B { };
struct R : B { };
struct D : L, R { };

int (B::*pb)() = &B::f;
int (L::*pl)() = pb;
int (R::*pr)() = pb;
int (D::*pdl)() = pl;
int (D::*pdr)() = pr;
bool x = (pdl == pdr);   

The relevant rule says

Otherwise, two pointers to members compare equal if they would refer to the same member of the same most derived object or the same subobject if indirection with a hypothetical object of the associated class type were performed, otherwise they compare unequal.

We expect that the result of pdl can clearly be that refers to D's L's instance of B, and pdr refers to D's R's instance of B, hence they don't refer to the member of the same subobject and are not equivalent. The result of the conversion is completely expressed in [conv.mem] p2. However, [conv.mem] p2 cannot well express the result in the case that multi-converts the pointer to a member to pointer to the derived classes' member. The current wording is

The result of the conversion refers to the same member as the pointer to member before the conversion took place, but it refers to the base class member as if it were a member of the derived class. The result refers to the member in D's instance of B.

[conv.mem] p2 can well tell the story that pl refers to the member in L's instance of B. However, we expect [conv.mem] p2 can also well define that pdl refers to the member in D's L's instance of B, in this case, the rule is hard to read out this meaning. The suggestion to the current wording might be:

A prvalue of type “pointer to member of B of type cv T”, where B is a class type, can be converted to a prvalue of type “pointer to member of D of type cv T”, where D is a complete class derived ([class.derived]) from B. .... The result of the conversion refers to the hypothetical member MD of class D of type cv T; any reference to MD refers to the member of M(B) of D. For class B, M(B) is defined as follows.

  • If the pointed member of B is a hypothetical member that is invented for converting the prvalue of type “pointer to member of C of type cv T” to “pointer to member of B of type cv T”, M(C) of B.
  • otherwise, B; the declaring-base-class.

Since the result has type “pointer to member of D of type cv T”, indirection through it with a D object is valid. The result is the same as if indirecting through the pointer to member of U that is the declaring-base-class with the base class subobject M(B) of D. The null member pointer value is converted to the null member pointer value of the destination type.

After this suggestion, the result of pdl is clear to interpret. pdl refers to the hypothetical member of class D, and such a reference results in pdl referring to the M(L) of D, where M(L) is B of L. The result of pdl is the member of B of L of D, which completely tells conversions in the path.

Not a completely formal suggestion, just one thought that can clarify the result in the conversion path.

@xmh0511 xmh0511 changed the title [conv.mem] p2 should completely express the conversion chain [conv.mem] p2 should completely express the conversion path May 26, 2022
@xmh0511 xmh0511 changed the title [conv.mem] p2 should completely express the conversion path [conv.mem] p2 should specify the complete conversion path May 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant