Reputation: 50548
For a feature request of a project of mine , I thought/I've been suggested to use std::launder
to move elements around in a vector where the elements are move constructible only (no move assignment operator defined).
The goal is to move the last element to a given position i
, then pop the former.
In other terms, the resulting code would be something like this (simplified version for the purpose):
void foo(std::vector<my_type> &vec, std::size_t i) {
my_type *el = vec.data() + i;
el->~my_type();
new (std::launder(el)) my_type{std::move(vec.back())};
vec.pop_back();
}
Where my_type
is defined as:
struct my_type { const int v; };
The purpose of using std::launder
is to set a barrier against the possible optimization due to the fact that v
within my_type
is const
. Therefore to be able to recycle the memory reserved for vec[i]
so as to replace the contained object with a different instance (actually, I'm theoretically moving the last item to a different position).
Is this a valid approach/solution or is this still UB, as it would happen if I did something similar without recurring to std::launder
?
As far as I understood it, the purpose of std::launder
is to allow users to do things like this one and thus it seems to me that the above snippet is legal. But I wouldn't be surprised if I was wrong, so I'd like to have a feedback by someone more experienced than me
--- EDIT
Similarly I want also to swap to elements of the same type.
The resulting code should be something like this:
const auto tmp = std::move(vec[i]);
vec[i].~object_type();
new (std::launder(&vec[i])) object_type{std::move(vec[j])};
vec[j].~object_type();
new (std::launder(&vec[j])) object_type{std::move(tmp)};
I'm quite confident that if std::launder
fits with the first example, this one should work as well for similar reasons. Am I wrong?
Upvotes: 1
Views: 266
Reputation: 137385
launder
gets you a pointer to an object that's already there.
There's no object there. You just destroyed it in the previous line.
Even the call to launder
itself is pure unadulterated UB.
For this kind of thing, launder
is needed when you access the newly created object. Not when you create it.
Upvotes: 4