Подтвердить что ты не робот

Переместить постоянный объект без предупреждения компилятора

Я тестировал следующий код с помощью Visual Studio 2017 версии 15.3.1.

v.push_back(std::move(str1)) работает так, как ожидалось. Он перемещает содержимое str1 в вектор.

str2 - постоянная строка. Поскольку постоянная строка не может быть изменена после ее создания, я ожидал, что оператор v.push_back(std::move(str2)) приведет к предупреждению компилятора. Однако, к моему удивлению, предупреждения компилятора не было. После этого я обнаружил, что перегрузка push_back(const T&) была фактически вызвана. std::move в std::move(str2) кажется, не имеет никакого эффекта.

Мой вопрос: Следует ли предупреждать компилятора о попытке перемещения постоянного объекта?

// Compiled with Visual Studio 2017 version 15.3.1
std::vector<std::string> v;

std::string str1 = "string 1";
v.push_back(std::move(str1));
// Call push_back(T&&). The contents of str1 is moved into the vector.
// This is less expensive, but str1 is now valid but unspecified.

const std::string str2 = "string 2";
v.push_back(std::move(str2));
// Call push_back(const T&). A copy of str2 is added into the vector.
// str2 itself is unchanged.
4b9b3361

Ответ 1

Нет. Помните, std::move ничего не двигает, это прославленный бросок через remove_reference_t. Так как в вашем случае он заносится в ссылку const rvalue (как std::remove_reference_t<const T> is const T), он не связывается с rvalue reference overload push_back(T&& ) и вместо этого связывается с константой lvalue reference one - push_back(const T& ).

Ответ 2

Существует простой способ предотвратить молчание move-from-const: просто удалите его.

#include <type_traits>
#include <string>

//Copy this line into your global header
template<class T> void move (const T& arg) = delete; //ADL

int main()
{
    {
        std::string str;
        std::string str2 = move(str);
    }

    {
        //error
        //const std::string str;
        //std::string str2 = move(str);
    }
}