Почему конструктор move std:: optional не удаляется, когда T не является конструктивным?

В соответствии со стандартом, copy-constructor std::optional<T>:

... должен быть определен как удаленный, если is_copy_constructible_v<T> не равен true.

Но конструктор move std::optional<T>:

... не участвует в разрешении перегрузки, если is_move_constructible_v<T> не является true.

Как я понимать удаленные конструкторы, целью не-удаления конструктора move std::optional<T> было бы разрешить такой код:

std::optional<X> o1;
std::optional<X> o2(std::move(o1));

... чтобы работать, опираясь на некоторую последовательность преобразований - o2 будет построен объектом типа A, который был построен с использованием std::optional<X>&& (исправьте меня, если я ошибаюсь).

Но о возможных конструкторах std::optional, я с трудом разбираюсь в том, что может соответствовать этому варианту использования...

Почему конструктор move std::optional<T> просто не удаляется, если T не может быть конструктивным?

Ответ 1

Чтобы явно удалить это означает, что это будет наилучшее соответствие для x-значения и, следовательно, приводят к ошибке времени компиляции, а не экземпляр-экземпляр принимает эти случаи.

Пример:

#include <utility>

struct X
{
    X() = default;
    X(const X&) = default;
    X(X&&) = delete;
};

int main()
{
    X a;
    X b(std::move(a));
}

Это приведет к чему-то вроде:

'X::X(X &&)': attempting to reference a deleted function

Явно удаленная функция все еще участвует в перегрузке разрешение, и может быть лучшим совпадением. Это может быть полезно, для отключения некоторых преобразований, например.

Ответ 2

Комитет действительно не заботится о скопированных, но не подвижных мерзостях. См., Например, обсуждение LWG issue 2768, в котором описываются такие типы, как "патологические" и более ранняя попытка поддержать его как "безумие",.

Стандартная формулировка такого рода вещей в общем случае "не участвует в разрешении перегрузки", если нет какой-либо конкретной причины для улавливания вызова (что иногда является подходящим - например, LWG issue 2766 - но может вызвать нежелательные побочные эффекты, такие как LWG issue 2993). Для специальных экземпляров копии, которые просто не могут быть выполнены до понятий, необходимо использовать "определяемые как удаленные". Для перемещения специальных членов OTOH, "определенный как удаленный", недостаточно точен, потому что существует огромная разница между "явно удаленным ходом" и "дефолтным движением, которое неявно определяется как удаленное": последний не участвует в разрешении перегрузки.

См. также обсуждение LWG-выпуск 2958.