这个扩展的动机,可以被符合标准的程序检测到,因此是不符合标准的,是为了让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除外),测试通过。boolT
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-- 或其他),就像arrayto一样vector。无论我们是否在谈论 and ,这个类比都bool应该value_type成立。vectorarray
有多个 C++11 和 C++14 功能示例,它们最初是作为 libc++ 中的扩展。这就是标准的演变方式。实际展示 的积极现场经验具有强大的影响力。在更改现有规范(应该如此)时,标准人员是一群保守的人。猜测,即使你确定你的猜测是正确的,也是发展国际公认标准的冒险策略。