Skip to content

CWG3026 [expr.unary.op] Wording is ambiguous: Pointer to member of which class? #705

Description

@hubert-reinterpretcast

Full name of submitter (unless configured in github; will be published with the issue): Hubert Tong

Reference (section label): expr.unary.op

Link to reflector thread (if any): N/A

Issue description:
There should be little controversy that the following should compile, but the wording is unclear: https://godbolt.org/z/aYo86aEer

struct A {
  union { int x; };
  int y;
};
struct B : A {};

template <typename> struct Q;
template <> struct Q<A> {};
template <typename T> Q<T> f(int T::*);

Q<A> g() { return f(&B::x); }
Q<A> h() { return f(&B::y); }

https://wg21.link/expr.unary.op under bullet 3.1 has:

If the operand is a qualified-id naming a non-static or variant member m of some class C, other than an explicit object member function, the result has type “pointer to member of class C of type T” and designates C​::​m.

In the above:

  • x is a variant member both of the anonymous union and of A, and
  • y is a non-static member of both A and of B.

It seems C in the wording is not quite unique.

Suggested resolution:

If the operand is a qualified-id naming a non-static or variant class member m of some class C, other than an explicit object member function, then let C be

  • the class of which m is a direct member if m is not a variant member, and otherwise
  • the class, that is not an anonymous union, of which m is a variant member.

The the result has type “pointer to member of class C of type T” and designates C​::​m. [Note: A qualified-id that names a member of a namespace-scope anonymous union is considered to be a class member access expression ([expr.prim.id.general]) and cannot be used to form a pointer to member.]

Activity

  1. changed the title [-][section.label] Proposed issue title[/-] [+][expr.unary.op] Wording is ambiguous: Pointer to member of which class?[/+] on May 11, 2025
  2. jensmaurer commented on May 11, 2025

    @jensmaurer
    Member
  3. changed the title [-][expr.unary.op] Wording is ambiguous: Pointer to member of which class?[/-] [+]CWG3026 [expr.unary.op] Wording is ambiguous: Pointer to member of which class?[/+] on May 11, 2025
  4. hubert-reinterpretcast commented on May 11, 2025

    @hubert-reinterpretcast
    MemberAuthor

    @jensmaurer, the binding of "m" to mean the class member disappeared in the CWG3026 version of the resolution.

  5. jensmaurer commented on May 11, 2025

    @jensmaurer
    Member

    Thanks, fixed.

  6. hubert-reinterpretcast commented on May 11, 2025

    @hubert-reinterpretcast
    MemberAuthor

    Because direct members of anonymous unions are also direct members of their enclosing class (if any) (https://wg21.link/class.mem.general#3),

    • the class of which m is a direct member if m is not a variant member, and otherwise
    • the class, that is not an anonymous union, of which m is a variant member.

    can be simplified to

    the class, that is not an anonymous union, of which m is a direct member.

  7. jensmaurer commented on May 12, 2025

    @jensmaurer
    Member

    Yeah. I've fixed that. Can we retain a little more of the less awkward incoming phrasing by saying

    If the operand is a qualified-id naming a non-static direct member m of some class C, where C is not an anonymous union, ... (old text)...

  8. hubert-reinterpretcast commented on May 13, 2025

    @hubert-reinterpretcast
    MemberAuthor

    Yeah. I've fixed that.

    I think we can remove the comma before "other than an explicit object member function".

    Can we retain a little more of the less awkward incoming phrasing by saying

    If the operand is a qualified-id naming a non-static direct member m of some class C, where C is not an anonymous union, ... (old text)...

    My attempt:

    If the operand is a qualified-id naming a non-static direct member m, other than an explicit object member function, of some class C, ignoring anonymous union classes, the result has type “pointer to member of class C of type T” and designates C​::​m.

    The implicit undefined behaviour I mentioned on the reflector re: P2996 (Reflection) will then instead manifest in the next bullet.

  9. jensmaurer commented on Aug 9, 2026

    @jensmaurer
    Member

    Resolved by paper P2996R13.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions