Description
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 classC
, other than an explicit object member function, the result has type “pointer to member of classC
of typeT
” and designatesC::m
.
In the above:
x
is a variant member both of the anonymous union and ofA
, andy
is a non-static member of bothA
and ofB
.
It seems C
in the wording is not quite unique.
Suggested resolution:
If the operand is a qualified-id naming a non-static
or variantclass memberm
of some class, other than an explicit object member function, then letC
C
be
- the class of which
m
is a direct member ifm
is not a variant member, and otherwise- the class, that is not an anonymous union, of which
m
is a variant member.The
theresult has type “pointer to member of classC
of typeT
” and designatesC::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.]