How*_*ant 91 c++ vector c++-standard-library libc++ std-bitset
第23.3.7节vector<bool>[vector.bool]第1段规定:
template <class Allocator> class vector<bool, Allocator> {
public:
// types:
typedef bool const_reference;
...
Run Code Online (Sandbox Code Playgroud)
但是,当使用libc ++时,此程序无法编译:
#include <vector>
#include <type_traits>
int
main()
{
static_assert(std::is_same<std::vector<bool>::const_reference, bool>{}, "?");
}
Run Code Online (Sandbox Code Playgroud)
此外,我注意到C++标准在本规范中一直与C++ 98一致.我还注意到自从第一次引入libc ++以来,libc ++一直没有遵循这个规范.
这种不合格的动机是什么?
How*_*ant 98
这种扩展的动机,可以通过一致的程序检测到,因而不符合,就是使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);
}
Run Code Online (Sandbox Code Playgroud)
标准规范表明,标记的断言// Fires!将触发,但仅在test运行时才会触发vector<bool>.当与运行vector<char>(或任何vector除了bool适当的非默认时T被分配),测试通过.
libc ++实现试图最小化vector<bool>在通用代码中具有不同行为的负面影响.它实现这一点的一件事是创建 vector<T>::const_reference一个代理引用,就像指定的那样vector<T>::reference,除了你不能通过它分配.也就是说,在libc ++上,vector<T>::const_reference本质上是指向内部位的指针vector,而不是该位的副本.
在libc ++上,上面test传递了vector<char>和vector<bool>.
费用是多少?
缺点是这个扩展是可检测的,如问题所示.但是,很少有程序真正关心这个别名的确切类型,更多的程序关心这个行为.
这种不合格的动机是什么?
为了使libc ++客户端能够在通用代码中获得更好的行为,并且可能在经过充分的现场测试之后,将此扩展建议用于未来的C++标准,以改善整个C++行业.
这样的提议可能以新容器(例如bit_vector)的形式出现,其具有与今天相同的API vector<bool>,但是具有一些升级,例如const_reference这里讨论的.然后是vector<bool>专业化的弃用(并最终删除). bitset也可以在这个部门使用一点升级,例如add const_reference和一组迭代器.
也就是说,在事后bitset是vector<bool>(应该被重新命名为bit_vector-或其他),为array是vector.而类比应该我们是否在谈论是成立的,bool为value_type的vector和array.
有许多C++ 11和C++ 14特性的例子最初是作为libc ++中的扩展而开始的.这就是标准的演变过程.实际证明的 积极的实地经验具有很强的影 当涉及到改变现有规范时,标准民众是保守派(因为它们应该是这样).即使您确定自己正确猜测,猜测也是制定国际公认标准的风险策略.