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