Can an operator recognize rvalues?
I have an STL container type T
, say template< typename F > using T = std::vector< F >;
. I want to write the following code:
typedef std::string F;
T< F > v(2, "a"), w(3, "b");
v += std::move(w);
std::cout << "v : ";
std::copy(std::begin(v), std::end(v), std::ostream_iterator< F >(std::cout, "|"));
std::cout << std::endl << "w : ";
std::copy(std::begin(w), std::end(w), std::ostream_iterator< F >(std::cout, "|"));
std::cout << std::endl;
and get the result:
v : a|a|b|b|b|
w : |||
those. I want to append all the content of the source w
to the end of the target v
using " std::move
-ing" (as one from <utility>
one by one or from <algorithm>
across a range) so that all the original elements are left empty and it just needs a call w.clear();
.
Is it possible to force the operator to recognize an rvalue reference? Say:
T & ::operator += (T &, T &&);
Or is there something else I need?
source to share
Yes it will work, but T
it is not a type, so you cannot write a statement like this. T
is a template, so the operator should be something like
template<typename U>
T<U>& operator+=(T<U>&, T<U>&&);
Possible implementation:
template<typename U>
T<U>& operator+=(T<U>& lhs, T<U>&& rvalue)
{
std::move(rvalue.begin(), rvalue.end(), std::back_inserter(lhs));
rvalue.clear();
return lhs;
}
And overloaded for lvalues:
template<typename U>
T<U>& operator+=(T<U>& lhs, const T<U>& lvalue)
{
std::copy(lvalue.begin(), lvalue.end(), std::back_inserter(lhs));
return lhs;
}
To make this work with any type (I find it a bad idea, it should be limited to only the appropriate types) try this:
template< class T, class U >
inline
typename std::enable_if< std::is_lvalue_reference< U >::value, T& >::type
operator += (T& lhs, U&& lvalue)
{ /* copy from lvalue */ }
template< class T, class U >
inline
typename std::enable_if< !std::is_lvalue_reference< U >::value, T& >::type
operator += (T& lhs, U&& rvalue)
{ /* move from rvalue */ }
source to share