Для запроса объекта из моего проекта я подумал / мне предложили использовать std::launder
для перемещения элементов в векторе, где элементы перемещаютсятолько конструируемые (оператор заданного перемещения не определен).
Цель состоит в том, чтобы переместить последний элемент в заданную позицию i
, а затем вытолкнуть первый.
Другими словами, полученный код будет чем-токак это (упрощенная версия для этой цели):
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();
}
Где my_type
определяется как:
struct my_type { const int v; };
Цель использования std::launder
состоит в том, чтобы установить барьер противвозможная оптимизация из-за того, что v
в пределах my_type
составляет const
.Следовательно, чтобы иметь возможность перерабатывать память, зарезервированную для vec[i]
, чтобы заменить содержащийся объект другим экземпляром (фактически, я теоретически перемещаю последний элемент в другую позицию).
Это правильный подход / решение или это все еще UB, как это было бы, если бы я сделал что-то подобное, не возвращаясь к std::launder
?
Насколько я понял, цель std::launder
позволяет пользователям делать подобные вещи, и поэтому мне кажется, что приведенный выше фрагмент кода является законным.Но я не удивлюсь, если я ошибаюсь, поэтому я хотел бы получить отзыв от кого-то более опытного, чем я
--- РЕДАКТИРОВАТЬ
Точно так жеЯ также хочу поменять на элементы того же типа.
Полученный код должен выглядеть примерно так:
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)};
Я вполне уверен, что если std::launder
подойдетс первым примером этот также должен работать по аналогичным причинам.Я не прав?