为什么libc ++的vector <bool> :: const_reference不是bool?
第23.3.7节类vector<bool>
[vector.bool]第1段规定:
template <class Allocator> class vector<bool, Allocator> { public: // types: typedef bool const_reference; ...
但是,使用libc ++时,该程序无法编译:
#include <vector> #include <type_traits> int main() { static_assert(std::is_same<std::vector<bool>::const_reference, bool>{}, "?"); }
此外,我注意到C ++标准在本规范中始终与C ++ 98保持一致。 而且我还注意到自libc ++第一次引入以来,libc ++始终没有遵循这个规范。
这种不合格的动机是什么?
这个扩展的动机可以通过一致性程序来检测,因此不符合,就是使vector<bool>
对于引用(const和otherwise)的行为更像vector<char>
。
介绍
自1998年以来, vector<bool>
被嘲笑为“不是一个容器”。 LWG 96是LWG最早的问题之一,发起了辩论。 17年后的今天, vector<bool>
大体上保持不变。
本文将介绍vector<bool>
与vector
每个实例的不同之处,从而影响generics代码。 然而,同样的文章详细讨论了如果正确实现,非常好的性能属性vector<bool>
。
总结 : vector<bool>
不是一个糟糕的容器。 这实际上非常有用。 它只是一个坏名字。
回到const_reference
正如上面介绍的, 这里详细介绍的, vector<bool>
有什么不好的地方在于,它在generics代码中的performance与其他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>
。 当运行一个vector<char>
(或者当一个合适的非默认T
被分配时,除了bool
之外的任何vector
),testing通过。
libc ++实现试图最小化在generics代码vector<bool>
performance不同的负面影响。 有一件事是为了实现这一点,使vector<T>::const_reference
一个代理引用 ,就像指定的vector<T>::reference
,除了你不能通过它分配。 也就是说,在libc ++中, vector<T>::const_reference
本质上是指向vector
内的位的指针,而不是该位的副本。
在libc ++上面的test
通过了vector<char>
和vector<bool>
。
在什么成本?
缺点是这个扩展是可检测的,如问题所示。 但是,很less有程序真正关心这个别名的确切types,更多的程序关心这个行为。
这种不合格的动机是什么?
为了使libc ++客户端在generics代码中有更好的行为,也许在经过充分的现场testing之后,为了改进整个C ++行业,将这个扩展推荐给未来的C ++标准。
这样的提议可能会以一个新的容器(比如bit_vector
)的forms出现,它与今天的vector<bool>
有很多相同的API,但是有一些升级,比如这里讨论的const_reference
。 随后是vector<bool>
的弃用(并最终删除)。 bitset
也可以在这个部门使用一些升级,例如添加const_reference
和一组迭代器。
也就是说,在事后bitset
是vector<bool>
(应该重命名为bit_vector
– 或其他),因为array
是vector
。 无论我们是否将bool
作为vector
和array
,这个类比应该是真实的。
C ++ 11和C ++ 14的许多function都是以libc ++的扩展名开始的。 这是标准如何演变的。 实际performance 积极的实地经验产生强烈的影响 对于改变现有的规范(他们应该是这样),标准的人是保守的。 猜测,即使你确定你猜对了,对于发展一个国际公认的标准来说,这是一个冒险的策略。