Скажем, у меня есть (тривиальный) класс, который можно конструировать с помощью перемещения и назначать с помощью перемещения, но нельзя создать с помощью копирования или назначить с помощью копирования:
class movable
{
public:
explicit movable(int) {}
movable(movable&&) {}
movable& operator=(movable&&) { return *this; }
movable(const movable&) = delete;
movable& operator=(const movable&) = delete;
};
Это отлично работает:
movable m1(movable(17));
Это, конечно, не работает, потому что m1
не является rvalue:
movable m2(m1);
Но я могу обернуть m1
в std::move
, что приводит его к ссылке rvalue, чтобы заставить его работать:
movable m2(std::move(m1));
Все идет нормально. Теперь предположим, что у меня есть (столь же тривиальный) класс-контейнер, который содержит одно значение:
template <typename T>
class container
{
public:
explicit container(T&& value) : value_(value) {}
private:
T value_;
};
Однако это не работает:
container<movable> c(movable(17));
Компилятор (я пробовал clang 4.0 и g++ 4.7.2) жалуется, что я пытаюсь использовать удаленный конструктор копирования movable
в списке инициализации container
. Опять же, обертывание value
в std::move
заставляет его работать:
explicit container(T&& value) : value_(std::move(value)) {}
Но зачем в этом случае std::move
? Разве value
уже не относится к типу movable&&
? Чем value_(value)
отличается от movable m1(movable(42))
?
T&&
является lvalue, тогда как безымянное значение того же типа является rvalue. - person avakar   schedule 30.10.2012value
— выражение lvalue. - person Joseph Mansfield   schedule 30.10.2012