C++ std::launder、std::vector和move仅可构造类型

C++ std::launder、std::vector和move仅可构造类型,c++,constants,c++17,C++,Constants,C++17,一段时间以来,我认为/我被建议使用std::launder在向量中移动元素,其中元素仅可移动构造(未定义移动赋值运算符)。 目标是将最后一个元素移动到给定位置i,然后弹出前一个元素 换句话说,生成的代码类似于以下内容(简化版): 使用std::launder的目的是设置一个障碍,防止可能的优化,因为my_type中的v是const。因此,为了能够回收为vec[i]保留的内存,以便用不同的实例替换包含的对象(实际上,理论上,我正在将最后一项移动到不同的位置) 这是一种有效的方法/解决方案,还是像我

一段时间以来,我认为/我被建议使用
std::launder
在向量中移动元素,其中元素仅可移动构造(未定义移动赋值运算符)。
目标是将最后一个元素移动到给定位置
i
,然后弹出前一个元素

换句话说,生成的代码类似于以下内容(简化版):

使用
std::launder
的目的是设置一个障碍,防止可能的优化,因为
my_type
中的
v
const
。因此,为了能够回收为
vec[i]
保留的内存,以便用不同的实例替换包含的对象(实际上,理论上,我正在将最后一项移动到不同的位置)

这是一种有效的方法/解决方案,还是像我在不重复使用
std::launder
的情况下做了类似的事情那样仍然是UB

据我所知,
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
符合第一个示例,那么出于类似的原因,这个示例也应该适用。我错了吗?

launder
获取指向已存在对象的指针

那里没有物体。你刚才在前一行把它毁了

甚至对
launder
本身的调用也纯粹是纯粹的泛白


对于这种情况,当您访问新创建的对象时,需要使用
launder
。当你创建它的时候就不会了。

launder
会给你一个指向已经存在的对象的指针

那里没有物体。你刚才在前一行把它毁了

甚至对
launder
本身的调用也纯粹是纯粹的泛白


对于这种情况,当您访问新创建的对象时,需要使用
launder
。当你创建它时就不会了。

这很有意义。如果
T
不是简单的可破坏的,并且
T
在可能的情况下是不可移动的,那么我如何将最后一个实例移动到位置
I
。如果
T
不是可破坏的,并且
T
在可能的情况下不可移动分配,那么我如何将最后一个实例移动到位置
I
,因此,目前很难说有标准的方法来实现您的目标。对于元素包含常量/引用成员的容器,有一些尚未解决,因此目前很难说有标准的方法来实现您的目标。
struct my_type { const int v; };
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)};