Ответ 1
TL;DR: когда все остальное равно, разрешение перегрузки прерывает связь, с помощью которой функция преобразования имеет наилучшее преобразование из возвращаемого значения в целевой тип.
Все ссылки относятся к ISO/IEC 14882: 2011 (С++ 11). Поведение инициализации:
void* x = a;
определяется следующим образом. Во-первых, это инициализация, как описано в 8.5 Initializers [dcl.init], и соответствует грамматике, описанной в p1. Поскольку тип назначения void*
является неклассовым типом, а тип источника A
является типом класса, этот конкретный инициализатор имеет форму, описанную в 8.5 p16, bullet 7:
В противном случае, если тип источника является (возможно, cv-qualit) классом, рассматриваются функции преобразования. Применяемые функции преобразования перечислены (13.3.1.5), а наилучшая выбирается с помощью разрешения перегрузки (13.3). Выбранное пользователем преобразование вызывается для преобразования выражения инициализатора в инициализированный объект. Если преобразование не может быть выполнено или неоднозначно, инициализация плохо сформирована.
"Перечисление применимых функций преобразования" подробно описано в 13.3.1.5 p1:
В условиях, указанных в 8.5, как часть инициализации объекта типа некласса, преобразование функция может быть вызвана для преобразования выражения инициализатора типа класса в тип объекта, являющегося инициализируется. Разрешение перегрузки используется для выбора функции преобразования для вызова. Предполагая, что "cv1 T" - тип инициализируемого объекта, а "cv S" - тип выражения инициализатора, причем S a тип класса, выбранные функции выбираются следующим образом:
- Рассматриваются функции преобразования S и его базовые классы. Те неявные преобразования функции, которые не скрыты внутри S и выдают тип T или тип, который может быть преобразован в тип T через стандартную последовательность преобразования (13.3.3.1.1) являются функциями кандидата. Для прямой инициализации эти явные функции преобразования, которые не скрыты внутри S, и дают тип T или тип, который может быть преобразованные в тип T с квалификационным преобразованием (4.4), также являются кандидатными функциями. преобразование функции, возвращающие тип с квалификацией cv, считаются выпущенными cv-неквалифицированной версией этого типа для этого процесса выбора кандидатских функций. Функции преобразования, возвращающие "ссылку на cv2 X" возвращают lvalues или xvalues, в зависимости от типа ссылки, типа "cv2 X" и поэтому считается, что для этого процесса выбора кандидатских функций X получает X.
Обратите внимание, что как A::operator A*()
, так и A::operator B*()
являются функциями-кандидатами, поскольку оба A*
и B*
могут быть конвертированы в void*
за
4.10p2: указатель "prvalue of type" на cv T
, где T
- тип объекта, может быть преобразован в указатель типа "указатель"
к cv void
"." Учитывая, что обе функции являются кандидатами, разрешение перегрузки должно выбирать между ними.
Разрешение перегрузки описывается в 13.3 [over.match]. p2:
Разрешение перегрузки выбирает функцию для вызова в семи разных контекстах языка:
...
- вызов функции преобразования для инициализации объекта типа nonclass из выражения типа класса (13.3.1.5)
...
Каждый из этих контекстов определяет набор функций-кандидатов и список аргументов своим уникальным способом. Но, как только функции кандидата и списки аргументов были идентифицированы, выбор лучшей функции во всех случаях одинаковый:
Сначала подмножество функций-кандидатов (те, которые имеют правильное количество аргументов и удовлетворяют некоторым другим условиям) выбирается так, чтобы сформировать набор жизнеспособных функций (13.3.2).
Затем выбирается наилучшая жизнеспособная функция на основе неявных последовательностей преобразования (13.3.3.1), необходимых для сопоставления каждого аргумента с соответствующим параметром каждой жизнеспособной функции.
Какая из наших двух функций жизнеспособна? 13.3.2 [over.match.viable] p1:
Из набора функций-кандидатов, построенных для данного контекста (13.3.1), набор жизнеспособных функций выбранный, из которого лучшая функция будет выбрана путем сравнения последовательностей преобразования аргументов для лучше всего подходит (13.3.3).
Требования представлены в p2:
Во-первых, чтобы быть жизнеспособной функцией, функция-кандидат должна иметь достаточно параметров для согласования числа с аргументы в списке.
и p3:
Во-вторых, для
F
, чтобы быть жизнеспособной функцией, для каждого аргумента должно существовать неявная последовательность преобразований (13.3.3.1), который преобразует этот аргумент в соответствующий параметрF
.
Оба требования тривиально удовлетворяются нашими функциями преобразования: у них есть один (неявный) аргумент того же типа, что и выражение инициализатора A
.
Определение наилучшего из жизнеспособных функций описано в 13.3.3 [over.match.best]. Он определяет некоторые формализмы для описания последовательностей преобразования, последовательности операций, необходимые для преобразования из типов аргументов фактической функции в типы формальных параметров функции. В случае наших функций преобразования оба они имеют ровно один параметр, тип которого точно соответствует фактическому аргументу, поэтому "последовательность преобразования", соответствующая каждой перегрузке, является тождественной последовательностью. Они различаются языком в p1:
Учитывая эти определения, жизнеспособная функция
F1
определяется как лучшая функция, чем другая жизнеспособная функцияF2
, если для всех аргументовi
,ICSi(F1)
не является худшей последовательностью преобразования, чемICSi(F2)
, и затем
для некоторого аргумента
j
,ICSj(F1)
- лучшая последовательность преобразования, чемICSj(F2)
, или, если не это,контекст представляет собой инициализацию путем пользовательского преобразования (см. 8.5, 13.3.1.5 и 13.3.1.6) и стандартная последовательность преобразования из возвращаемого типа
F1
в тип назначения (то есть тип инициализация объекта) является лучшей последовательностью преобразования, чем стандартная последовательность преобразования из возвращаемый типF2
к типу назначения.
Как насчет этой финальной пули? Имеет ли одна из наших перегрузок более качественная стандартная последовательность преобразования от ее возвращаемого типа до void*
?
13.3.3.2. Ранжирование неявных последовательностей преобразования [over.ics.rank] p4 указывает во второй точке маркера:
Если класс
B
получается прямо или косвенно из классаA
, преобразованиеB*
вA*
лучше, чем преобразованиеB*
вvoid*
, а преобразованиеA*
вvoid*
лучше, чем преобразованиеB*
вvoid*
.
Это точно в случае OP, за исключением случаев, когда имена A
и B
отменены. Разрешение перегрузки для двух операторов преобразования OP разрешается в пользу A::operator B*()
, поскольку указанное правило делает последовательность преобразования B*
→ void*
лучше, чем A*
→ void*