12 Overloading [over]

12.2 Overload resolution [over.match]

12.2.4 Best viable function [over.match.best]

12.2.4.1 General [over.match.best.general]

Define as the implicit conversion sequence that converts the argument in the list to the type of the parameter of viable function F.
[over.best.ics] defines the implicit conversion sequences and [over.ics.rank] defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.
Given these definitions, a viable function is defined to be a better function than another viable function if for all arguments i, is not a worse conversion sequence than , and then
  • for some argument j, is a better conversion sequence than , or, if not that,
  • the context is an initialization by user-defined conversion (see [dcl.init], [over.match.conv], and [over.match.ref]) and the standard conversion sequence from the result of to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence from the result of to the destination type
    [Example 1: struct A { A(); operator int(); operator double(); } a; int i = a; // a.operator int() followed by no conversion is better than // a.operator double() followed by a conversion to int float x = a; // ambiguous: both possibilities require conversions, // and neither is better than the other — end example]
    or, if not that,
  • the context is an initialization by conversion function for direct reference binding of a reference to function type, the return type of is the same kind of reference (lvalue or rvalue) as the reference being initialized, and the return type of is not
    [Example 2: template <class T> struct A { operator T&(); // #1 operator T&&(); // #2 }; typedef int Fn(); A<Fn> a; Fn& lf = a; // calls #1 Fn&& rf = a; // calls #2 — end example]
    or, if not that,
  • is not a function template specialization and is a function template specialization, or, if not that,
  • and are function template specializations, and the function template for is more specialized than the template for according to the partial ordering rules described in [temp.func.order], or, if not that,
  • and are non-template functions and
    • they have the same non-object-parameter-type-lists ([dcl.fct]), and
    • if they are member functions, both are direct members of the same class, and
    • if both are non-static member functions, they have the same types for their object parameters, and
    • is more constrained than according to the partial ordering of constraints described in [temp.constr.order]
    [Example 3: template <typename T = int> struct S { constexpr void f(); // #1 constexpr void f(this S&) requires true; // #2 }; void test() { S<> s; s.f(); // calls #2 } — end example]
    or, if not that,
  • is a constructor for a class D, is a constructor for a base class B of D, and for all arguments the corresponding parameters of and have the same type
    [Example 4: struct A { A(int = 0); }; struct B: A { using A::A; B(); }; int main() { B b; // OK, B​::​B() } — end example]
    or, if not that,
  • is a rewritten candidate ([over.match.oper]) and is not
    [Example 5: struct S { friend auto operator<=>(const S&, const S&) = default; // #1 friend bool operator<(const S&, const S&); // #2 }; bool b = S() < S(); // calls #2 — end example]
    or, if not that,
  • and are rewritten candidates, and is a synthesized candidate with reversed order of parameters and is not
    [Example 6: struct S { friend std::weak_ordering operator<=>(const S&, int); // #1 friend std::weak_ordering operator<=>(int, const S&); // #2 }; bool b = 1 < S(); // calls #2 — end example]
    or, if not that,
  • and are generated from class template argument deduction ([over.match.class.deduct]) for a class D, and is generated from inheriting constructors from a base class of D while is not, and for each explicit function argument, the corresponding parameters of and are either both ellipses or have the same type, or, if not that,
  • is generated from a deduction-guide ([over.match.class.deduct]) and is not, or, if not that,
  • is the copy deduction candidate and is not, or, if not that,
  • is generated from a non-template constructor and is generated from a constructor template.
    [Example 7: template <class T> struct A { using value_type = T; A(value_type); // #1 A(const A&); // #2 A(T, T, int); // #3 template<class U> A(int, T, U); // #4 // #5 is the copy deduction candidate, A(A) }; A x(1, 2, 3); // uses #3, generated from a non-template constructor template <class T> A(T) -> A<T>; // #6, less specialized than #5 A a(42); // uses #6 to deduce A<int> and #1 to initialize A b = a; // uses #5 to deduce A<int> and #2 to initialize template <class T> A(A<T>) -> A<A<T>>; // #7, as specialized as #5 A b2 = a; // uses #7 to deduce A<A<int>> and #1 to initialize — end example]
If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution; otherwise the call is ill-formed.107
[Example 8: void Fcn(const int*, short); void Fcn(int*, int); int i; short s = 0; void f() { Fcn(&i, s); // is ambiguous because &i int* is better than &i const int* // but s short is also better than s int Fcn(&i, 1L); // calls Fcn(int*, int), because &i int* is better than &i const int* // and 1L short and 1L int are indistinguishable Fcn(&i, 'c'); // calls Fcn(int*, int), because &i int* is better than &i const int* // and 'c' int is better than 'c' short } — end example]
If the best viable function resolves to a function for which multiple declarations were found, and if any two of these declarations inhabit different scopes and specify a default argument that made the function viable, the program is ill-formed.
[Example 9: namespace A { extern "C" void f(int = 5); } namespace B { extern "C" void f(int = 5); } using A::f; using B::f; void use() { f(3); // OK, default argument was not used for viability f(); // error: found default argument twice } — end example]
107)107)
The algorithm for selecting the best viable function is linear in the number of viable functions.
Run a simple tournament to find a function W that is not worse than any opponent it faced.
Although it is possible that another function F that W did not face is at least as good as W, F cannot be the best function because at some point in the tournament F encountered another function G such that F was not better than G.
Hence, either W is the best function or there is no best function.
So, make a second pass over the viable functions to verify that W is better than all other functions.