【问题标题】:Why does std::allocator require propagate_on_container_move_assignment to be true?为什么 std::allocator 要求propagate_on_container_move_assignment 为真?
【发布时间】:2017-06-22 10:59:45
【问题描述】:

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

模板类分配器
{
公开:
typedef size_t size_type;
typedef ptrdiff_t 差异类型;
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 进行比较。是否有任何理由在移动分配时移动这些默认分配器?

【问题讨论】:

  • 这不是 C++11。 is_always_equal 是在 C++14 之后添加的。

标签: c++ c++11 allocator


【解决方案1】:

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

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

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

C++17 引入了新的 trait is_always_equal(在 N4258 中)以允许在 POCMA 为 false 的情况下对操作进行非抛出异常规范。

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

【讨论】:

  • 之所以做成 POCMA,是因为它影响了对容器元素的要求,而不仅仅是异常规范。如果没有 POCMA(或 is_always_equal),您必须考虑元素移动的可能性。
  • 我有一个必然的问题:为什么不定义一个 constexpr operator==?为什么这个 pocma 是必要的。我想如果我使用这样的运算符作为 if 语句的条件,那么死代码消除将产生与我使用 POCMA no 的标签调度相同的代码?
  • @Oliv A constexpr operator== 是可能的,并在lwg 2108 中讨论。要使用它,您需要在 SFINAE 上下文中尝试相等比较,以查看它是否是有效的常量表达式(因为并非所有分配器都有 constexpr operator==)。标签调度更简单。死代码消除仍然适用于始终返回 true 的非 constexpr operator==。在实践中并没有太大的区别。
  • @JonathanWakely 谢谢你的回答。我想分享一些平静的实验。一段时间以来,我习惯于使用概念 TS 进行编程并使用它,我发现我的大部分设计决策都是出于我不得不使用和维护使用 SFINAE 代码的困难的动机。在 STL 中似乎就是这种情况。我已阅读标准 N4618:“is_always_equal:true_type 仅当表达式 a1 == a2 保证对任何两个都为真时……”。这是对分配器程序员的不必要的约束传播。这个要求可以是硬编码的。为什么不硬编码呢?
  • @Oliv 我不明白这个问题(为分配器定义using is_always_equal = true_type; 确实 对其进行硬编码),但我认为它不属于此处的评论。 StackOverflow cmets 不用于讨论。坚持这个答案的主题。如果您有任何问题,请提出新问题。
猜你喜欢
  • 2019-08-22
  • 1970-01-01
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 2022-03-27
  • 2019-02-25
  • 2016-09-07
相关资源
最近更新 更多