@Brian Public сейчас.

е следующее:

struct X {
    X() {}
    X(X&&) { puts("move"); }
};
X x = X();

В C ++ 14 перемещение может быть исключено, несмотря на то, что конструктор перемещения имеет побочные эффекты благодаря [class.copy] / 31,

Такое исключение операций копирования / перемещения ... допускается в следующих обстоятельствах ... когда временный объект класса, который не был связан со ссылкой (12.2), будет скопирован / перемещен в объект класса с тем же cv-unqualified тип

В C ++ 17 эта пуля была удалена. Вместо этого движение гарантированно будет отменено благодаря [dcl.init] /17.6.1:

Если выражение инициализатора является prvalue, а версия cv-unqualified типа источника является тем же классом, что и класс назначения, выражение инициализатора используется для инициализации объекта назначения. [Пример: T x = T(T(T())); вызываетT конструктор по умолчанию для инициализацииx, -конец примера ]

Пока факты, которые я изложил, хорошо известны. Но теперь давайте изменим код так, чтобы он читал:

X x({});

В C ++ 14 выполняется разрешение перегрузки и{} преобразуется во временный типX используя конструктор по умолчанию, затем переместился вx, Правила отмены копирования позволяют исключить этот шаг.

В C ++ 17 разрешение перегрузки то же самое, но теперь [dcl.init] /17.6.1 не применяется, а маркера из C ++ 14 больше нет. Выражения инициализатора нет, так как инициализатор представляет собой список фигурных скобок. Вместо этого кажется, что [dcl.init] / (17.6.2) применяется:

В противном случае, если инициализация является прямой инициализацией, или если это инициализация копирования, где cv-неквалифицированная версия исходного типа является тем же классом или производным классом класса назначения, конструкторы рассматриваются. Применимые конструкторы перечислены (16.3.1.3), и лучший выбирается через разрешение перегрузки (16.3). Выбранный таким образом конструктор вызывается для инициализации объекта, с выражением инициализатора или списком выражений в качестве аргументов. Если конструктор не применяется, или разрешение перегрузки неоднозначно, инициализация некорректна.

Похоже, что для этого требуется вызвать конструктор перемещения, и если в другом месте стандарта есть правило, гласящее, что его можно удалить, я не знаю, где оно.

Ответы на вопрос(1)

Ваш ответ на вопрос