[over.match.best.general] (original) (raw)
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 abetterfunction 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 #1Fn&& rf = a; // calls #2 — _end example_]
or, if not that, - is not a function template specialization andis a function template specialization, or, if not that,
- andare function template specializations, and the function template foris more specialized than the template foraccording to the partial ordering rules described in [temp.func.order], or, if not that,
- and are non-template functions and is more partial-ordering-constrained than ([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 Dwhile 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 adeduction-guide ([over.match.class.deduct]) and is not, or, if not that,
- is the copy deduction candidateand 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 #5A a(42); // uses #6 to deduce A and #1 to initializeA b = a; // uses #5 to deduce A and #2 to initialize template <class T>A(A<T>) -> A<A<T>>; // #7, as specialized as #5A b2 = a; // uses #7 to deduce A<A> 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.105
[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_]