替代矢量

我们都知道(希望如此) ,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;
44144 次浏览

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

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

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.

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 :

#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.

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...

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

  • 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 bool wrapper;
  • use something (char/int/etc) with same size as bool instead 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.

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

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.

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.

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 :).

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

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.Container does not implement it as there is a superior Boost.DynamicBitset solution.

...

So boost::container::vector::iterator returns 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.

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

My preferred workaround is a vector of 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.

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:

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 );