为什么' boost::container::flat_set '不是' nothrow_move_constru

Why is `boost::container::flat_set` not `nothrow_move_constructible`?

本文关键字:nothrow constru 不是 move container boost 为什么 flat set      更新时间:2023-10-16

我正在编写一些代码,该代码具有一个通用容器,要求元素为nothrow_move_constructible

我决定添加一个static_assert来强制执行,以防万一。

令我惊讶的是,我现在不能编译时使用boost::container::flat_set

我以为这只是一个疏忽,我需要一个最近的增强版本,但似乎实际上他们故意使它不安全移动:

查看文档:

http://www.boost.org/doc/libs/1_61_0/doc/html/boost/container/flat_set.html

您可以看到他们确实更新了它以使用r值引用并将swap标记为noexcept,但他们选择不使移动向量noexcept。看起来move赋值是有条件的noexcept。该条件似乎在某种程度上取决于值类型和分配器。

nothrow move不可构造的基本原理是什么?这只是一个疏忽吗?

如果容器中的对象不是nothrow_move_constructible,那么在某些情况下(通常涉及分配器),将一个容器的整个集合重新定位到另一个容器是非常危险的。如果两个容器不是用相同的分配器构造的,那么将内存从一个容器移动到另一个容器是不安全的(想想来自两个不同内存领域的两个容器)。

深入到当前源,合约和实现都有问题:

//! <b>Effects</b>: Move constructs a flat_map.
//!   Constructs *this using x's resources.
flat_map(BOOST_RV_REF(flat_map) x)
    : m_flat_tree(boost::move(x.m_flat_tree))
{ ... }

所以你当前对nothrow的期望是正确的。但是他们这样做可能是不对的。

我只能猜测他们担心将来不得不重新访问这个协议,并且不想以后不得不削弱nothrow合约。