这个扩展的动机,可以被符合标准的程序检测到,因此是不符合标准的,是为了让vector<bool>
行为更像vector<char>
引用(const 和其他)。
介绍
自1998年以来,vector<bool>
一直被嘲笑为“不完全是容器”。 LWG 96是最早的 LWG 问题之一,引发了辩论。17 年后的今天,vector<bool>
基本保持不变。
本文介绍了一些具体示例,说明 的行为vector<bool>
与 的所有其他实例有何不同vector
,从而损害了通用代码。然而,同一篇论文详细讨论了vector<bool>
如果正确实施可以具有的非常好的性能属性。
摘要: vector<bool>
不是一个坏容器。它实际上非常有用。它只是有一个坏名声。
回到const_reference
如上所述,这里详细介绍,不好vector<bool>
的是它在泛型代码中的行为与其他vector
实例不同。这是一个具体的例子:
#include <cassert>
#include <vector>
template <class T>
void
test(std::vector<T>& v)
{
using const_ref = typename std::vector<T>::const_reference;
const std::vector<T>& cv = v;
const_ref cr = cv[0];
assert(cr == cv[0]);
v[0] = 1;
assert(true == cv[0]);
assert(cr == cv[0]); // Fires!
}
int
main()
{
std::vector<char> vc(1);
test(vc);
std::vector<bool> vb(1);
test(vb);
}
标准规范说,标记的断言// Fires!
将触发,但仅在test
使用vector<bool>
. 当使用 a 运行时vector<char>
(或分配适当的非默认值时vector
除外),测试通过。bool
T
libc++ 实现试图将vector<bool>
在通用代码中表现不同的负面影响最小化。它为实现这一目标所做的一件事是创建 vector<T>::const_reference
一个proxy-reference,就像指定的一样vector<T>::reference
,只是您不能通过它进行分配。也就是说,在 libc++ 上,vector<T>::const_reference
本质上是指向 . 中的位的指针vector
,而不是该位的副本。
在 libc++ 上,上述test
通行证适用于vector<char>
和vector<bool>
。
以什么代价?
缺点是这个扩展是可检测的,如问题所示。然而,很少有程序真正关心这个别名的确切类型,更多的程序关心行为。
这种不符合的动机是什么?
为了在通用代码中为 libc++ 客户端提供更好的行为,也许在经过充分的现场测试之后,建议将此扩展扩展到未来的 C++ 标准,以改善整个 C++ 行业。
这样的提议可能会以新容器的形式出现(例如bit_vector
),它具有与今天的 API 大致相同的 API vector<bool>
,但有一些升级,例如const_reference
这里讨论的。随后是vector<bool>
专业化的弃用(并最终删除)。 bitset
也可以在这个部门使用一些升级,例如 addconst_reference
和一组迭代器。
也就是说,事后看来bitset
是 to vector<bool>
(应该重命名为bit_vector
-- 或其他),就像array
to一样vector
。无论我们是否在谈论 and ,这个类比都bool
应该value_type
成立。vector
array
有多个 C++11 和 C++14 功能示例,它们最初是作为 libc++ 中的扩展。这就是标准的演变方式。实际展示 的积极现场经验具有强大的影响力。在更改现有规范(应该如此)时,标准人员是一群保守的人。猜测,即使你确定你的猜测是正确的,也是发展国际公认标准的冒险策略。