struct X
{
void f(double) {}
static void f(int) {}
};
int main()
{
X x;
auto y = x.f;
}
gcc gives:
error: unable to deduce ‘auto’ from ‘x.X::f’
x.f is a class member access postfix-expression documented in 5.2.5 [expr.ref]
It effectively says:
If
fis a (possibly overloaded) member function, function overload resolution (13.3) is used to deter- mine whetherx.frefers to a static or a non-static member function. (from N3485 5.2.5.4.3 )
How can overload resolution be applied here - x.f doesn't have a parameter list with which to do overload resolution?
Or am I missing something?
Update: If I change the auto y = x.f line to an expression-statement:
- auto y = x.f;
+ x.f;
then gcc instead complains:
error: statement cannot resolve address of overloaded function
I think you're right in that the Standard isn't precise at this point:
[expr.ref]/4
If f is a (possibly overloaded) member function, function overload resolution (13.3) is used to determine whether
x.frefers to a static or a non-static member function.
As the first sub-bullet states:
If it refers to a static member function and the type of E2 is “function of parameter-type-list returning T”, then E1.E2 is an lvalue; the expression designates the static member function. The type of E1.E2 is the same type as that of E2, namely “function of parameter-type-list returning T”.
That is, x.f can be used to initialize a function ptr if f is static, whereas (see following sub-bullet) if f is not static, it can only be used in a function-call expression.
But actually, overload resolution is not performed to select an overload from the name of an overloaded function outside the context of a function-call-expression:
[over.over]/1
A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set. [...] The function selected is the one whose type is identical to the function type of the target type required in the context.
That is, an exact match, not invoking the overload resolution mechanism described in [over.match]. Therefore [expr.ref]/4 is incomplete, is doesn't describe your case of using x.f to initialize a function pointer/reference.
As the auto keyword doesn't specify a target type (or according to [dcl.spec.auto]/6, the mechanism to deduce the type for auto fails), you cannot use auto y = x.f;:
x.f refers to a set of overloaded functionsauto failsThe type of x.f therefore is
Even if there's only one x.f valid in this context, the compiler must do the overload resolution before determining if the function is static or not.
§5.2.5 « If E2 is a (possibly overloaded) member function, function overload resolution (13.3) is used to determine whether E1.E2 refers to a static or a non-static member function. »
The overload resolution mechanism (as described in §13.3 and §13.4) need a valid context to select the correct candidate :
§13.4.1 « A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set »
auto y = x.f; is not a valid resolution context, you either have to drop the auto keyword or to use a static_cast to force the overload resolution :
X x;
auto y = static_cast<void (&)(int)>(x.f);
y(1);
auto z = static_cast<void (X::*)(double)>(&X::f);
(x.*z)(1.);
Note that you can't have a reference to a non-static member, only a pointer, as per § 8.3.3 :
There is no “reference-to-member” type in C++
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