16 Overloading [over]

16.4 Address of overloaded function [over.over]

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.
A function template name is considered to name a set of overloaded functions in such contexts.
A function with type F is selected for the function type FT of the target type required in the context if F (after possibly applying the function pointer conversion) is identical to FT.
[Note
:
That is, the class of which the function is a member is ignored when matching a pointer-to-member-function type.
end note
]
The target can be
The overloaded function name can be preceded by the & operator.
An overloaded function name shall not be used without arguments in contexts other than those listed.
[Note
:
Any redundant set of parentheses surrounding the overloaded function name is ignored ([expr.prim]).
end note
]
If the name is a function template, template argument deduction is done ([temp.deduct.funcaddr]), and if the argument deduction succeeds, the resulting template argument list is used to generate a single function template specialization, which is added to the set of overloaded functions considered.
[Note
:
As described in [temp.arg.explicit], if deduction fails and the function template name is followed by an explicit template argument list, the template-id is then examined to see whether it identifies a single function template specialization.
If it does, the template-id is considered to be an lvalue for that function template specialization.
The target type is not used in that determination.
end note
]
Non-member functions and static member functions match targets of function pointer type or reference to function type.
Non-static member functions match targets of pointer to member function type.
If a non-static member function is selected, the reference to the overloaded function name is required to have the form of a pointer to member as described in [expr.unary.op].
All functions with associated constraints that are not satisfied ([temp.constr.decl]) are eliminated from the set of selected functions.
If more than one function in the set remains, all function template specializations in the set are eliminated if the set also contains a function that is not a function template specialization.
Any given non-template function F0 is eliminated if the set contains a second non-template function that is more constrained than F0 according to the partial ordering rules of [temp.constr.order].
Any given function template specialization F1 is eliminated if the set contains a second function template specialization whose function template is more specialized than the function template of F1 according to the partial ordering rules of [temp.func.order].
After such eliminations, if any, there shall remain exactly one selected function.
[Example
:
int f(double);
int f(int);
int (*pfd)(double) = &f;        // selects f(double)
int (*pfi)(int) = &f;           // selects f(int)
int (*pfe)(...) = &f;           // error: type mismatch
int (&rfi)(int) = f;            // selects f(int)
int (&rfd)(double) = f;         // selects f(double)
void g() {
  (int (*)(int))&f;             // cast expression as selector
}
The initialization of pfe is ill-formed because no f() with type int(...) has been declared, and not because of any ambiguity.
For another example,
struct X {
  int f(int);
  static int f(long);
};

int (X::*p1)(int)  = &X::f;     // OK
int    (*p2)(int)  = &X::f;     // error: mismatch
int    (*p3)(long) = &X::f;     // OK
int (X::*p4)(long) = &X::f;     // error: mismatch
int (X::*p5)(int)  = &(X::f);   // error: wrong syntax for
                                // pointer to member
int    (*p6)(long) = &(X::f);   // OK
end example
]
[Note
:
If f() and g() are both overloaded functions, the cross product of possibilities must be considered to resolve f(&g), or the equivalent expression f(g).
end note
]
[Note
:
Even if B is a public base of D, we have
D* f();
B* (*p1)() = &f;                // error

void g(D*);
void (*p2)(B*) = &g;            // error
end note
]