Overload resolution
In order to compile a function call, the compiler must first perform name lookup, which, for functions, may involve argument-dependent lookup, and for function templates may be followed by template argument deduction. If these steps produce more than one candidate function, then overload resolution is performed to select the function that will actually be called.
In general, the candidate function whose parameters match the arguments most closely is the one that is called.
Contents |
[edit] Details
Before overload resolution begins, the functions selected by name lookup and template argument deduction are combined to form the set of candidate functions (the exact criteria depend on the context in which overload resolution takes place, see below).
If any candidate function is a member function (static or non-static), but not a constructor, it is treated as if it has an extra parameter (implicit object parameter) which represents the object for which they are called and appears before the first of the actual parameters.
Similarly, the object on which a member function is being called, is prepended to the argument list as the implied object argument
For member functions of class X
, the type of the implicit object parameter is affected by cv-qualifications and ref-qualifications of the member function as described in member_functions
The user-defined conversion functions are considered to be members of the implied object argument for the purpose of determining the type of the implicit object parameter.
The member functions introduced by a using-declaration into a derived class are considered to be members of the derived class for the purpose of defining the type of the implicit object parameter.
For the static member functions, the implicit object parameter is considered to match any object: its type is not examined and no conversion sequence is attempted for it.
For the rest of overload resolution, the implied object argument is indistinguishable from other arguments, but the following special rules apply to the implicit object parameter:
This section is incomplete Reason: small illustrative examples |
[edit] Candidate functions
[edit] Call to a named function
This section is incomplete |
[edit] Call to a class object
This section is incomplete |
[edit] Call to an overloaded operator
This section is incomplete |
[edit] Initialization by constructor
This section is incomplete |
[edit] Copy-initialization by conversion
This section is incomplete |
[edit] Non-class initialization by conversion
This section is incomplete |
[edit] Reference initialization by conversion
This section is incomplete |
[edit] List-initialization
This section is incomplete |
[edit] Viable functions
Given the set of candidate functions, constructed as described above, the next step of overload resolution is examining arguments and parameters to reduce the set to the set of viable functions
To be included in the set of viable functions, the candidate function must satisfy the following:
M
arguments, the candidate function that has exactly M
parameters is viableM
parameters, but has an ellipsis parameter (is a variadic function), it is viable.M
parameters and the M+1
'st parameter and all parameters that follow must have default arguments, it is viable. For the rest of overload resolution, the parameter list is truncated at M.[edit] Best viable function
For each pair of viable function F1
and F2
, the implicit conversion sequences from the i
-th parameter to i
-th argument are ranked to determine which one is better (except the first argument, the implicit object argument for static member functions has no effect on the ranking)
F1
is determined to be a better function than F2
if implicit conversions for all arguments of F1 are not worse than the implicit conversions for all arguments of F2, and
These pair-wise comparisons are applied to all viable functions. If exactly one viable function is better than all others, overload resolution succeeds and this function is called. Otherwise, compilation fails.
void Fcn(const int*, short); // overload #1 void Fcn(int*, int); // overload #2 int i; short s = 0; void f() { Fcn(&i, 1L); // 1st argument: &i -> int* is better than &i -> const int* // 2nd argument: 1L -> short and 1L -> int are equivalent // calls Fcn(int*, int) Fcn(&i,’c’); // 1st argument: &i -> int* is better than &i -> const int* // 2nd argument: 'c' -> int is better than 'c' -> short // calls Fcn(int*, int) Fcn(&i, s); // 1st argument: &i -> int* is better than &i -> const int* // 2nd argument: s -> short is better than s -> int // no winner, compilation error }
[edit] Ranking of implicit conversion sequences
The argument-parameter implicit conversion sequences considered by overload resolution correspond to implicit conversions used in copy initialization (for non-reference parameters), except that when considering conversion to the implicit object parameter or to the left-hand side of assignment operator, conversions that create temporary objects are not considered.
Each type of standard conversion sequence is assigned one of three ranks:
The rank of the standard conversion sequence is the worst of the ranks of the standard conversions it holds (there may be up to three conversions)
Binding of a reference parameter directly to the argument expression is either Identity or a derived-to-base Conversion:
struct Base {}; struct Derived : Base {} d; int f(Base&); // overload #1 int f(Derived&); // overload #2 int i = f(d); // d -> Derived& has rank Exact Match // d -> Base& has rank Conversion // calls f(Derived&)
Since ranking of conversion sequences operates with types and value categories only, a bit field can bind to a reference argument for the purpose of ranking, but if that function gets selected, it will be ill-formed.
S1
is better than a standard conversion sequence S2
ifS1
is a subsequence of S2
, excluding lvalue transformations. The identity conversion sequence is considered a subsequence of any other conversionS1
is better thank the rank of S2
S1
is a subset of the cv-qualification of the result of S2
int f(const int*); int f(int*); int i; int j = f(&i); // &i -> int* is better than &i -> const int*, calls f(int*)
S1
and S2
are binding to a reference parameter to something other than the implicit object parameter of a ref-qualified member function, and S1
binds an rvalue reference to an rvalue while S2
binds an rvalue reference to an rvalue
int i; int f1(); int g(const int&); // overload #1 int g(const int&&); // overload #2 int j = g(i); // lvalue int -> const int& is the only valid conversion int k = g(f1()); // rvalue int -> const int&& better than rvalue int -> const int&
S1
and S2
are binding to a reference parameter and S1
binds an lvalue reference to function while S2
binds an rvalue reference to function.S1
and S2
are binding to a reference parameters only different in top-level cv-qualification, and S1
's type is less cv-qualified than S2
's.
int f(const int &); // overload #1 int f(int &); // overload #2 (both references int g(const int &); // overload #1 int g(int); // overload #2 int i; int j = f(i); // lvalue i -> int& is better than lvalue int -> const int& // calls f(int&) int k = g(i); // lvalue i -> const int& ranks Exact Match // lvalue i -> rvalue int ranks Exact Match // ambiguous overload: compilation error
U1
is better than a user-defined conversion sequence U2
if they call the same constructor/user-defined conversion function and the second standard conversion sequence in U1
is better than the second standard conversion sequence in U2
struct A { operator short(); // user-defined conversion function } a; int f(int); // overload #1 int f(float); // overload #2 int i = f(a); // A -> short, followed by short -> int (rank Promotion) // A -> short, followed by short -> float (rank Conversion) // calls f(int)
L1
is better than list-initialization sequence L2
if L1
initializes an std::initializer_list parameter, while L2
does not.
std::vector<std::size_t> v{10, 20}; // calls vector<size_t>(initializer_list<size_t>) // not vector<size_t>(size_t, size_t)
If two conversion sequences are indistinguishable because they have the same rank, the following additional rules apply:
Mid
is derived (directly or indirectly) from Base
, and Derived
is derived (directly or indirectly) from Mid
Ambiguous conversion sequences are ranked as user-defined conversion sequences because multiple conversion sequences for an argument can exist only if they involve different user-defined conversions:
class B; class A { A (B&);}; // converting constructor class B { operator A (); }; // user-defined conversion function class C { C (B&); }; // converting constructor void f(A) { } // overload #1 void f(C) { } // overload #2 B b; f(b); // B -> A via ctor or B -> A via function (ambiguous conversion) // b -> C via ctor (user-defined conversion) // the conversions for overload #1 and for overload #2 // are indistinguishable; compilation fails