vector <bool> </bool>的替代方案

时间:2009-03-22 00:21:00

标签: c++ stl vector boolean

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

  • 改为使用vector<char>
  • 使用包装器类并拥有vector<bool_wrapper>

你们怎么处理这个问题?我需要c_array()功能。

作为一个附带问题,如果我不需要c_array()方法,如果我需要随机访问,解决此问题的最佳方法是什么?我应该使用deque还是别的什么?

编辑:

  • 我确实需要动态调整大小。
  • 对于那些不知道的人,vector<bool>是专门的,所以每个bool需要1位。因此,您无法将其转换为c风格的数组。
  • 我猜“包装”有点用词不当。我在想这样的事情:

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

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

8 个答案:

答案 0 :(得分:38)

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

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

答案 1 :(得分:20)

这是一个有趣的问题。

如果你需要一个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 * const 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;
}

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

不确定它是否适合所有情况。如果它适合您的需求,那么重写类似矢量的类就不那么重要了......

答案 2 :(得分:16)

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

答案 3 :(得分:11)

  

你们怎么处理这个问题?我需要c_array()功能。

boost::container::vector<bool>

  

<强>矢量&LT;的 BOOL &GT;专业化一直存在很大问题,并且已经有几次尝试不推荐地将其从标准中删除或删除。 Boost.Container没有实现它,因为有一个优秀的 Boost.DynamicBitset 解决方案。

     

...

     

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

答案 4 :(得分:5)

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

载体&lt; char&gt;或类似的将使用更少的空间,但它也有可能在某些情况下(非常小的)速度命中,因为字符小于机器字大小。我相信,这是使用整数而不是字符来实现bool的主要原因。

如果你真的想要干净的语义,我也喜欢制作你自己的布尔类的建议 - 看起来像一个bool,就像一个bool,但是愚弄模板专业化。

此外,欢迎来到想要矢量的人的俱乐部&lt; bool&gt;专业化从C ++标准中删除(使用bit_vector替换它)。这是所有酷孩子们出去玩的地方:)。

答案 5 :(得分:4)

这个问题在comp.lang.c ++。moderated上已经discussed了。提出的解决方案:

  • 您自己的分配器(基于std::allocator)和自己的向量专业化;
  • 使用std::deque(早在S. Mayers书籍中推荐) - 但这不符合您的要求;
  • 制作POD bool包装;
  • 使用与char大小相同的内容(int / bool / etc)代替bool;

同样早期,我看到了标准委员会的建议 - 介绍宏(类似STD_VECTOR_BOOL_SPECIAL)以禁止此专业化 - 但AFAIK此提案未在stl实施中实施且未获批准。

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

答案 6 :(得分:4)

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

答案 7 :(得分:2)

我首选的解决方法是范围枚举的vector,其基础类型为bool。如果委员会不对它进行专门化,这将非常接近vector<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 &> );

对于将演员表投向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 );