¿C ++ 17 prohíbe la elisión de copia en un caso donde C ++ 14 lo permitió?

Considera lo siguiente:

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

En C ++ 14, el movimiento podría eludirse a pesar de que el constructor del movimiento tiene efectos secundarios gracias a [class.copy] / 31,

Esta elisión de operaciones de copiar / mover ... está permitida en las siguientes circunstancias ... cuando un objeto de clase temporal que no se ha vinculado a una referencia (12.2) se copiará / moverá a un objeto de clase con el mismo cv-no calificado tipo

En C ++ 17 esta bala fue eliminada. En cambio, se garantiza que el movimiento se eliminará gracias a [dcl.init] /17.6.1:

Si la expresión inicializadora es un valor prva y la versión no calificada por cv del tipo fuente es la misma clase que la clase del destino, la expresión inicializadora se usa para inicializar el objeto de destino. [Ejemplo: T x = T(T(T())); llama alT constructor predeterminado para inicializarx. -ejemplo final ]

Hasta ahora, los hechos que he declarado son bien conocidos. Pero ahora cambiemos el código para que lea:

X x({});

En C ++ 14, se realiza la resolución de sobrecarga y{} se convierte a un tipo temporalX utilizando el constructor predeterminado, luego se trasladó ax. Las reglas de copia de elisión permiten eludir este movimiento.

En C ++ 17, la resolución de sobrecarga es la misma, pero ahora [dcl.init] /17.6.1 no se aplica y la viñeta de C ++ 14 ya no está allí. No hay una expresión de inicializador, ya que el inicializador es una lista de inicialización arriostrada. En cambio, parece que se aplica [dcl.init] / (17.6.2):

De lo contrario, si la inicialización es inicialización directa, o si es una inicialización de copia donde la versión no calificada por cv del tipo de origen es la misma clase o una clase derivada de la clase del destino, se consideran los constructores. Los constructores aplicables se enumeran (16.3.1.3), y el mejor se elige mediante la resolución de sobrecarga (16.3). El constructor así seleccionado se llama para inicializar el objeto, con la expresión inicializadora o la lista de expresiones como argumento (s). Si no se aplica ningún constructor, o la resolución de sobrecarga es ambigua, la inicialización está mal formada.

Esto parece requerir que se llame al constructor de movimiento, y si hay una regla en otra parte del estándar que dice que está bien eludirlo, no sé dónde está.

Respuestas a la pregunta(1)

Su respuesta a la pregunta