16 Overloading [over]

16.3 Overload resolution [over.match]

16.3.3 Best viable function [over.match.best]

Определите ICSi(F) следующим образом:

  • Если F это статическая функция-член, ICS1(F) определяется таким образом, что ICS1(F) не лучше и не хуже, чем ICS1(G) для любой функции G, и симметрично ICS1(G) не лучше и не хуже, чем ICS1(F);131 иначе,

  • пусть ICSi(F) обозначает неявную последовательность преобразования, которая преобразует i-й аргумент в списке в тип i-й параметр жизнеспособной функции F. [over.best.ics] определяет последовательности неявного преобразования и [over.ics.rank] определяет, что означает, что одна последовательность неявного преобразования является лучшей последовательностью преобразования или худшей последовательностью преобразования, чем другая.

С учетом этих определений жизнеспособная функция F1 определяется как better функция, чем другая жизнеспособная функция, F2 если для всех аргументов iICSi(F1) не является худшей последовательностью преобразования, чем ICSi(F2), а затем

  • для некоторого аргумента jICSj(F1) является лучшей последовательностью преобразования, чем ICSj(F2), или, если это не так,

  • контекст - это инициализация посредством определяемого пользователем преобразования (см. [dcl.init], [over.match.conv]и [over.match.ref]), а стандартная последовательность преобразования из возвращаемого типа F1 в целевой тип (т. е. тип инициализируемой сущности) является лучшей последовательностью преобразования, чем стандартное преобразование. последовательность от типа возврата F2 к типу назначения [Example:

    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] или, если не это,

  • контекст - это инициализация с помощью функции преобразования для direct reference binding ссылки на тип функции, возвращаемый тип F1 - это тот же вид ссылки (т.е. lvalue или rvalue), что и инициализируемая ссылка, а возвращаемый тип F2 - не [Example:

    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] или, если не это,

  • F1 не является специализацией шаблона функции, а F2 является специализацией шаблона функции, или, если это не так,

  • F1 и F2 являются специализациями шаблонов функций, а шаблон функции для F1 более специализирован, чем шаблон для, в F2 соответствии с правилами частичного упорядочивания, описанными в [temp.func.order], или, если это не так,

  • F1 генерируется из a deduction-guide([over.match.class.deduct]) и F2 не является, или, если это не так,

  • F1 является кандидатом на вычитание копии ([over.match.class.deduct]) и F2 не является, или, если это не так,

  • F1 создается из конструктора, не являющегося шаблоном, и F2 создается из шаблона конструктора. [Example:

    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]

Если существует ровно одна жизнеспособная функция, которая является лучшей функцией, чем все другие жизнеспособные функции, то она выбирается с помощью разрешения перегрузки; в противном случае звонок будет неправильно сформирован.132 [Example:

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]

Если лучшая жизнеспособная функция разрешается в функцию, для которой было найдено несколько объявлений, и если по крайней мере два из этих объявлений - или объявления, на которые они ссылаются, в случае using-declarations - указывают аргумент по умолчанию, который сделал функцию жизнеспособной, программа плохая. -формированный. [Example:

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]

Если функция является статической функцией-членом, это определение означает, что первый аргумент, подразумеваемый аргумент объекта, не влияет на определение того, является ли функция лучше или хуже любой другой функции.

Алгоритм выбора наилучшей жизнеспособной функции линейен по количеству жизнеспособных функций. Проведите простой турнир, чтобы найти функцию, W которая не хуже любого соперника, с которым она столкнулась. Хотя другая функция F , с W которой не сталкивались, могла быть по крайней мере так же хороша, как W, F не может быть лучшей функцией, потому что в какой-то момент турнира F встретилась другая функция, G такая F как G. Следовательно,W это либо лучшая функция , либо лучшая функция не существует. Итак, сделайте второй проход по жизнеспособным функциям, чтобы убедиться, что они W лучше, чем все другие функции.

16.3.3.1 Implicit conversion sequences [over.best.ics]

An - это последовательность преобразований, используемая для преобразования аргумента в вызове функции в тип соответствующего параметра вызываемой функции. Последовательность преобразований является неявным преобразованием, как определено в разделе , что означает, что она регулируется правилами инициализации объекта или ссылки одним выражением ( , ).implicit conversion sequence [conv][dcl.init] [dcl.init.ref]

Последовательности неявного преобразования связаны только с типом, cv-квалификацией и категорией значения аргумента, а также с тем, как они преобразуются для соответствия соответствующим свойствам параметра. Другие свойства, такие как время жизни, класс хранения, выравнивание, доступность аргумента, является ли аргумент битовым полем и является ли функция deleted, игнорируются. Таким образом, хотя неявная последовательность преобразования может быть определена для данной пары аргумент-параметр, преобразование аргумента в параметр может по-прежнему быть плохо сформированным в окончательном анализе.

Правильно сформированная последовательность неявного преобразования - это одна из следующих форм:

Однако если цель

  • первый параметр конструктора или

  • неявный объектный параметр определяемой пользователем функции преобразования

а конструктор или определяемая пользователем функция преобразования является кандидатом от

  • [over.match.ctor], когда аргумент является временным на втором этапе инициализации копии класса,

  • [over.match.copy],, [over.match.conv]или [over.match.ref] (во всех случаях), или

  • вторая фаза, [over.match.list] когда список инициализаторов имеет ровно один элемент, который сам является списком инициализаторов, а цель является первым параметром конструктора класса X, а преобразование - в X или ссылка на cv X,

определяемые пользователем последовательности преобразования не рассматриваются. [ Note: Эти правила предотвращают применение более одного определяемого пользователем преобразования во время разрешения перегрузки, тем самым избегая бесконечной рекурсии. ] [end noteExample:

  struct Y { Y(int); };
  struct A { operator int(); };
  Y y1 = A();       // error: A​::​operator int() is not a candidate

  struct X { };
  struct B { operator X(); };
  B b;
  X x({b});         // error: B​::​operator X() is not a candidate

end example]

Для случая, когда тип параметра является ссылкой, см [over.ics.ref]..

Если тип параметра не является ссылкой, неявная последовательность преобразования моделирует копирование-инициализацию параметра из выражения аргумента. Неявная последовательность преобразования - это последовательность, необходимая для преобразования выражения аргумента в значение типа параметра. [ Note: Если параметр имеет тип класса, это концептуальное преобразование, определенное для целей пункта [over]; фактическая инициализация определяется в терминах конструкторов и не является преобразованием. ] Любое различие в CV-квалификации верхнего уровня относится к самой инициализации и не является преобразованием. [ Параметр типа может быть инициализирован из аргумента типа . Последовательность неявного преобразования для этого случая является последовательностью идентичности; он не содержит «преобразования» из в . ] Когда параметр имеет тип класса и выражение аргумента имеет тот же тип, неявная последовательность преобразования является преобразованием идентичности. Когда параметр имеет тип класса, а выражение аргумента имеет тип производного класса, неявная последовательность преобразования представляет собой преобразование производного в базовый класс из производного класса в базовый класс. [ Такого стандартного преобразования нет; это преобразование производного в базовое существует только в описании неявных последовательностей преобразования. ] Производное преобразование в базовое имеет ранг преобразования ( ).end noteExample: Aconst Aconst AAend exampleNote: end note[over.ics.scs]

Во всех контекстах при преобразовании в параметр неявного объекта или при преобразовании в левый операнд операции присваивания разрешены только стандартные последовательности преобразования.

Если для сопоставления аргумента с типом параметра не требуется никаких преобразований, неявная последовательность преобразования - это стандартная последовательность преобразования, состоящая из преобразования идентичности ([over.ics.scs]).

Если не удается найти последовательность преобразований для преобразования аргумента в тип параметра, неявная последовательность преобразований не может быть сформирована.

Если существует несколько различных последовательностей преобразований, каждая из которых преобразует аргумент в тип параметра, неявная последовательность преобразования, связанная с параметром, определяется как уникальная последовательность преобразования, обозначенная как ambiguous conversion sequence. С целью ранжирования последовательностей неявных преобразований, как описано в [over.ics.rank]разделе, неоднозначная последовательность преобразования рассматривается как заданная пользователем последовательность преобразования, неотличимая от любой другой заданной пользователем последовательности преобразования. [ Note: Это правило предотвращает невозможность работы функции из-за неоднозначной последовательности преобразования одного из ее параметров. [Example:

class B;
class A { A (B&);};
class B { operator A (); };
class C { C (B&); };
void f(A) { }
void f(C) { }
B b;
f(b);               // ill-formed: ambiguous because there is a conversion b  C (via constructor)
                    // and an (ambiguous) conversion b  A (via constructor or conversion function)
void f(B) { }
f(b);               // OK, unambiguous

end example] ] Если функция, использующая неоднозначную последовательность преобразования, выбрана как наиболее жизнеспособная функция, вызов будет неправильно сформирован, поскольку преобразование одного из аргументов в вызове неоднозначно.end note

Три формы неявных последовательностей преобразования, упомянутые выше, определены в следующих подпунктах.

16.3.3.1.1 Standard conversion sequences [over.ics.scs]

Таблица 13 суммирует преобразования, определенные в пункте, [conv] и разбивает их на четыре непересекающиеся категории: преобразование Lvalue, корректировка квалификации, продвижение и преобразование. [ Note: Эти категории ортогональны по отношению к категории значения, cv-квалификации и представлению данных: преобразования Lvalue не изменяют cv-квалификацию или представление данных типа; Квалификационные корректировки не изменяют категорию значения или представление данных типа; и «Акции» и «Конверсии» не изменяют категорию значения или CV-квалификацию типа. ]end note

[ Note: Как описано в пункте [conv], стандартная последовательность преобразования представляет собой либо само преобразование идентификатора (то есть без преобразования), либо состоит из одного-трех преобразований из других четырех категорий. Если в последовательности есть два или более преобразований, преобразования применяются в каноническом порядке: преобразование Lvalue , продвижение или преобразование , корректировка квалификации . ]end note

Каждой конверсии в таблице 13 также соответствует ранг (точное соответствие, продвижение или конверсия). К ним привыкли rank standard conversion sequences. Ранг последовательности преобразования определяется путем рассмотрения ранга каждого преобразования в последовательности и ранга любого из них reference binding. Если любой из них имеет ранг конверсии, последовательность имеет ранг конверсии; в противном случае, если какой-либо из них имеет рейтинг повышения, последовательность имеет рейтинг повышения; в противном случае последовательность имеет ранг точного соответствия.

Таблица 13 - Конверсии
Преобразование Категория Классифицировать Подпункт
Никаких преобразований не требуется Личность
Lvalue-to-rvalue преобразование [conv.lval]
Преобразование массива в указатель Преобразование Lvalue [conv.array]
Преобразование функции в указатель Точное совпадение [conv.func]
Квалификационные преобразования [conv.qual]
Преобразование указателя на функцию Квалификационная корректировка [conv.fctptr]
Интегральные акции [conv.prom]
Продвижение с плавающей запятой Продвижение Продвижение [conv.fpprom]
Интегральные преобразования [conv.integral]
Преобразования с плавающей запятой [conv.double]
Преобразования с плавающей запятой [conv.fpint]
Преобразования указателей Преобразование Преобразование [conv.ptr]
Указатель на преобразования членов [conv.mem]
Логические преобразования [conv.bool]

16.3.3.1.2 User-defined conversion sequences [over.ics.user]

Определяемая пользователем последовательность преобразования состоит из начальной стандартной последовательности преобразования, за которой следует определяемое пользователем преобразование ([class.conv]), за которым следует вторая стандартная последовательность преобразования. Если определяемое пользователем преобразование равно specified by a constructor, начальная стандартная последовательность преобразования преобразует исходный тип в тип, требуемый аргументом конструктора. Если определяемое пользователем преобразование указано с помощью conversion function, начальная стандартная последовательность преобразования преобразует исходный тип в неявный объектный параметр функции преобразования.

Вторая стандартная последовательность преобразования преобразует результат определенного пользователем преобразования в целевой тип последовательности. Поскольку неявная последовательность преобразования является инициализацией, при выборе наилучшего пользовательского преобразования для пользовательской последовательности преобразования применяются специальные правила инициализации с помощью пользовательского преобразования (см. [over.match.best] И [over.best.ics]).

Если определяемое пользователем преобразование определяется специализацией шаблона функции преобразования, вторая стандартная последовательность преобразования должна иметь ранг точного совпадения.

Преобразованию выражения типа класса в тот же тип класса дается ранг точного соответствия, а преобразованию выражения типа класса в базовый класс этого типа дается ранг преобразования, несмотря на то, что конструктор (т. Е. , определяемая пользователем функция преобразования) вызывается для этих случаев.

16.3.3.1.3 Ellipsis conversion sequences [over.ics.ellipsis]

Последовательность преобразования многоточия возникает, когда аргумент в вызове функции совпадает со спецификацией параметра многоточия вызываемой функции (см [expr.call]. Раздел Ресурсы ).

16.3.3.1.4 Reference binding [over.ics.ref]

Когда параметр ссылочного типа binds directly на выражение аргумента, неявная последовательность преобразования является преобразованием идентичности, если только выражение аргумента не имеет тип, который является производным классом типа параметра, и в этом случае последовательность неявного преобразования является производным преобразованием в- базовое преобразование ([over.best.ics]). [Example:

struct A {};
struct B : public A {} b;
int f(A&);
int f(B&);
int i = f(b);       // calls f(B&), an exact match, rather than f(A&), a conversion

end example] Если параметр привязывается непосредственно к результату применения функции преобразования к выражению аргумента, неявная последовательность преобразования - это a user-defined conversion sequence, а вторая стандартная последовательность преобразования - либо преобразование идентичности, либо, если функция преобразования возвращает объект типа, который является производный класс типа параметра, преобразование производного в базовое.

Когда параметр ссылочного типа не привязан напрямую к выражению аргумента, последовательность преобразования - это та последовательность, которая требуется для преобразования выражения аргумента в ссылочный тип в соответствии с [over.best.ics]. Концептуально эта последовательность преобразования соответствует копированию-инициализации временного объекта указанного типа с помощью выражения аргумента. Любое различие в CV-квалификации верхнего уровня учитывается самой инициализацией и не является преобразованием.

За исключением неявного параметра объекта, о котором см. [over.match.funcs], Стандартная последовательность преобразования не может быть сформирована, если она требует привязки ссылки lvalue, отличной от ссылки на энергонезависимый const тип, к rvalue или привязки ссылки rvalue к lvalue, отличному от функции lvalue. [ Note: Это означает, например, что функция-кандидат не может быть жизнеспособной функцией, если она имеетconst параметр ссылки, отличного от lvalue (кроме неявного параметра объекта), и соответствующий аргумент потребует создания временного элемента для инициализации ссылки lvalue ( см. [dcl.init.ref]). ]end note

Однако другие ограничения на привязку ссылки к конкретному аргументу, не основанные на типах ссылки и аргумента, не влияют на формирование стандартной последовательности преобразования. [ Example: Функция с параметром «lvalue ссылка на int» может быть жизнеспособным кандидатом, даже если соответствующий аргумент является int битовым полем. Формирование последовательностей неявного преобразования обрабатывает int битовое поле как int lvalue и находит точное совпадение с параметром. Если функция выбрана путем разрешения перегрузки, вызов, тем не менее, будет неправильно сформирован из-за запрета на привязкуconst ссылки, отличной от lvalue, к битовому полю ([dcl.init.ref]). ]end example

16.3.3.1.5 List-initialization sequence [over.ics.list]

Когда аргумент является списком инициализатора ([dcl.init.list]), это не выражение, и для его преобразования в тип параметра применяются специальные правила.

Если тип параметра является агрегатным классом, X а список инициализаторов имеет единственный элемент типа cv U, где U is X или класс, производный от X, неявная последовательность преобразования - это последовательность, необходимая для преобразования элемента в тип параметра.

В противном случае, если тип параметра является символьным массивом,133 а в списке инициализаторов есть единственный элемент, который является строковым литералом соответствующего типа ([dcl.init.string]), неявная последовательность преобразования является преобразованием идентичности.

В противном случае, если тип параметра равен std​::​initializer_­list<X> и все элементы списка инициализатора могут быть неявно преобразованы в X, последовательность неявного преобразования является наихудшим преобразованием, необходимым для преобразования элемента списка в X, или, если список инициализатора не имеет элементов, идентификатор конверсия. Это преобразование может быть определенным пользователем преобразованием даже в контексте вызова конструктора списка инициализаторов. [Example:

void f(std::initializer_list<int>);
f( {} );                // OK: f(initializer_­list<int>) identity conversion
f( {1,2,3} );           // OK: f(initializer_­list<int>) identity conversion
f( {'a','b'} );         // OK: f(initializer_­list<int>) integral promotion
f( {1.0} );             // error: narrowing

struct A {
  A(std::initializer_list<double>);             // #1
  A(std::initializer_list<complex<double>>);    // #2
  A(std::initializer_list<std::string>);        // #3
};
A a{ 1.0,2.0 };         // OK, uses #1

void g(A);
g({ "foo", "bar" });    // OK, uses #3

typedef int IA[3];
void h(const IA&);
h({ 1, 2, 3 });         // OK: identity conversion

end example]

В противном случае, если тип параметра - «массив из N X», если существует неявная последовательность преобразования для каждого элемента массива из соответствующего элемента списка инициализаторов (или из, {} если такого элемента нет), последовательность неявного преобразования является худшая такая последовательность неявного преобразования.

В противном случае, если параметр не является совокупным учащимся X и Разрешением перегрузки PER [over.match.list] выбирает один лучший конструктором C из X выполнить инициализацию объекта типа X от аргумента инициализатора списка:

  • Если C это не конструктор списка инициализаторов, а список инициализаторов имеет единственный элемент типа cv U, где U is X или класс, производный от X, неявная последовательность преобразования имеет ранг точного соответствия, если он U есть X, или ранг преобразования, если U является производным от X.

  • В противном случае неявная последовательность преобразования является пользовательской последовательностью преобразования, а вторая стандартная последовательность преобразования является преобразованием идентичности.

Если жизнеспособны несколько конструкторов, но ни один из них не лучше других, последовательность неявного преобразования является последовательностью неоднозначного преобразования. Пользовательские преобразования разрешены для преобразования элементов списка инициализаторов в типы параметров конструктора, за исключением случаев, указанных в [over.best.ics]. [Example:

struct A {
  A(std::initializer_list<int>);
};
void f(A);
f( {'a', 'b'} );        // OK: f(A(std​::​initializer_­list<int>)) user-defined conversion

struct B {
  B(int, double);
};
void g(B);
g( {'a', 'b'} );        // OK: g(B(int, double)) user-defined conversion
g( {1.0, 1.0} );        // error: narrowing

void f(B);
f( {'a', 'b'} );        // error: ambiguous f(A) or f(B)

struct C {
  C(std::string);
};
void h(C);
h({"foo"});             // OK: h(C(std​::​string("foo")))

struct D {
  D(A, C);
};
void i(D);
i({ {1,2}, {"bar"} });  // OK: i(D(A(std​::​initializer_­list<int>{1,2}), C(std​::​string("bar"))))

end example]

В противном случае, если параметр имеет тип агрегата, который может быть инициализирован из списка инициализаторов в соответствии с правилами для aggregate initialization, неявная последовательность преобразования является пользовательской последовательностью преобразования, а вторая стандартная последовательность преобразования является преобразованием идентичности. [Example:

struct A {
  int m1;
  double m2;
};

void f(A);
f( {'a', 'b'} );        // OK: f(A(int,double)) user-defined conversion
f( {1.0} );             // error: narrowing

end example]

В противном случае, если параметр является справочным, см [over.ics.ref]. [ Note: Правила в этом разделе будут применяться для инициализации базового временного объекта для ссылки. ] [ end noteExample:

struct A {
  int m1;
  double m2;
};

void f(const A&);
f( {'a', 'b'} );        // OK: f(A(int,double)) user-defined conversion
f( {1.0} );             // error: narrowing

void g(const double &);
g({1});                 // same conversion as int to double

end example]

В противном случае, если тип параметра не является классом:

  • если в списке инициализаторов есть один элемент, который сам не является списком инициализаторов, неявная последовательность преобразования является той, которая требуется для преобразования элемента в тип параметра; [Example:

    void f(int);
    f( {'a'} );             // OK: same conversion as char to int
    f( {1.0} );             // error: narrowing
    

    end example]

  • если список инициализаторов не имеет элементов, неявная последовательность преобразования является преобразованием идентичности. [Example:

    void f(int);
    f( { } );               // OK: identity conversion
    

    end example]

Во всех случаях, кроме перечисленных выше, преобразование невозможно.

Поскольку нет параметров типа массива, это будет происходить только как ссылочный тип ссылочного параметра.

16.3.3.2 Ranking implicit conversion sequences [over.ics.rank]

В этом подпункте определяется частичный порядок неявных последовательностей преобразования на основе отношений better conversion sequence и better conversion. Если неявная последовательность преобразования S1 определена этими правилами как лучшая последовательность преобразования, чем S2, то это также случай, когда S2 является a, worse conversion sequence чем S1. Если последовательность преобразования S1 не лучше и не хуже, чем последовательность преобразования S2, то говорят, что S1 и S2 indistinguishable conversion sequences.

При сравнении основных форм неявных последовательностей преобразования (как определено в [over.best.ics])

  • a standard conversion sequence - лучшая последовательность преобразования, чем определенная пользователем последовательность преобразования или последовательность преобразования с многоточием, и

  • a user-defined conversion sequence - лучшая последовательность преобразования, чем ellipsis conversion sequence.

Две неявные последовательности преобразования одной и той же формы являются неотличимыми последовательностями преобразования, если не применяется одно из следующих правил:

  • Последовательность инициализации списка L1 является лучшей последовательностью преобразования, чем последовательность инициализации списка, L2 если

    • L1 конвертируется в std​::​initializer_­list<X> для некоторых X и L2 не преобразуется , или, если не то,

    • L1 преобразуется в тип «массив N1 T», L2 преобразуется в тип «массив из N2 T» и N1 меньше, чем N2,

    даже если в противном случае применимо одно из других правил этого параграфа. [Example:

      void f1(int);                                 // #1
      void f1(std::initializer_list<long>);         // #2
      void g1() { f1({42}); }                       // chooses #2
    
      void f2(std::pair<const char*, const char*>); // #3
      void f2(std::initializer_list<std::string>);  // #4
      void g2() { f2({"foo","bar"}); }              // chooses #4
    

    end example]

  • Стандартная последовательность преобразования S1 является лучшей последовательностью преобразования, чем стандартная последовательность преобразования, S2 если

    • S1 является надлежащей подпоследовательностью S2 (сравнение последовательностей преобразования в канонической форме, определенной с помощью [over.ics.scs], исключая любое преобразование Lvalue; последовательность преобразования идентичности считается подпоследовательностью любой последовательности преобразования, отличной от идентичности) или, если это не так,

    • ранг S1 лучше, чем ранг S2, или S1 и S2 имеют такой же ранг и различимы по правилам, изложенным в нижеследующем абзаце, или, если это не так,

    • S1 и S2 являются привязками ссылок ([dcl.init.ref]), и ни одна из них не относится к неявному объектному параметру нестатической функции-члена, объявленной без a ref-qualifier, и S1 связывает ссылку rvalue с rvalue и S2 связывает ссылку lvalue [Example:

      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] или, если не это,

    • S1 и S2 являются привязками ссылок ([dcl.init.ref]) и S1 связывает ссылку lvalue с функцией lvalue и S2 связывает ссылку rvalue с функцией lvalue [Example:

      int f(void(&)());               // #1
      int f(void(&&)());              // #2
      void g();
      int i1 = f(g);                  // calls #1
      

      end example] или, если не это,

    • S1 и S2 отличаются только их квалификационным преобразованием и дают аналогичные типы T1 и T2 ([conv.qual]), соответственно, а сигнатура cv-qualification типа T1 является надлежащим подмножеством сигнатуры cv-qualification типа T2 [Example:

      int f(const volatile int *);
      int f(const int *);
      int i;
      int j = f(&i);                  // calls f(const int*)
      

      end example] или, если не это,

    • S1 и S2 являются ссылочными привязками ([dcl.init.ref]), а типы, на которые ссылаются ссылки, относятся к одному и тому же типу, за исключением cv-квалификаторов верхнего уровня, а тип, на который ссылается ссылка, инициализированная с помощью, S2 более квалифицирован cv, чем тип, на который ссылка инициализируется S1 ссылками. [Example:

      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);                   // ambiguous
      
      struct X {
        void f() const;
        void f();
      };
      void g(const X& a, X b) {
        a.f();                        // calls X​::​f() const
        b.f();                        // calls X​::​f()
      }

      end example]

  • Определяемая пользователем последовательность преобразования U1 является лучшей последовательностью преобразования, чем другая определяемая пользователем последовательность преобразования, U2 если они содержат ту же определенную пользователем функцию преобразования или конструктор или инициализируют один и тот же класс в совокупной инициализации, и в любом случае вторая стандартная последовательность преобразования U1 равна лучше, чем вторая стандартная последовательность преобразования U2. [Example:

    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]

Стандартные последовательности конверсии упорядочены по их рангам: точное соответствие - лучшая конверсия, чем продвижение, а это лучшая конверсия, чем конверсия. Две последовательности преобразования с одинаковым рангом неразличимы, если не применяется одно из следующих правил:

  • Преобразование, которое не преобразует указатель, указатель на член или std​::​nullptr_­t на bool , лучше, чем такое преобразование .

  • Преобразование, которое продвигает перечисление, базовый тип которого фиксирован для его базового типа, лучше, чем преобразование, которое продвигает в продвинутый базовый тип, если они разные.

  • Если класс B является производным прямо или косвенно от класса A, преобразование B* в A* лучше, чем преобразование B* в void*, а преобразование A* в void* лучше, чем преобразование B* в void*.

  • Если класс B является производным прямо или косвенно от класса, A а класс C является производным прямо или косвенно от B,

    • преобразование C* в B* лучше, чем преобразование C* в A*, [Example:

      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]

    • привязка выражения типа C к ссылке на тип B лучше, чем привязка выражения типа C к ссылке на тип A,

    • преобразование A​::​* в B​::​* лучше, чем преобразование A​::​* в C​::​*,

    • преобразование C в B лучше, чем преобразование C в A,

    • преобразование B* в A* лучше, чем преобразование C* в A*,

    • привязка выражения типа B к ссылке на тип A лучше, чем привязка выражения типа C к ссылке на тип A,

    • преобразование B​::​* в C​::​* лучше, чем преобразование A​::​* в C​::​*, и

    • преобразование B в A лучше, чем преобразование C в A.

    [ Note: Сравниваемые последовательности преобразования будут иметь разные типы источников только в контексте сравнения второй стандартной последовательности преобразования инициализации посредством пользовательского преобразования (см. [over.match.best]); во всех других контекстах исходные типы будут такими же, а целевые типы будут разными. ] end note