Alternative to vector<bool>

C++StlVectorBoolean

C++ Problem Overview


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:

  • Use a vector<char> instead, or
  • Use a wrapper class and have vector<bool_wrapper>

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

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?

Edit:

  • I do need dynamic sizing.
  • For those who don't know, vector<bool> is specialized so that each bool takes 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:

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

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

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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

Solution 3 - C++

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.

Solution 4 - C++

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

Solution 5 - C++

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

Solution 6 - C++

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.

Solution 7 - C++

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

Solution 8 - C++

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrlbondView Question on Stackoverflow
Solution 1 - C++Daniel EarwickerView Answer on Stackoverflow
Solution 2 - C++KlaimView Answer on Stackoverflow
Solution 3 - C++David Rodríguez - dribeasView Answer on Stackoverflow
Solution 4 - C++Evgeny PanasyukView Answer on Stackoverflow
Solution 5 - C++AHelpsView Answer on Stackoverflow
Solution 6 - C++baydaView Answer on Stackoverflow
Solution 7 - C++ToddView Answer on Stackoverflow
Solution 8 - C++Tony E LewisView Answer on Stackoverflow