I was wondering what went wrong in having a r-reference return type like:
vector<T>&& id2(vector<T>&& v) { return std::move(v);}
as in the code below. Doing a = id2(a)
sets empty. The other version id
returning the normal type is OK.
I heard this has something to do with self-move assignment. But I only have a basic knowledge about move semantics, and I don't understand the cryptic language in the answer there quoted from the standards. Can someone please explain this in common-sense/layman's language?
If I take a temporary a
, reap out its content and return the content as a temporary to be assigned back to a
, why should a
be cleared or undefined?
#include <vector>
#include <iostream>
using namespace std;
template <class T>
vector<T> id(vector<T>&& v) { return std::move(v); }
template <class T>
vector<T>&& id2(vector<T>&& v) { return std::move(v);}
int main() {
vector<int> a;
a.resize(3,1);
a = id(std::move(a));
cout << a.size() << endl; //output: 3
a.resize(3,1);
a = id2(std::move(a));
cout << a.size() << endl; //output: 0
}
Thanks,
-- Update ---
If I am reading the said duplicate post, the second example there quoted below was about passing r-ref to a local variable outside a function, which is an error anyway regardless of this is a r-ref or l-ref. I don't think that's quite the same as my example. If you use left reference instead of r-ref in my example, it would have worked. Am I missing something on this?
std::vector<int>&& return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector<int> &&rval_ref = return_vector();
--- Update 2 ---
@pradhan. It seems that the issue boils down to self-move assignment. Regarding the library choice of behavior on self-move assignment for standard containers, this is what bothers me. If you do a self-assign of std::vector
in the old fashion, it's perfectly fine, but when you self-move assign, it's undefined behavior. Unless there is something inherently wrong, is it more natural (backward compatible) to have standard containers allow self-move assign as with self-assign?
#include <vector>
#include <iostream>
int main() {
std::vector<int>a{1,2,3};
a = a;
std::cout << a.size() << std::endl; //output: 3
a = std::move(a);
std::cout << a.size() << std::endl; //output: 0
}