Что мешало использовать конструктор перемещения для разрешения перегрузки, если это единственно возможное?

#c

#c

Вопрос:

Рассмотрим этот фрагмент: OnlyMoveable может быть создан только с помощью конструктора по умолчанию или операции перемещения.

В этом особом случае, по крайней мере для меня, кажется очевидным, что нет никакой двусмысленности и что построение k должно вызывать конструктор перемещения.

Почему автоматическое приведение ссылки на значение rvalue не входит в стандарт? Это сэкономило бы много «подробных» std::move при манипулировании типами только для перемещения.

Что было бы рискованным или неясным, если бы такое приведение было выполнено, когда двусмысленность была невозможна?

 struct OnlyMoveable {
    OnlyMoveable() {}

    OnlyMoveable(const OnlyMoveableamp; other) = delete;

    OnlyMoveable(OnlyMoveableamp;amp; other) {} 
};

void dummy ()
{ 

    OnlyMoveable defaultCtor;

    OnlyMoveable j(std::move(defaultCtor));

    OnlyMoveable defaultCtor2;
    // Do not compile, because attemps to call the copy ctor. Ok, but well, why the compiler in this special case where there is no
    // other overload than the move, can automitcally perform the rvalue reference cast ? 
    //OnlyMoveable k(defaultCtor2);
};
 

Ответ №1:

Без существования конструктора копирования эта инициализация не будет компилироваться:

 OnlyMoveable k(defaultCtor2); // error
 

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

Конечно, как программист, если вы знаете, что вам больше никогда не понадобится использовать defaultCtor2 , или, по крайней мере, вы не будете читать его значение, вы можете использовать явное std::move указание компилятору использовать конструктор перемещения:

 OnlyMoveable k(std::move(defaultCtor2)); // ok
 

Комментарии:

1. Согласен, но в то же время в C уже есть много вещей, которые, по крайней мере, столь же «опасны», как это (захват лямбды для каждой ссылки, неявные вызовы конструктора, невиртуальный деструктор в базовом классе, виртуальные функции, которые не работают, если вызываются во время ctor — список не является исчерпывающим … )

2. @sandwood Это правда. Вы предполагаете, что, поскольку язык позволяет вам делать другие опасные вещи, он должен разрешать все опасные вещи?

3. Не совсем. Мой вопрос был действительно, есть ли другая вещь (тогда потенциально опасный код ..), Которая предотвратила бы автоматическое приведение значения rvalue .

4. Ну, это языковые правила, которые предотвращают это, но я считаю, что мотивация, по крайней мере частично, заключается в том, чтобы не допускать опасный код.