Этот вопрос касается формулировки стандарта c ++.
Все компиляторы, и я думаю, что так и должно быть, исключите конструктор копирования для инициализации объекта b
ниже ( сборка здесь ):
struct B;
struct A{
operator B();
};
struct B{
B(const B&);
B(B&&);
};
void test(A a){
B b(a);
}
Но когда я читаю стандарт, я не понимаю, почему это исключение произойдет (жирный шрифт) [dcl.init] /17.6.2:
В противном случае, если инициализация является прямой инициализацией, [...], рассматриваются конструкторы.
Применимые конструкторы перечисляются ([over.match.ctor]), и лучший выбирается с помощью разрешения перегрузки ([over.match]).
Выбранный таким образом конструктор называется для инициализации объекта, с выражением инициализатора или списком выражений в качестве аргументов.
Если конструктор не применяется или разрешение перегрузки неоднозначно, инициализация неверна.
В частности, говорится, что конструктор вызывается. Но никакой компилятор этого не делает.
Я предполагаю, что что-то упустил или неправильно читал стандарт. Как читать стандарт?
Это отличие от предыдущего и следующего параграфов стандарта, которые специально предписывают копию elision [dcl.init] /17.6.1:
Если выражение инициализатора является prvalue, а cv-неквалифицированная версия типа источника совпадает с классом класса назначения, выражение инициализатора используется для инициализации объекта назначения .
и [dlc.init] /17.6.3:
В противном случае (т. Е. Для остальных случаев инициализации копирования), определяемые пользователем преобразования, которые могут преобразовывать из исходного типа в целевой тип [...]
Выбранная функция вызывается с выражением инициализатора в качестве аргумента; [...]
Вызов используется для прямой инициализации, в соответствии с приведенными выше правилами, объекта, являющегося местом назначения инициализации копирования.
Где последнее предложение отправляет меня обратно в [dcl.init] /17.6.1, что также подразумевает исключение копии.