为什么vector <bool> :: reference不会返回对bool的引用?

BЈо*_*вић 56 c++ compiler-errors g++

#include <vector>

struct A
{
    void foo(){}
};

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

int main()
{
    std::vector< bool > v= { false, true, false };

    const bool f = false;
    A a;

    callIfToggled( f, v[0], a );
    callIfToggled( f, v[1], a );
    callIfToggled( f, v[2], a );
}
Run Code Online (Sandbox Code Playgroud)

上面示例的编译会产生下一个错误:

dk2.cpp: In function 'int main()':
dk2.cpp:29:28: error: no matching function for call to 'callIfToggled(const bool&, std::vector<bool>::reference, A&)'
dk2.cpp:29:28: note: candidate is:
dk2.cpp:13:6: note: template<class T> void callIfToggled(bool, bool&, T&)
Run Code Online (Sandbox Code Playgroud)

我使用g ++(版本4.6.1)编译如下:

g++ -O3 -std=c++0x -Wall -Wextra -pedantic dk2.cpp
Run Code Online (Sandbox Code Playgroud)

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

Pub*_*bby 59

矢量专门用于布尔.

它被认为是标准的错误.vector<char>改为使用:

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...>;
Run Code Online (Sandbox Code Playgroud)

有时您可能需要引用向量中包含的bool.不幸的是,使用vector<char>只能给你参考字符.如果您确实需要bool&,请查看Boost Containers库.它有一个非专业版vector<bool>.

  • +1用于'使用'的智能*用法*(无双关语). (5认同)
  • 很好的解决方法,以及用于别名的新`using`语法的漂亮演示. (3认同)

rod*_*igo 51

你的期望是正常的,但问题在于这std::vector<bool>是C++委员会的一种实验.它实际上是一个模板特化,它将bool值紧密地存储在内存中:每个值一位.

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

  • +1.std :: vector <bool>仅支持std :: vector提供的功能的子集.这很难看,因为你必须用不同的类型(char)替换bool来获得一个工作向量. (7认同)
  • 大多数(如果不是全部)委员会成员都后悔的一个实验! (2认同)

Pot*_*ter 18

std::vector< bool >打包其内容,使每个布尔值存储在一位,八位到一个字节.这是存储器效率高但计算密集的,因为处理器必须执行算术来访问所请求的位.并且它不适用于bool引用或指针语义,因为一个字节中的位在C++对象模型中没有地址.

你仍然可以声明一个类型的变量std::vector<bool>::reference并像使用它一样使用它bool&.这允许通用算法兼容.

std::vector< bool > bitvec( 22 );
std::vector< bool >::reference third = bitvec[ 2 ];
third = true; // assign value to referenced bit
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,您可以使用auto&&自动选择绑定到vector元素的左值引用的说明符或绑定到临时值的rvalue引用来解决此问题.

std::vector< bool > bitvec( 22 );
auto &&third = bitvec[ 2 ]; // obtain a std::vector< bool >::reference
third = true; // assign value to referenced bit
Run Code Online (Sandbox Code Playgroud)


red*_*der 15

std::vector<bool>是一个不合格的容器.为了优化空间,它包装bools并且不能提供参考.

boost::dynamic_bitset改用.

  • -1没有提到`dynamic_bitset`是如何不同或更好的.当然它也不能返回`bool&`. (2认同)

jro*_*rok 5

只需2美分:

std::vector<bool>::reference是typedef,struct _Bit_reference其定义为

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); }
  };
Run Code Online (Sandbox Code Playgroud)

改变这样的功能,它工作(好吧,至少编译,没有测试):

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

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