I have the following factory function:
auto factory() -> std::tuple<bool, std::vector<int>>
{
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
return { true, vec };
}
auto [b, vec] = factory();
In the return statement is vec
considered an xvalue
or prvalue
and therefore moved or copy elided?
My guess is no, because the compiler, when list-initializing the std::tuple
in the return statement, still doesn't know that vec is going to be destroyed. So maybe an explicit std::move is required:
auto factory() -> std::tuple<bool, std::vector<int>>
{
...
return { true, std::move(vec) };
}
auto [b, vec] = factory();
Is it that really required?
In the return statement is
vec
considered an xvalue or prvalue and therefore moved or copy elided?
vec
is always an lvalue. Even in the simple case:
std::vector<int> factory() {
std::vector<int> vec;
return vec;
}
That is still returning an lvalue. It's just that we have special rules that say that we just ignore the copy in this case when we're returning the name of an automatic object (and another special rule in the case that copy elision doesn't apply, but we still try to move from lvalues).
But those special rules only apply to the return object;
case, they don't apply to the return {1, object};
case, no matter how similar it might look. In your code here, that would do a copy, because that's what you asked for. If you want to do a move, you must do:
return {1, std::move(object)};
And in order to avoid the move, you must do:
auto factory() -> std::tuple<bool, std::vector<int>>
{
std::tuple<bool, std::vector<int>> t;
auto& [b, vec] = t;
b = true;
vec.push_back(1);
vec.push_back(2);
return t;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With