[英]Is it wrong if the standard container element type and std::allocator type are different?
Take from here (which is quite old): 从这里开始 (这是相当古老的):
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.
用于allocator模板参数的类型和用作标准容器中的元素类型的类型一致也很重要。 For instance:
例如:
std::list<int, std::allocator<long> > // Wrong!
won't work.
不行。
Question 题
Is the above statement correct (or was it ever correct)? 以上陈述是否正确(或者是否正确)? Any tests I have done seem to work fine no matter what I put for
T
in std::allocator
. 无论我在
std::allocator
为T
做什么,我所做的任何测试似乎都能正常工作。 For example, std::vector<int, std::allocator<std::string>>
compiled and worked fine pushing back and erasing elements, etc. (From what I understand std::allocator<std::string>::rebind<int>::other
is the magic that makes this work). 例如,
std::vector<int, std::allocator<std::string>>
编译并正常工作推回和擦除元素等(根据我的理解std::allocator<std::string>::rebind<int>::other
是使这项工作变得神奇的魔力。
I'm adding an answer here to clarify the difference between ill-formed and undefined behavior. 我在这里添加一个答案,以澄清不良行为和未定义行为之间的区别。
[intro.compliance]/p1: [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]: [defns.ill.formed]:
program that is not well formed
程序不完善
[defns.well.formed] [defns.well.formed]
C++ program constructed according to the syntax rules, diagnosable semantic rules, and the One Definition Rule (3.2).
C ++程序根据语法规则,可诊断语义规则和单定义规则(3.2)构建。
In English: an ill-formed program shall have a diagnostic associated with it. 在英语中:不正确的程序应具有与之相关的诊断。 Undefined behavior can do anything:
未定义的行为可以做任何事情:
(all but the 4th routinely happen in practice) (除了第4次以外通常都会在实践中发生)
Undefined behavior is very bad, and imho, the C and C++ standards apply that specification much too liberally. 未定义的行为非常糟糕,而imho,C和C ++标准过于宽松地应用了该规范。
Technically, violating a Requires clause results in undefined behavior. 从技术上讲,违反Requires子句会导致未定义的行为。
[res.on.required]/p1: [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.
违反函数的Requires:段中指定的前提条件会导致未定义的行为,除非函数的Throws:paragraph指定在违反前提条件时抛出异常。
As noted by MSN, allocator_type::value_type
shall be the same as container::value_type
as stated in Table 99 -- Allocator-aware container requirements . 如MSN所述,
allocator_type::value_type
应与表99中所述的container::value_type
相同 - 可识别分配器的容器要求 。
allocator_type A Requires: allocator_type::value_type
is the same as X::value_type.
( X
denotes an allocator-aware container class with a value_type
of T
using allocator of type A
) (
X
表示一个分配器感知容器类,其value_type
为T
使用类型A
分配器)
So a violation such as: 所以违反如下:
std::list<int, std::allocator<long> >
is undefined behavior. 是未定义的行为。 So it:
所以:
Just very recently (within weeks of me writing this), libc++ ( http://libcxx.llvm.org ) has started diagnosing this undefined behavior with static_assert
so that you get the bad news asap. 就在最近(在我写这篇文章的几周内),libc ++( http://libcxx.llvm.org )已经开始用
static_assert
诊断这个未定义的行为,以便你尽快得到坏消息。
We decided to go this direction, instead of allowing the behavior because the containers are not set up to allow conversions among closely related types. 我们决定采用这个方向,而不是允许行为,因为容器没有设置为允许密切相关类型之间的转换。 For example:
例如:
std::list<int, std::allocator<long>> list1;
std::list<int> list2 = list1; // is specified to not work
Ie if you start treating list1
and list2
as equivalent types because the std::allocator
gets rebind
'd anyway, you're going to get disappointed down the road as you discover the two lists are really different types and not designed to interoperate anyway. 即如果你开始将
list1
和list2
视为等效类型,因为std::allocator
无论如何都会rebind
,当你发现这两个列表实际上是不同的类型并且无论如何都不能进行互操作时,你会感到很失望。 So it is really best to get the bad news asap, instead of finding out 2 months, or 2 years later, when you try to use them as equivalent types. 所以最好尽快得到坏消息,而不是在2个月或2年之后发现,当你尝试将它们用作等效类型时。
Perhaps a future standard will treat list1
and list2
as equivalent types. 也许未来的标准会将
list1
和list2
视为等效类型。 It is mostly technically possible ( std::is_same
would likely not work). 它在技术上大多数可能(
std::is_same
可能不起作用)。 But there are no proposals that I've heard of in this direction. 但是我没有听到过这方面的建议。 This direction does not seem likely to me.
这个方向对我来说似乎不太可能。 And with
static_assert
, the error is easily diagnosable. 使用
static_assert
,错误很容易被诊断出来。 Instead I would like to see the standard move in the direction of making this code ill-formed instead of undefined. 相反,我希望看到标准的方向是使这个代码形成错误而不是未定义。 The hardest part in doing so would be word-smithing the standard, and not in the std::lib implementation.
这样做最困难的部分是字标准,而不是std :: lib实现。
EDIT: In [containers.requirements.general], the Allocator-aware container requirements indicate that the allocator_type::value_type
is the same as Container::value_type
. 编辑:在[containers.requirements.general]中,Allocator感知容器要求表明
allocator_type::value_type
与Container::value_type
相同。
So it's ill formed to pass in an allocator type with a different value_type
, although at least one implementation simply uses allocator_traits<...>::rebind<value_type>
to get the correct allocator. 因此,传入具有不同
value_type
的allocator类型是value_type
,尽管至少有一个实现只使用allocator_traits<...>::rebind<value_type>
来获取正确的分配器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.