Я думаю, что правильное поведение по стандарту должно быть неоднозначным.
[dcl.init] /17.1:
Если инициализатором является (не заключенный в скобки) фигурный список инициализации или является = фигурный инициализированный список, объект или ссылка инициализируются списком.
[dcl.init.list] /3.6:
В противном случае, если T является типом класса, учитываются конструкторы. Применимые конструкторы перечисляются, и лучший выбирается через разрешение перегрузки ([over.match], [over.match.list]). Если для преобразования какого-либо из аргументов требуется сужающее преобразование (см. Ниже), программа некорректна.
И [over.match.list] просто говорит о выборе конструктора. У нас есть две жизнеспособные опции: P(E)
с помощью L{}.operator E()
и P(P&&)
(неявный конструктор перемещения) с помощью L{}.operator P()
. Нет лучше другого.
<ч />
Однако, это очень напоминает CWG 2327 :
struct Cat {};
struct Dog { operator Cat(); };
Dog d;
Cat c(d);
Что, как показывает проблема, в настоящее время вызывает Cat(Cat&&)
вместо просто d.operator Cat()
и предполагает, что мы должны также рассмотреть функции преобразования. Но это все еще открытый вопрос. Я не уверен, что gcc или clang сделали в ответ на эту проблему (или в ответ на подобные примеры, которые были подняты первыми), но, основываясь на ваших результатах, я подозреваю, что они решают, что функция прямого преобразования L{}.operator P()
лучше соответствовать и просто сделать это.