Files
2025-10-25 03:02:53 +03:00

246 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[over.ics.rank]
# 12 Overloading [[over]](./#over)
## 12.2 Overload resolution [[over.match]](over.match#over.ics.rank)
### 12.2.4 Best viable function [[over.match.best]](over.match.best#over.ics.rank)
#### 12.2.4.3 Ranking implicit conversion sequences [over.ics.rank]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/overloading.tex#L2706)
This subclause defines a partial ordering of implicit conversion
sequences based on the relationships[*better conversion sequence*](#def:conversion_sequence,better "12.2.4.3Ranking implicit conversion sequences[over.ics.rank]") and[*better conversion*](#def:conversion,better "12.2.4.3Ranking implicit conversion sequences[over.ics.rank]")[.](#1.sentence-1)
If an implicit conversion sequence S1 is
defined by these rules to be a better conversion sequence than
S2, then it is also the case that S2 is a[*worse conversion sequence*](#def:conversion_sequence,worse "12.2.4.3Ranking implicit conversion sequences[over.ics.rank]") than S1[.](#1.sentence-2)
If conversion sequence S1 is neither better
than nor worse than conversion sequence S2, S1 and S2 are said to
be[*indistinguishable conversion sequences*](#def:conversion_sequence,indistinguishable "12.2.4.3Ranking implicit conversion sequences[over.ics.rank]")[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/overloading.tex#L2722)
When comparing the basic forms of implicit conversion sequences
(as defined in [[over.best.ics]](over.best.ics "12.2.4.2Implicit conversion sequences"))
- [(2.1)](#2.1)
a [standard conversion sequence](over.ics.scs "12.2.4.2.2Standard conversion sequences[over.ics.scs]") is a better
conversion sequence than a user-defined conversion sequence
or an ellipsis conversion sequence, and
- [(2.2)](#2.2)
a [user-defined conversion sequence](over.ics.user "12.2.4.2.3User-defined conversion sequences[over.ics.user]") is a
better conversion sequence than an [ellipsis conversion
sequence](over.ics.ellipsis "12.2.4.2.4Ellipsis conversion sequences[over.ics.ellipsis]")[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/overloading.tex#L2736)
Two implicit conversion sequences of the same form are
indistinguishable conversion sequences unless one of the
following rules applies:
- [(3.1)](#3.1)
List-initialization sequence L1 is a better conversion sequence than
list-initialization sequence L2 if
* [(3.1.1)](#3.1.1)
L1 converts to std::initializer_list<X> for some X andL2 does not, or, if not that,
* [(3.1.2)](#3.1.2)
L1 and L2 convert to arrays of the same element type, and
either the number of elements n1 initialized by L1 is less than the number of elements n2 initialized by L2, orn1=n2 andL2 converts to an array of unknown bound and L1 does not,
even if one of the other rules in this paragraph would otherwise apply[.](#3.1.sentence-1)
[*Example [1](#example-1)*: void f1(int); // #1void f1(std::initializer_list<long>); // #2void g1() { f1({42}); } // chooses #2void f2(std::pair<const char*, const char*>); // #3void f2(std::initializer_list<std::string>); // #4void g2() { f2({"foo","bar"}); } // chooses #4 — *end example*]
[*Example [2](#example-2)*: void f(int (&&)[] ); // #1void f(double (&&)[] ); // #2void f(int (&&)[2]); // #3 f( {1} ); // Calls #1: Better than #2 due to conversion, better than #3 due to bounds f( {1.0} ); // Calls #2: Identity conversion is better than floating-integral conversion f( {1.0, 2.0} ); // Calls #2: Identity conversion is better than floating-integral conversion f( {1, 2} ); // Calls #3: Converting to array of known bound is better than to unknown bound,// and an identity conversion is better than floating-integral conversion — *end example*]
- [(3.2)](#3.2)
Standard conversion sequenceS1 is a better conversion
sequence than standard conversion sequenceS2 if
* [(3.2.1)](#3.2.1)
S1 is a proper subsequence ofS2 (comparing the conversion sequences in the canonical form defined
by [[over.ics.scs]](over.ics.scs "12.2.4.2.2Standard conversion sequences"), excluding any Lvalue Transformation;
the identity conversion sequence is considered to be a
subsequence of any non-identity conversion sequence)
or, if not that,
* [(3.2.2)](#3.2.2)
the rank ofS1 is better than the rank ofS2,
orS1 andS2 have the same rank and are distinguishable by the rules
in the paragraph below,
or, if not that,
* [(3.2.3)](#3.2.3)
S1 and S2 include reference bindings ([[dcl.init.ref]](dcl.init.ref "9.5.4References")) and
neither refers to an implicit object parameter of a non-static member function
declared without a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]"),
and S1 binds an rvalue reference to an
rvalue and S2 binds an lvalue reference
[*Example [3](#example-3)*: int i;int f1();int&& f2();int g(const int&);int g(const int&&);int j = g(i); // calls g(const int&)int k = g(f1()); // calls g(const int&&)int l = g(f2()); // calls g(const int&&)struct A { A& operator<<(int); void p() &; void p() &&;};
A& operator<<(A&&, char);
A() << 1; // calls A::operator<<(int) A() << 'c'; // calls operator<<(A&&, char) A a;
a << 1; // calls A::operator<<(int) a << 'c'; // calls A::operator<<(int) A().p(); // calls A::p()&& a.p(); // calls A::p()& — *end example*]
or, if not that,
* [(3.2.4)](#3.2.4)
S1 and S2 include reference bindings ([[dcl.init.ref]](dcl.init.ref "9.5.4References")) andS1 binds an lvalue reference to an lvalue of function type andS2 binds an rvalue reference to an lvalue of function type
[*Example [4](#example-4)*: int f(void(&)()); // #1int f(void(&&)()); // #2void g();int i1 = f(g); // calls #1 — *end example*]
or, if not that,
* [(3.2.5)](#3.2.5)
S1 and S2 differ only
in their qualification conversion ([[conv.qual]](conv.qual "7.3.6Qualification conversions")) and
yield similar types T1 and T2, respectively
(where a standard conversion sequence that is a reference binding
is considered to yield the cv-unqualified referenced type),
where T1 and T2 are not the same type, andconst T2 is reference-compatible with T1 ([[dcl.init.ref]](dcl.init.ref "9.5.4References"))
[*Example [5](#example-5)*: int f(const volatile int *);int f(const int *);int i;int j = f(&i); // calls f(const int*)int g(const int*);int g(const volatile int* const&);int* p;int k = g(p); // calls g(const int*) — *end example*]
or, if not that,
* [(3.2.6)](#3.2.6)
S1 andS2 bind “reference to T1” and “reference to T2”,
respectively ([[dcl.init.ref]](dcl.init.ref "9.5.4References")),
where T1 and T2 are not the same type, andT2 is reference-compatible with T1
[*Example [6](#example-6)*: int f(const int &);int f(int &);int g(const int &);int g(int);
int i;int j = f(i); // calls f(int &)int k = g(i); // ambiguousstruct X {void f() const; void f();};void g(const X& a, X b) { a.f(); // calls X::f() const b.f(); // calls X::f()}int h(int (&)[]);int h(int (&)[1]);void g2() {int a[1];
h(a); // calls h(int (&)[1])} — *end example*]
or, if not that,
* [(3.2.7)](#3.2.7)
S1 and S2 bind the same reference type “reference to € and
have source types V1 and V2, respectively,
where the standard conversion sequence from V1* to T* is better than the standard conversion sequence from V2* to T*[.](#3.2.sentence-1)
[*Example [7](#example-7)*: struct Z {};
struct A {operator Z&(); operator const Z&(); // #1};
struct B {operator Z(); operator const Z&&(); // #2};
const Z& r1 = A(); // OK, uses #1const Z&& r2 = B(); // OK, uses #2 — *end example*]
- [(3.3)](#3.3)
User-defined conversion sequenceU1 is a better conversion sequence than another user-defined conversion
sequenceU2 if they contain the same user-defined conversion function or
constructor or they initialize the same class in an aggregate
initialization and in either case the second standard conversion
sequence ofU1 is better than
the second standard conversion sequence ofU2[.](#3.3.sentence-1)
[*Example [8](#example-8)*: struct A {operator short();} a;int f(int);int f(float);int i = f(a); // calls f(int), because short → int is// better than short → float. — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/overloading.tex#L2973)
Standard conversion sequences are ordered by their ranks: an Exact Match is a
better conversion than a Promotion, which is a better conversion than
a Conversion[.](#4.sentence-1)
Two conversion sequences with the same rank are indistinguishable unless
one of the following rules applies:
- [(4.1)](#4.1)
A conversion that does not convert a pointer or a pointer to member
tobool is better than one that does[.](#4.1.sentence-1)
- [(4.2)](#4.2)
A conversion that promotes an enumeration whose underlying type is fixed to its underlying
type is better than one that promotes to the promoted underlying type, if the two are
different[.](#4.2.sentence-1)
- [(4.3)](#4.3)
A conversion in either direction
between floating-point type FP1 and floating-point type FP2 is better than a conversion in the same direction
between FP1 and arithmetic type T3 if
* [(4.3.1)](#4.3.1)
the floating-point conversion rank ([[conv.rank]](conv.rank "6.9.6Conversion ranks")) of FP1 is equal to the rank of FP2, and
* [(4.3.2)](#4.3.2)
T3 is not a floating-point type, orT3 is a floating-point type
whose rank is not equal to the rank of FP1, or
the floating-point conversion subrank ([[conv.rank]](conv.rank "6.9.6Conversion ranks")) of FP2 is greater than the subrank of T3[.](#4.3.sentence-1)
[*Example [9](#example-9)*: int f(std::float32_t);int f(std::float64_t);int f(long long);float x;
std::float16_t y;int i = f(x); // calls f(std::float32_t) on implementations where// float and std::float32_t have equal conversion ranksint j = f(y); // error: ambiguous, no equal conversion rank — *end example*]
- [(4.4)](#4.4)
If classB is derived directly or indirectly from classA,
conversion ofB* toA* is better than conversion ofB* tovoid*,
and conversion ofA* tovoid* is better than conversion
ofB* tovoid*[.](#4.4.sentence-1)
- [(4.5)](#4.5)
If classB is derived directly or indirectly from classA and classC is derived directly or indirectly fromB,
* [(4.5.1)](#4.5.1)
conversion ofC* toB* is better than conversion ofC* toA*,
[*Example [10](#example-10)*: struct A {};struct B : public A {};struct C : public B {};
C* pc;int f(A*);int f(B*);int i = f(pc); // calls f(B*) — *end example*]
* [(4.5.2)](#4.5.2)
binding of an expression of typeC to a reference to typeB is better than binding an expression of typeC to a reference to typeA,
* [(4.5.3)](#4.5.3)
conversion ofA::* toB::* is better than conversion ofA::* toC::*,
* [(4.5.4)](#4.5.4)
conversion ofC toB is better than conversion ofC toA,
* [(4.5.5)](#4.5.5)
conversion ofB* toA* is better than conversion ofC* toA*,
* [(4.5.6)](#4.5.6)
binding of an expression of typeB to a reference to typeA is better than binding an expression of typeC to a
reference to typeA,
* [(4.5.7)](#4.5.7)
conversion ofB::* toC::* is better than conversion
ofA::* toC::*,
and
* [(4.5.8)](#4.5.8)
conversion ofB toA is better than conversion ofC toA[.](#4.5.sentence-1)
[*Note [1](#note-1)*:
Compared conversion sequences will have different source types only in the
context of comparing the second standard conversion sequence of an
initialization by user-defined conversion (see [[over.match.best]](over.match.best "12.2.4Best viable function")); in
all other contexts, the source types will be the same and the target
types will be different[.](#4.5.sentence-2)
— *end note*]