C++ 替代 vector<bool>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/670308/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:37:15  来源:igfitidea点击:

Alternative to vector<bool>

c++stlvectorboolean

提问by rlbond

As (hopefully) we all know, vector<bool>is totally broken and can't be treated as a C array. What is the best way to get this functionality? So far, the ideas I have thought of are:

正如(希望)我们都知道的那样,vector<bool>它完全坏了,不能被视为 C 数组。获得此功能的最佳方法是什么?到目前为止,我想到的想法是:

  • Use a vector<char>instead, or
  • Use a wrapper class and have vector<bool_wrapper>
  • 使用 avector<char>代替,或
  • 使用包装类并有 vector<bool_wrapper>

How do you guys handle this problem? I need the c_array()functionality.

大家是怎么处理这个问题的?我需要这个c_array()功能。

As a side question, if I don't need the c_array()method, what is the best way to approach this problem if I need random access? Should I use a deque or something else?

作为一个附带问题,如果我不需要该c_array()方法,如果我需要随机访问,解决此问题的最佳方法是什么?我应该使用双端队列还是其他东西?

Edit:

编辑:

  • I do need dynamic sizing.
  • For those who don't know, vector<bool>is specialized so that each booltakes 1 bit. Thus you can't convert it to a C-style array.
  • I guess "wrapper" is a bit of a misnomer. I was thinking something like this:
  • 我确实需要动态调整大小。
  • 对于那些不知道的人,vector<bool>是专门的,所以每个bool需要 1 位。因此,您无法将其转换为 C 样式数组。
  • 我想“包装器”有点用词不当。我在想这样的事情:

Of course, then I have to read into a my_booldue to possible alignment issues :(

当然,my_bool由于可能的对齐问题,我必须阅读 a :(

struct my_bool
{
    bool the_bool;
};
vector<my_bool> haha_i_tricked_you;

采纳答案by Daniel Earwicker

Use std::dequeif you don't need the array, yes.

std::deque如果您不需要数组,请使用,是的。

Otherwise use an alternative vectorthat doesn't specialize on bool, such as the one in Boost Container.

否则,请使用vector不专注于的替代方案bool,例如Boost Container 中的替代方案。

回答by Klaim

That's an interesting problem.

这是一个有趣的问题。

If you need what would have been a std::vector if it was not specialized, then maybe something like that would work fine with your case :

如果你需要一个 std::vector 如果它不是专门的,那么也许类似的东西可以很好地处理你的情况:

#include <vector>
#include <iostream> 
#include <algorithm>

class Bool
{
public:

    Bool(): m_value(){}
    Bool( bool value ) : m_value(value){}

    operator bool() const { return m_value; }

    // the following operators are to allow bool* b = &v[0]; (v is a vector here).
    bool* operator& () { return &m_value; }
    const bool* operator& () const { return &m_value; }

private:

    bool m_value;

};




int main()
{
    std::vector<Bool> working_solution(10, false);


    working_solution[5] = true;
    working_solution[7] = true;


    for( int i = 0; i < working_solution.size(); ++i )
    {
        std::cout<< "Id " << i << " = " << working_solution[i] << "(" <<(working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct
    }

    std::sort( working_solution.begin(), working_solution.end());
    std::cout<< "--- SORTED! ---" << std::endl;

    for( int i = 0; i < working_solution.size(); ++i )
    {
            bool* b = &working_solution[i]; // this works!

        std::cout<< "Id " << i << " = " << working_solution[i] << "(" << (working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct
    }

    std::cin.get();
    return 0;
}

I tried this with VC9 and it seems to work fine. The idea of the Bool class is to simulate the bool type by providing the same behavior and size (but not the same type). Almost all the work is done by the bool operator and the default copy constructors here. I added a sort to be sure it react as assumed when using algorithms.

我用 VC9 试过这个,它似乎工作正常。Bool 类的思想是通过提供相同的行为和大小(但不是相同的类型)来模拟 bool 类型。几乎所有的工作都是由 bool 运算符和这里的默认复制构造函数完成的。我添加了一个排序以确保它在使用算法时按假设做出反应。

Not sure it would suit all cases. If it's right for your needs, it would be less work than rewriting a vector-like class...

不确定它是否适合所有情况。如果它适合您的需求,那将比重写一个类似向量的类要少...

回答by David Rodríguez - dribeas

Depends on your needs. I would go for either std::vector<unsigned char>. Writting a wrapper can be fine if you only use a subset of the functionality, else it will become a nightmare.

取决于您的需求。我会去std::vector<unsigned char>。如果您只使用功能的一个子集,那么编写包装器就可以了,否则它将成为一场噩梦。

回答by Evgeny Panasyuk

How do you guys handle this problem? I need the c_array() functionality.

大家是怎么处理这个问题的?我需要 c_array() 功能。

boost::container::vector<bool>:

boost::container::vector<bool>

vector<bool> specialization has been quite problematic, and there have been several unsuccessful tries to deprecate or remove it from the standard. Boost.Containerdoes not implement it as there is a superior Boost.DynamicBitsetsolution.

...

So boost::container::vector::iteratorreturns real bool references and works as a fully compliant container. If you need a memory optimized version of boost::container::vector<bool> functionalities, please use Boost.DynamicBitset.

vector< bool> 专业化一直存在很大问题,并且有几次尝试从标准中弃用或删除它,但都没有成功。Boost.Container没有实现它,因为有一个卓越的Boost.DynamicBitset解决方案。

...

所以boost::container::vector::iterator返回真正的 bool 引用并作为一个完全兼容的容器工作。如果您需要boost::container::vector< bool> 功能的内存优化版本,请使用Boost.DynamicBitset

回答by AHelps

Consider using a vector< int >. Once you get past compilation and type checking, bool and int are both just machine words (edit: apparently this is not always true; but will be true on many PC architectures). In those cases where you want to convert without a warning, use "bool foo = !!bar", which converts zero to false and non-zero to true.

考虑使用向量< int >。一旦你通过了编译和类型检查, bool 和 int 都只是机器字(编辑:显然这并不总是正确的;但在许多 PC 架构上都是正确的)。如果您想在没有警告的情况下进行转换,请使用“bool foo = !!bar”,它将零转换为 false,将非零转换为 true。

A vector< char > or similar will use less space, though it also has the potential to take a (very small) speed hit in some circumstances, because characters are less than the machine word size. This is, I believe, the main reason that bools are implemented using ints instead of chars.

vector<char> 或类似的将使用更少的空间,尽管在某些情况下它也有可能会受到(非常小的)速度影响,因为字符小于机器字的大小。我相信,这是使用整数而不是字符来实现布尔值的主要原因。

If you really want clean semantics, I also like the suggestion of making your own boolean class -- looks like a bool, acts like a bool, but fools the template specialization.

如果你真的想要干净的语义,我也喜欢创建你自己的布尔类的建议——看起来像一个布尔,行为像一个布尔,但愚弄了模板专业化。

Also, welcome to the club of people who want the vector< bool > specialization dropped from the C++ standard (with bit_vector to replace it). It's where all the cool kids hang out :).

另外,欢迎加入那些希望从 C++ 标准中删除 vector< bool > 专业化(用 bit_vector 替换它)的人的俱乐部。这是所有酷孩子们闲逛的地方:)。

回答by bayda

This problem was already discussedon comp.lang.c++.moderated. Proposed solutions:

这个问题已经在 comp.lang.c++.moderated 上讨论过了。建议的解决方案:

  • your own allocator (based on std::allocator) and own vector specialization;
  • use std::deque(as early was recommended in one of books S. Mayers) - but this not for your requirements;
  • make POD boolwrapper;
  • use something (char/int/etc) with same size as boolinstead bool;
  • 您自己的分配器(基于std::allocator)和自己的向量专业化;
  • 使用std::deque(早期在 S. Mayers 一书中推荐) - 但这不符合您的要求;
  • 制作PODbool包装器;
  • 使用大小相同的东西(char/ int/etc )bool代替bool

Also early I saw proposal for standard committee - introduce macro (something like STD_VECTOR_BOOL_SPECIAL) to disallow this specialization - but AFAIK this proposal was not implemented in stl implementations and wasn't approved.

我也很早就看到了标准委员会的提案 - 引入宏(类似的东西STD_VECTOR_BOOL_SPECIAL)来禁止这种专业化 - 但 AFAIK 这个提案没有在 stl 实现中实现,也没有被批准。

It seems that your problem has no ways to do this nicely... Maybe in C++0x.

似乎你的问题没有办法很好地做到这一点......也许在 C++0x 中。

回答by Todd

Simplest answer is use vector<struct sb>where sbis struct {boolean b};. Then you can say push_back({true}). It seems good.

最简单的答案是使用vector<struct sb>where sbis struct {boolean b};。那你可以说push_back({true})。看起来不错。

回答by Tony E Lewis

My preferred workaround is a vectorof a scoped enum that has an underlying type of bool. This gets pretty close to the vector<bool>we would have had if the committee hadn't specialised it.

我首选的解决方法是vector具有基础类型的范围枚举的 a boolvector<bool>如果委员会没有对其进行专门化,这将非常接近我们会拥有的情况。

enum class switch_status : bool { ON, OFF };

static_assert( sizeof( switch_status ) == 1 );

::std::vector<switch_status> switches( 20, switch_status::ON );

static_assert( ::std::is_same_v< decltype( switches.front() ), switch_status &> );
static_assert( ::std::is_same_v< decltype( switches.back()  ), switch_status &> );
static_assert( ::std::is_same_v< decltype( switches[ 0 ]    ), switch_status &> );

You will have your own opinions about the wisdom of embracing casts to/from bool:

您将有自己的关于接受演员表到/从的智慧的意见bool

enum class switch_status : bool { OFF = false, ON = true };

static_assert( static_cast< bool          >( switch_status::ON  ) == true               );
static_assert( static_cast< bool          >( switch_status::OFF ) == false              );
static_assert( static_cast< switch_status >( true               ) == switch_status::ON  );
static_assert( static_cast< switch_status >( false              ) == switch_status::OFF );