Address of an overloaded function (original) (raw)

Besides function-call expressions, where overload resolution takes place, the name of an overloaded function may appear in the following 7 contexts:

# Context Target
1 initializer in a declaration of an object or reference the object or reference being initialized
2 on the right-hand-side of an built-in assignment expression the left-hand side of the built-in assignment
3 as a function call argument the function parameter
4 as a user-defined operator argument the operator parameter
5 the return statement the return value of a function or conversion
6 explicit cast or static_cast argument the corresponding cast
7 constant template argument the corresponding template parameter

In each context, the name of an overloaded function may be preceded by address-of operator **&** and may be enclosed in a redundant set of parentheses.

If the target type contains a placeholder type, placeholder type deduction is performed, and the following description uses the deduced type as target type. (since C++26)

Contents

[edit] Selecting functions

When the address of an overloaded function is taken, a set S of functions is selected from the overload set referred to by the name of the overload function:

If the target is of function pointer type or reference to function type, S can only include non-member functions, explicit object member functions(since C++23) and static member functions. If the target is of pointer-to-member-function type, S can only include implicit object member functions.

  1. In other words, the class of which the function is a member is ignored if the target type is a pointer-to-member-function type.

[edit] Eliminating functions

After forming the set S, functions are elimiated in the following order:

All functions with associated constraints that are not satisfied are eliminated from the S. (since C++20)
Any given non-template function func is eliminated if S contains a second non-template function that is more partial-ordering-constrained than func. (since C++20)

After such eliminations (if any), exactly one selected function should remain in S. Otherwise, the program is ill-formed.

[edit] Example

int f(int) { return 1; } int f(double) { return 2; }   void g(int(&f1)(int), int(f2)(double)) { f1(0); f2(0.0); }   template<int(*F)(int)> struct Templ {};   struct Foo { int mf(int) { return 3; } int mf(double) { return 4; } };   struct Emp { void operator<<(int (*)(double)) {} };   int main() { // 1. initialization int (*pf)(double) = f; // selects int f(double) int (&rf)(int) = f; // selects int f(int) int (Foo::*mpf)(int) = &Foo::mf; // selects int mf(int)   // 2. assignment pf = nullptr; pf = &f; // selects int f(double)   // 3. function argument g(f, f); // selects int f(int) for the 1st argument // and int f(double) for the second   // 4. user-defined operator Emp{} << f; //selects int f(double)   // 5. return value auto foo = -> int ()(int) { return f; // selects int f(int) };   // 6. cast auto p = static_cast<int(*)(int)>(f); // selects int f(int)   // 7. template argument Templ t; // selects int f(int)   // prevent “unused variable” warnings as if by [[maybe_unused]] {}(pf, rf, mpf, foo, p, t); }

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
CWG 202 C++98 constant template argument was not a contextof taking the address of an overloaded function it is
CWG 250 C++98 function template specializations generated with non-deducedtemplate arguments were not selected from the overload set also selected
CWG 1153 C++98 it was unclear whether a given function type matches the target type made clear
CWG 1563 C++11 it was unclear whether list-initialization is a contextof taking the address of an overloaded function made clear

[edit] References