Ответ 1
TL;DR
Неоднозначное. (Кроме того, если вы остановитесь на tl; dr, то тег language-lawyer
может быть не чашкой чая. ^ _ ^)
Спойлер
Оба кандидата имеют один параметр const foo&
, который в равной степени привязывается к аргументу const foo
или foo
. Нет других правил, которые бы предпочли одну или другую функцию.
Прервать его с текущий рабочий проект С++
Инициализаторы [dcl.init]
В обоих случаях
- выполняется копирование ([dcl.init]/15)
- тип назначения - тип класса ([dcl.init]/17.6)
- (X) выражение инициализатора не является prvalue ([dcl.init]/17.6.1)
- (X) тип источника не совпадает или получен из целевого типа ([dcl.init]/17.6.2)
- Пользовательские последовательности преобразования перечисляются из [over.match.copy] и наилучшим образом выбранным разрешение перегрузки.
Копирование инициализации класса по пользовательскому преобразованию [over.match.copy]
T
- тип, который является intialised, в обоих случаях это bar
.
S
- тип выражения инициализатора, в двух случаях foo
и const foo
соответственно.
- преобразовательные конструкторы
T
являются кандидатами ([over.match.copy]/1.1)-
bar::bar(const foo& foo);
является кандидатом
-
- тип выражения инициализатора
_cv_ S
, поэтому рассматриваются неявные функции преобразования ([over.match.copy]/1.2)-
foo::operator bar() const
не скрывается внутриfoo
или внутриconst foo
и даетbar
, который совпадает сT
и, следовательно, является кандидатом.
-
Таким образом, наш список кандидатов в обоих случаях одинаковый:
-
bar::bar(const foo& foo)
-
foo::operator bar() const
В обоих случаях мы имеем пользовательское преобразование, состоящее из:
- Стандартное преобразование типа источника в пользовательский аргумент преобразования
- Пользовательское преобразование (одна из двух вышеперечисленных функций) для типа результата
- Стандартное преобразование типа результата в целевой тип
Если мы выберем конструктор, "тип результата" будет "prvalue cv-неквалифицированной версии типа назначения, объект результата которого инициализируется конструктором" ([dcl.init]/17.6.3), поэтому для обеих кандидатских функций второе стандартное преобразование Идентичность (bar
→ bar
).
Разрешение перегрузки [over.match]
Подстановка жизнеспособных функций-кандидатов [over.match.viable]
Per [dcl.init]/17.6.3, выражение инициализатора будет аргументом для выбранного вызова, в два случая foo
и const foo
соответственно.
bar::bar(const foo& foo)
- Один аргумент в списке аргументов, ровно один параметр. ([over.match.viable]/2.1)
- Нет связанных ограничений ([over.match.viable]/3)
- Неявная последовательность преобразования существует как из
foo
, так иconst foo
вconst foo&
([over.match.viable]/4) - Первоначальное стандартное преобразование Преобразование идентичности в обоих случаях: [over.best.ics]/5= > [over.ics.ref]/1 для прямого связывания ссылок:
-
const foo
является ссылочной совместимостью как сfoo
, так и сconst foo
, посколькуconst
больше cv-qual, чемconst
, и ничего. [dcl.init.ref]/4 -
const foo&
привязывается непосредственно к lvaluefoo
и lvalueconst foo
. [dcl.init.ref]/5
-
- жизнеспособное
foo::operator bar() const
- Один аргумент в списке аргументов, ровно один неявный объектпараметр. ([over.match.viable]/2.1)
- Неявный параметр объекта
const foo&
в обоих случаях ([over.match.funcs]/4)
- Неявный параметр объекта
- Нет связанных ограничений ([over.match.viable]/3)
- Неявная последовательность преобразования существует как из
foo
, так иconst foo
вconst foo&
([over.match.viable]/4) - Первоначальное стандартное преобразование Преобразование идентичности в обоих случаях, см. выше.
- жизнеспособное
Выберите наилучшую жизнеспособную функцию [over.best.ics]
Оба являются Identity = > User Defined Conversion = > Identity, то есть пользовательские последовательности конверсий.
Ранжирование последовательностей преобразования over.ics.rank
Можно ли установить ранжирование между последовательностями? Только если применяется одно из следующих условий:
- (X) Непоследовательные последовательности инициализации ([over.ics.rank]/3)
- (X) Не стандартная последовательность преобразования ([over.ics.rank]/3.2)
- (X) Две последовательности не содержат "одну и ту же пользовательскую функцию преобразования или конструктор или [...] инициализировать один и тот же класс в агрегатной инициализации" ([over.ics.rank]/3.3)
Последовательности конверсии неразличимы, т.е. ни лучше, ни хуже
Лучшая жизнеспособная функция over.match.best
Является ли функция "лучшей"? Только если применяется одно из следующих условий:
- (X) Ни одна из них не является лучшей последовательностью преобразования ([over.match.best]/1.3)
- (X) Второе стандартное преобразование одно и то же ([over.match.best]/1.4)
- (X) Не прямая ссылка, связывающая ссылку на тип функции ([over.match.best]/1.5)
- (X) Также не является специализированной функцией шаблона ([over.match.best]/1.6 и [over.match.best]/1.7)
- (X) Также не ограничено ([over.match.best]/1.8)
- (X) Один является конструктором для
bar
, но другой не является конструктором для базового классаbar
([over. match.best]/1.9) - (X) Не выводится типы классов ([[over.match.best]/1.10] (http://eel.is/c++draft/over.match.best#1.10 и [over.match.best]/1.11
- (X) Ни шаблон конструктора ([over.match.best]/1.12)
Также не существует "лучшей" функции, поэтому вызов плохо сформирован. [over.match.best]/2