2
template <typename InfoType>
class ObjPool {
public:
struct tag;
using size_type = unsigned;
using uid_type = IntWrapper<tag, size_type>;

uid_type add(InfoType&& newInfo) {
    if (removedUids_.size()) {
        uid_type reuse = removedUids_.back();
        removedUids_.pop_back();
        infos_[reuse] = newInfo;  // This line
        alive_[reuse] = true;
        ++size_;
        return reuse;
    }
    else {
        infos_.push_back(newInfo);
        alive_.push_back(true);
        ++size_;
        return uid_type(size_-1);
    }
}

// Other code
};

The compiler generates error:

object of type 'Graph::NodeInfo' cannot be assigned because its copy assignment operator is implicitly deleted infos_[reuse] = newInfo;

I don't quite understand why? I defined a move assignment and expect this line to call the move version rather than the copy version.

Why is

infos_[reuse] = std::move(newInfo);

necessary here?

Compiled with clang with c++11.

user69818
  • 403
  • 6
  • 13

1 Answers1

2

A named variable of rvalue reference type is an lvalue (thanks @M.M for the correction). It has a name and you can take its address, and it is pretty much identical to an lvalue reference. Since rvalue references can only bind to rvalues, the move assignment operator can't take a (named) rvalue reference. Calling std::move will make it an rvalue (specifically an xvalue) so that it will be passed to the move operator.

From cppreference:

Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression;

Weak to Enuma Elish
  • 4,622
  • 3
  • 24
  • 36
  • Thanks. So here newInfo is treated as a lvalue, then how about data members of newInfo? For instance, if `v` is a member of InfoType, is `newInfo.v` treated as rvalue or lvalue? – user69818 Feb 23 '16 at 03:22
  • 1
    You mean "The name of a variable declared with rvalue reference type is an lvalue" . Other rvalue references (e.g. that returned by `std::move)` are not lvalues – M.M Feb 23 '16 at 03:26
  • I am confused because, most examples with move constructors/assignment do not apply std::move on the members. – user69818 Feb 23 '16 at 03:29
  • @user69818 A member of an lvalue is also an lvalue (I am not aware of an instance where it wouldn't be) and a member of an rvalue is an xvalue. [Here](http://coliru.stacked-crooked.com/a/5c1f16b6e2f55e55) is a quick example to show it. Without `std::move` or the `static_cast`, it won't compile. – Weak to Enuma Elish Feb 23 '16 at 03:38
  • @JamesRoot I am so confused. Then why move constructor don't apply std::move at all? The move constructors examples in C++ primer and Stroustrups's book has no std::move on the move-from objects. – user69818 Feb 23 '16 at 03:50
  • Stroustrup page 515, the example below, for instance. – user69818 Feb 23 '16 at 03:52
  • Also here: http://stackoverflow.com/questions/6687388/why-do-some-people-use-swap-for-move-assignments – user69818 Feb 23 '16 at 03:53
  • @user69818 Well, I don't have that book on me, but you only need to move it if you're relying on a member's move semantics. Personally at least, in a move constructor I default construct the object and then swap with the argument, so I don't end up using `std::move`. – Weak to Enuma Elish Feb 23 '16 at 03:59
  • @JamesRoot This is just mysterious to me. None of the move constructor/assign examples in all the three books I have (Stroustrup, Professional C++, and C++ primer) use std::move when doing member-by-member assignment in the body of the move constructor/assignment. If they are just copying members, then what is the point of move constructor... – user69818 Feb 23 '16 at 04:03
  • @user69818 Maybe they wanted to ease the reader into move semantics. – Weak to Enuma Elish Feb 23 '16 at 04:08
  • @JamesRoot OK, I reread all the examples careful, and I figure that they don't use std::move, because the members are either pointers to dynamically allocated memory, or build-in types that only have copy assignments. None of the books explain why or give examples that do have std::move. This really causes a lot of confusion, which made me think std::move is not necessary. – user69818 Feb 23 '16 at 04:14