The question is inspired by a note in the standard [class.mem]
The type of a non-static member function is an ordinary function type, and the type of
The standard explicitly states that you can't do this.
[expr.prim.id]
2 An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
(2.1) as part of a class member access in which the object expression refers to the member's class58 or a class derived from that class, or
(2.2) to form a pointer to member ([expr.unary.op]), or
(2.3) if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
[ Example:
struct S { int m; }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK
— end example ]
Note my emphasis on can only be used: Those are the only ways that you can use an expression denoting a member function. Any other way you can come up with is ill-formed.
Note that 2.3 is exactly what you want to to - to use S::m
(m
being a member function) in an unevaluated context (i.e.: decltype
), but it specifically (and I would assume deliberately) only applies to data members.
I can think of at least one implication of allowing this (See below). There's probably more.
m
is declared as void m();
and it is a member of class S
. If decltype(S::m)
is valid, then std::add_pointer<decltype(S::m)>
should also be valid.this
parameter,
what would this second type be? void (S::*)()
, or maybe something
like void (*)(S*)
? Or even void (*)()
? It may be obvious to us that we want void (S::*)()
, but knowing that S::m
is just a regular function type, why would add_pointer
turn it into a pointer-to-member? How could it even differentiate it?