为什么libc++的vector<bool>::const_reference不是bool?
Why is libc++'s vector<bool>::const_reference not bool?
Section 23.3.7 class 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和其他)方面的行为更像vector<char>
,它可以被符合标准的程序检测到,因此不符合标准。
自1998年以来,vector<bool>
一直被嘲笑为"不完全是容器"。第一批LWG议题之一的LWG 96引发了这场辩论。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>
一起运行时才会触发。当使用vector<char>
运行时(或者在分配了适当的非默认T
时,除了bool
之外的任何vector
),测试通过。
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
)的形式出现,该容器具有与今天的vector<bool>
相同的API,但会进行一些升级,例如这里讨论的const_reference
。其次是弃用(并最终删除)vector<bool>
专门化。bitset
也可以在这方面进行一些升级,例如添加const_reference
和一组迭代器。
也就是说,事后看来,bitset
对vector<bool>
(应该重命名为bit_vector
——或者其他什么),就像array
对vector
一样。无论我们是否将bool
视为vector
和array
的value_type
,这个类比都应该成立。
有很多c++ 11和c++ 14特性的例子,最初是作为libc++的扩展。标准就是这样发展的。实际演示积极的现场经验具有很强的影响力。当涉及到改变现有规范时,标准人员是一群保守的人(他们应该这样做)。猜测,即使你确信你猜对了,对于发展一个国际公认的标准来说,也是一种冒险的策略。
- 写入向量<向量<bool>>
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- Visual Studio Code "undefined reference to `WinMain@16'"
- 使用 MATLAB 编码器生成C++代码:编译错误"undefined reference to `rgb2gray_tbb_real64'"
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 为什么创建友元类的实例会导致"undefined reference to"错误?
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 让bool方法返回其他整数
- Tensorflow c++ api undefined reference to 'tflite::D efaultErrorReporter()'
- 如何在 std::vector 中找到<bool>哪些索引是真的?
- 不断"Attempting to reference a deleted function"
- Arduino-C++ bool 不会从 false 变为 true
- 为什么在这种情况下,bool 类型的输出等于 0?
- 显式 std::exception_ptr 转换为 bool 不存在.VS2010 错误?
- std::iterator::reference 必须是引用吗?
- 错误:不能使用"显式"说明符声明 bool'
- C++/SDL "initial value of reference to a non-const must be an lvalue"
- 为什么 C++ 11 在 ios 类中添加了运算符 bool
- 为什么 vector:<bool>:reference 不返回对 bool 的引用?
- 错误:从类型为"std::vector:<bool>:reference {aka std::_Bit_reference}"的右值初始化类型为"bool&"的非常量引用无效