为什么std::allocator 要求propagate_on_container_move_assignment 为真?

use*_*538 4 c++ allocator c++11

根据当前标准 (20.7.9),std::allocator有一个成员propagate_on_container_move_assignment设置为true_type

模板类分配器
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* 指针;
typedef const T* const_pointer;
typedef T&参考;
typedef const T& const_reference;
typedef T value_type;
模板结构重新绑定 { typedef 分配器其他;};
typedef true_typepropagate_on_container_move_assignment;
typedef true_type is_always_equal;
[...]

std::allocator没有数据成员,并且总是与任何其他std::allocator. 是否有任何理由在移动分配时移动这些默认分配器?

Ker*_* SB 5

正如您在标签中指出的那样,我正在回答相对于 C++11 的问题:

如果特征不为真,则赋值操作将需要对分配器是否相等执行运行时检查。是的,当然分配器总是相等的,但是代码不知道这一点并且仍然必须执行检查,因此您不能提供 noexcept 保证。使用 POCMA = true,您可以静态地知道您将窃取资源,因此不会抛出。

C++14 使std::allocator有 POCMA = true(在LWG2103 中)。在 C++11 中是错误的。

C++17 引入了新特性is_always_equal(在N4258 中),即使在 POCMA 为 false 时,也允许操作的非抛出异常规范。

(我认为公平地说分配器的设计从未完全完成,直到今天,没有人完全确定它们应该如何工作。)

  • @Oliv 可以使用 constexpr `operator==`,并在 [lwg 2108](https://cplusplus.github.io/LWG/lwg-defects.html#2108) 中进行了讨论。要使用它,您需要在 SFINAE 上下文中尝试相等比较,以查看它是否是有效的常量表达式(因为并非所有分配器都具有 constexpr `operator==`)。标签调度更简单。死代码消除仍然适用于始终返回 true 的非 constexpr `operator==`。在实践中它没有太大区别。 (2认同)