C++ 为什么向量<;bool>;::参考不';不返回对bool的引用?

C++ 为什么向量<;bool>;::参考不';不返回对bool的引用?,c++,compiler-errors,g++,C++,Compiler Errors,G++,问题是为什么会发生这种情况?是不是vector::reference不是bool&?还是编译器的错误? 或者,我在尝试一些愚蠢的事情吗?:) 这被认为是标准的错误。使用矢量: g++ -O3 -std=c++0x -Wall -Wextra -pedantic dk2.cpp 模板 结构foo{ 使用类型=t; }; 样板 结构foo{ 使用type=char; }; 样板 使用固定向量=std::vector; 有时,您可能需要引用向量中包含的bool。不幸的是,使用vector只能提

问题是为什么会发生这种情况?是不是
vector::reference
不是
bool&
?还是编译器的错误?
或者,我在尝试一些愚蠢的事情吗?:)

这被认为是标准的错误。使用
矢量

g++ -O3 -std=c++0x -Wall -Wextra -pedantic dk2.cpp
模板
结构foo{
使用类型=t;
};
样板
结构foo{
使用type=char;
};
样板
使用固定向量=std::vector;

有时,您可能需要引用向量中包含的bool。不幸的是,使用
vector
只能提供对字符的引用。如果您确实需要
bool&
,请查看。它有一个非专用版本的
vector

std::vector
是一个不合格的容器。为了优化空间,它打包了
bool
s,不能提供参考


>使用< /P> < P>你的期望是正常的,但问题是 STD::vector 是C++的一种实验。它实际上是一个模板专门化,将bool值紧密地存储在内存中:每个值一位

既然你一点也不能引用,那就是你的问题。

就我的2美分:

std::vector::reference
struct\u Bit\u reference
的类型定义,定义为

template<typename t>
struct foo {
  using type = t;
};
template<>
struct foo<bool> {
  using type = char;
};

template<typename t, typename... p>
using fixed_vector = std::vector<typename foo<t>::type, p...>;
像这样更改函数,它可以工作(至少可以编译,还没有测试过):

模板
无效callIfToggled(布尔v1,标准::向量::参考v2,T&T)
{
布尔b=v2;
如果(v1!=b)
{
v2=v1;
t、 foo();
}
}

编辑:我将条件从(v1!=v2)(这不是一个好主意)更改为(v1!=b)。

std::vector
将其内容打包,使每个布尔值存储在一位中,八位为一个字节。这是一种内存效率高但计算量大的方法,因为处理器必须执行算术才能访问请求的位。它不适用于<代码>布尔O/COD>引用或指针语义,因为字节内的位在C++对象模型中没有地址。 您仍然可以声明类型为
std::vector::reference
的变量,并将其当作
bool&
使用。这使得通用算法能够兼容

template< typename T >
void callIfToggled( bool v1, std::vector<bool>::reference v2, T & t )
{
    bool b = v2;  
    if ( v1 != b )
    {
        v2 = v1;
        t.foo();
    }
}

创建一个包含
bool
的结构,并使用该结构类型生成
向量

尝试:

vector
其中
sb
struct{booleanb];

那么你可以说

向后推({true})


typedef struct sbool{bool b;}bool struct;
然后是
vector bs;

不幸的是,尽管它的名字叫
std::vector
,但它不是
bool
vector
。作为一种解决方法,您可以使用
std::unique\u ptr(new bool[3])
…Herb Sutter的文章就是关于这个问题的。Howard Hinnant的文章说这是一个很好的优化,只是名称应该更改为不表示标准容器的更大含义。要获得一种引用,需要使用操作符[](结果是动态的_bitset::reference)。但是没有迭代器。-1因为没有提到
动态位集
是如何不同或更好的。当然,它也不能返回
bool&
。它不是一个扩展,只是GCC如何实现向量专门化。我不知道标准是怎么说的。你可以自己看看:lib/GCC/mingw32中的std_bvector.h/4.6.1/include/c++/bits。(您的目录树可能不同,但可能相似)当然,对于这一特定情况,它是有效的——进一步说明了为什么
vector
是一个可怕的误用词——因为它变得极其困难、乏味,或者不可能在适用于其他实际容器的泛型代码情况下使用。不过,我认为这里一个可用的解决方法是使用
template void callIfToggled(B&v1、B&v2、T&T)
并依赖于
v2
中的转换运算符-我想这是感谢转发引用的另一个原因。不过,不要原谅错误的名称选择!很好的解决方法,很好的演示了新的
使用
语法进行别名。@Nawaz我向上帝发誓,双关语是有意的。+1.std::vector只支持子类std::vector提供的一组功能。这很难看,因为您必须用不同的类型(char)替换bool才能得到一个工作向量。这是一个大多数(若不是全部)的实验委员会的成员们后悔了,很好的回答,特别是提到了代码>和代码>,这对于通用代码来说是至关重要的,让代理类型/迭代器永远有用。当然,它在循环中工作得很好:<代码>(Auto&&:BiAccess容器)< /C> > C++中不需要<代码>结构> <代码>或<代码> TyPulf< /Co> >
template<typename t>
struct foo {
  using type = t;
};
template<>
struct foo<bool> {
  using type = char;
};

template<typename t, typename... p>
using fixed_vector = std::vector<typename foo<t>::type, p...>;
typedef unsigned long _Bit_type;

struct _Bit_reference
  {
    _Bit_type * _M_p;
    _Bit_type _M_mask;

    // constructors, operators, etc...

    operator bool() const
    { return !!(*_M_p & _M_mask); }
  };
template< typename T >
void callIfToggled( bool v1, std::vector<bool>::reference v2, T & t )
{
    bool b = v2;  
    if ( v1 != b )
    {
        v2 = v1;
        t.foo();
    }
}
std::vector< bool > bitvec( 22 );
std::vector< bool >::reference third = bitvec[ 2 ];
third = true; // assign value to referenced bit
std::vector< bool > bitvec( 22 );
auto &&third = bitvec[ 2 ]; // obtain a std::vector< bool >::reference
third = true; // assign value to referenced bit