With reference to C++ Annotations, to call outer(outer&& rhs)
, one would use the code:
outer out((outer)outer()/*0*/)/*1*/;
Which at 0 constructs an anonymous object of type outer, and at 1 it constructs an object of type outer with the name out. (The (outer)
is there to prevent out
form being an outer(outer (*)())
)
See the anonymous there? Now consider the definition of outer(outer&& rhs):
outer(outer && rhs) : m_inner(rhs.m_inner) {}
outer(outer &&)
has 1 argument of type outer &&
named rhs.
Now, there is a perceivable difference between the statement 0 in ex. 1 and the first parameter: the former doesn't have a name, the latter does, hence removing the anonimity of the object. Now since the object has a name it is just a lvalue reference (which allows people to use a construct-by-swap idiom).
The problem arises, though, when someone needs to use it as a rvalue reference. For that the
template<class T>
typename std::remove_reference<T>::type&& move(T&& t);
function was created. What's it do? It "obtains an rvalue reference to its argument and converts it to an xvalue" (more on all sorts of values here), which is exactly what we need! So, the final code could be:
#include <utility>
class outer {
class inner {
public:
inner() {}
inner(inner && rhs) {}
};
public:
outer() {}
outer(outer && rhs) : m_inner(std::move(rhs.m_inner)) {}
private:
inner m_inner;
};
Note the #include <utility>
and std::move()
call.