Reputation: 14583
For example, if I have a function:
struct my_type {
void add(some_type st) {
values_.emplace_back(
std::move(st)
);
}
vector<some_type> values_;
};
And I call the member:
int main() {
my_type mt;
some_type st;
mt.add(std::move(st));
}
I've moved st into the argument for add, which them just turns right around and moves it into a container it's managing.
This turns up quite a lot where I've got wrapper around some underlying container.
Does the C++ language allow/require some optimization of this "double move" pattern? Or should I be writing separate lvalue and rvalue add functions?
Upvotes: 1
Views: 422
Reputation: 275585
A move is a cast to an rvalue reference.
What that does depends on what function or ctor you pass it to.
In your case, it depend on what some_type
does when you construct an instance from a some_type&&
.
That is literaly arbitrary code that you haven't included.
If some_type
is written with a simple and efficient move ctor, and it doesn't leak its identity, under as-if the intermediate instance could be eliminated. On the other hand, if some_type
leaks identity or does other similar and/or bad things, the intermediate object may have to practically exist.
As an example, a std::vector
as some_type
could probably be eliminated; and if not, you wouldn't care, as a move is 3 pointers copied and zeroed. A type that prints its address when copied to std err, probably not.
There is currently nothing similar to elision that allows lifetime merging despite side effects. There have been some proposals along that direction, but I am unaware of any getting far (which mostly is evidence of my ignorance, not evidence of lack of existence), and I doubt they cover this case.
If you don't know what elision is, you should go learn; you need new vocabulary before you can discuss this issue practically. Talking about this issue in C++ without understanding C++ elision is like discussing e^(ipi)+1=0 with someone who doesn't know what multiplication is. Possible, but long winded.
Upvotes: 1