This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 113c. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-02-24


170. Pointer-to-member conversions

Section: 7.3.13  [conv.mem]     Status: DRWP     Submitter: Mike Stump     Date: 16 Sep 1999

[Accepted as a DR at the June, 2023 meeting.]

The descriptions of explicit (7.6.1.9 [expr.static.cast] paragraph 9) and implicit (7.3.13 [conv.mem] paragraph 2) pointer-to-member conversions differ in two significant ways:

  1. In a static_cast, a conversion in which the class in the target pointer-to-member type is a base of the class in which the member is declared is permitted and required to work correctly, as long as the resulting pointer-to-member is eventually dereferenced with an object whose dynamic type contains the member. That is, the class of the target pointer-to-member type is not required to contain the member referred to by the value being converted. The specification of implicit pointer-to-member conversion is silent on this question.

    (This situation cannot arise in an implicit pointer-to-member conversion where the source value is something like &X::f, since you can only implicitly convert from pointer-to-base-member to pointer-to-derived-member. However, if the source value is the result of an explicit "up-cast," the target type of the conversion might still not contain the member referred to by the source value.)

  2. The target type in a static_cast is allowed to be more cv-qualified than the source type; in an implicit conversion, however, the cv-qualifications of the two types are required to be identical.

The first difference seems like an oversight. It is not clear whether the latter difference is intentional or not.

(See also issue 794.)

CWG 2022-11-09

The second concern is NAD; implicit conversions allow chaining a pointer-to-member conversion with a qualification conversion.

Proposed resolution (approved by CWG 2023-02-06):

  1. Change in 7.3.13 [conv.mem] paragraph 2 as follows:

    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 (11.7 [class.derived]) from B. If B is an inaccessible (11.8 [class.access]), ambiguous (6.5.2 [class.member.lookup]), or virtual (11.7.2 [class.mi]) base class of D, or a base class of a virtual base class of D, a program that necessitates this conversion is ill-formed. If class D does not contain the original member and is not a base class of the class containing the original member, the behavior is undefined. Otherwise, The 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. 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 B with the B subobject of D. The null member pointer value is converted to the null member pointer value of the destination type. [ Footnote: ... ]
  2. Change in 7.6.1.9 [expr.static.cast] paragraph 13 as follows:

    ... If class B contains the original member, or is a base or derived class of the class containing the original member, the resulting pointer to member points to the original member. ...