gpt4 book ai didi

c++ - 标准容器元素类型和std::allocator类型不一样是不是错了?

转载 作者:可可西里 更新时间:2023-11-01 15:53:32 27 4
gpt4 key购买 nike

取自here (很旧):

It's also important that the type used for the allocator template parameter and the type used as the element type in a standard container agree. For instance:

std::list<int, std::allocator<long> >                    // Wrong!

won't work.

问题

以上说法是否正确(或曾经正确过)?无论我为 T 设置什么,我所做的任何测试似乎都可以正常工作在std::allocator .例如,std::vector<int, std::allocator<std::string>>编译和工作正常推回和删除元素等。(据我所知,std::allocator<std::string>::rebind<int>::other 是使这项工作发挥作用的魔法)。

最佳答案

我在这里添加一个答案来澄清格式错误和未定义行为之间的区别。

[intro.compliance]/p1:

The set of diagnosable rules consists of all syntactic and semantic rules in this International Standard except for those rules containing an explicit notation that “no diagnostic is required” or which are described as resulting in “undefined behavior.”

[defns.ill.formed]:

program that is not well formed

[defns.well.formed]

C++ program constructed according to the syntax rules, diagnosable semantic rules, and the One Definition Rule (3.2).

在英语中:格式错误的程序应具有与之关联的诊断。未定义的行为可以做任何事情:

  1. 它可以按照您的预期进行编译和执行。
  2. 它可以发出诊断。
  3. 它可以删除您编写的代码。
  4. 它可以重新格式化最近的磁盘。

(除了第 4 个在实践中经常发生)

未定义的行为非常糟糕,恕我直言,C 和 C++ 标准过于宽松地应用了该规范。

从技术上讲,违反 Requires 子句会导致未定义的行为。

[res.on.required]/p1:

Violation of the preconditions specified in a function’s Requires: paragraph results in undefined behavior unless the function’s Throws: paragraph specifies throwing an exception when the precondition is violated.

如 MSN 所述,allocator_type::value_type 应与表 99 中所述的 container::value_type 相同 -- Allocator-aware container requirements .

allocator_type A       Requires:  allocator_type::value_type 
is the same as X::value_type.

(X 表示使用 A 类型分配器的 value_typeT 的分配器感知容器类)

因此违规行为例如:

std::list<int, std::allocator<long> >  

是未定义的行为。所以它:

  1. 可以按照您的预期进行编译和执行。
  2. 可以发布诊断。
  3. 可以删除你写的代码。
  4. 可以重新格式化最近的磁盘。

就在最近(在我写这篇文章的几周内),libc++ ( http://libcxx.llvm.org ) 已经开始使用 static_assert 诊断这种未定义的行为,以便您尽快得到坏消息。

我们决定朝这个方向发展,而不是允许这种行为,因为容器没有设置为允许在密切相关的类型之间进行转换。例如:

std::list<int, std::allocator<long>>  list1;
std::list<int> list2 = list1; // is specified to not work

即如果您开始将 list1list2 视为等效类型,因为 std::allocator 无论如何都会得到 rebind,当您发现这两个列表实际上是不同的类型并且无论如何都不能互操作时,您将会感到失望。因此,当您尝试将它们用作等效类型时,最好尽快得到坏消息,而不是在 2 个月或 2 年后才发现。

也许 future 的标准会将 list1list2 视为等效类型。这在技术上几乎是可行的(std::is_same 可能行不通)。但是我没有听说过这方面的提议。这个方向对我来说似乎不太可能。使用 static_assert,错误很容易诊断。相反,我希望看到标准朝着使此代码格式错误而不是未定义的方向发展。这样做最困难的部分是对标准进行文字加工,而不是在 std::lib 实现中。

关于c++ - 标准容器元素类型和std::allocator类型不一样是不是错了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17957366/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com