Ответ 1
С++ 14
Согласно N3797 [expr.static.cast], пункт 4:
Выражение
e
может быть явно преобразовано в типT
используяstatic_cast
формыstatic_cast<T>(e)
если объявлениеT t(e);
хорошо сформирована, для некоторой изобретенной временной переменнойt
(8.5). Эффект такого явного преобразования такой же, как выполнение объявления и инициализации, а затем использование временной переменной в результате преобразования.
Выражение static_cast<B>(a)
выполняет прямую инициализацию временной переменной типа B
из инициализатора a
. Затем применяется следующая марка от N3797 [dcl.init], параграф 17:
Если инициализация является прямой инициализацией или если она является копией-инициализацией, в которой рассматривается cv-неквалифицированная версия типа источника того же класса, что или производный класс класса назначения, рассматриваются конструкторы. Соответствующие конструкторы перечислены (13.3.1.3), а лучший выбирается с помощью разрешения перегрузки (13.3). Выбранный таким образом конструктор вызывается для инициализации объекта с выражением инициализатора или списком выражений в качестве аргумента (ов). Если конструктор не применяется или разрешение перегрузки неоднозначно, инициализация плохо сформирована.
И "применимые конструкторы" определены N3797 [over.match.ctor]:
Для прямой инициализации функции-кандидаты - это все конструкторы класса инициализируемого объекта.
Таким образом, все три конструктора: B::B(int)
, B::B(const B&)
, B::B(B&&)
являются кандидатами во время разрешения перегрузки. Затем A->int
три соответствующие имплицитные последовательности преобразования: A->int
, A->const B&
, A->B&&
. В результате A->int
отличается от двух других, поскольку условия следующей пули из пункта 3 N3797 [over.ics.rank] не выполняются:
Пользовательская последовательность
U1
преобразования является лучшей последовательностью преобразования, чем другая пользовательская последовательностьU2
преобразования, если они содержат одну и ту же определяемую пользователем функцию преобразования или конструктор или они инициализируют один и тот же класс в инициализации агрегата, и в любом случае вторая стандартная последовательность преобразования от U1 лучше, чем вторая стандартная последовательность преобразованияU2
.
Кроме того, не применяются специальные правила определения наилучшей жизнеспособной функции в N3797 [over.match.best], поэтому разрешение перегрузки неоднозначно, что вызывает ошибку компилятора.
С++ 17
Вывод выше также имеет место, поэтому это ошибка компилятора (пока). Формулировка пункта 4 [expr.static.cast] изменилась из-за CWG 242, но это не влияет на наш вывод.
Обратите внимание, что гарантированное копирование не применяется здесь, потому что оно не является инициализацией из знака того же типа.
С++ 20 или более поздняя версия
Уже обсуждается вопрос о добавлении гарантированного экземпляра копии в такие случаи с прямой инициализацией, поэтому, возможно, поведение выбора a.operator B()
будет законным в будущем.