I'm not sure to perfectly understand [dcl.type]/4.3
:
For an expression
e
, the type denoted bydecltype(e)
is defined as follows:
- [...]
- (4.3) otherwise, if
e
is an unparenthesized id-expression or an unparenthesized class member access,decltype(e)
is the type of the entity named bye
. If there is no such entity, or ife
names a set of overloaded functions, the program is ill-formed;- [...]
For me, the emphasized part both apply to id-expression and class member access, right?
Playing with my favorite compiler, I get the following.
namespace N { void f() {} }
using type = decltype(N::f);
type* pf = N::f;
Ok I guess; N::f
is an unparenthesized id-expression and does not name a set of overloaded functions.
namespace N { void f() {} void f(int) {} }
using type = decltype(N::f); // error: decltype cannot resolve address of overloaded function
type* pf = N::f;
Ok; N::f
does name a set of overloaded functions.
struct S { void f(){} };
using type = decltype(S::f); // error: invalid use of non-static member function 'void S::f()'
type* pf = &S::f;
Hum? S::f
would name a set of one overloaded function?
All in all, is my understanding of [dcl.type]/4.3
just bad? is gcc trunk wrong? both? none? kamoulox?
decltype is a compile time evaluation (like sizeof ), and so can only use the static type.
A non-static member function is a function that is declared in a member specification of a class without a static or friend specifier. ( see static member functions and friend declaration for the effect of those keywords)
What happens if non static members are used in static member function? Explanation: There must be specific memory space allocated for the data members before the static member functions uses them. But the space is not reserved if object is not declared.
Static member function: it can only access static member data, or other static member functions while non-static member functions can access all data members of the class: static and non-static.
The simple reason is that the use of S::f
is constrained for class members.
[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:
- as part of a class member access in which the object expression refers to the member's class or a class derived from that class, or
- to form a pointer to member ([expr.unary.op]), or
- if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
The last bullet, the one related to your code, only applies to non-static data member. There is no provision for functions.
I can only speculate as to why it's not allowed, though I previously asked that question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With