I've been trying to make an std::vector
of boolean values and I got fed up with the specialization. To get around this, I made a wrapper class around bool
and a testsuite to make sure that it compiles and works as expected.
It seems to do everything std::vector<bool>
does, except, of course, flip()
. It also satisfies the container rules so that you can take a reference or a pointer to an element.
On to the code:
vector_safe_bool.hpp
:
#pragma once
// A wrapper class around bool that can be used in std::vector without breaking container rules
class vector_safe_bool {
bool value;
public:
vector_safe_bool() = default;
vector_safe_bool(bool b) : value{b} {}
bool *operator&() noexcept { return &value; }
const bool *operator&() const noexcept { return &value; }
operator const bool &() const noexcept { return value; }
operator bool &() noexcept { return value; }
};
vsb_test.cpp
:
#include "vector_safe_bool.hpp"
#include <iostream>
#include <vector>
#if USE_VECTOR_SAFE_BOOL
using which_bool = vector_safe_bool;
#define TEST_CONTAINER true
#else
using which_bool = bool;
#define TEST_CONTAINER false
#endif
int main()
{
// The commented lines work for neither bool nor vector_safe_bool
const which_bool t1 = true;
// bool *t1p = &t1;
const bool *t1cp = &t1;
// bool &t1r = t1;
const bool &t1cr = t1;
// bool &&t1rr = t1;
which_bool t2 = true;
bool *t2p = &t2;
const bool *t2cp = &t2;
bool &t2r = t2;
const bool &t2cr = t2;
// bool &&t2rr = t2;
t2++;
++t2;
std::vector<which_bool> bv(10, true);
#if TEST_CONTAINER
for(auto &b : bv)
;
#endif
for(const auto &b : bv)
;
for(auto &&b : bv)
;
const std::vector<which_bool> cbv(10, true);
#if TEST_CONTAINER
for(auto &cb : cbv)
;
#endif
for(const auto &cb : cbv)
;
for(auto &&cb : cbv)
;
}
GNUmakefile
:
CXX = g++
CXXFLAGS = -Wall -Wextra -Wno-unused-variable -Wno-deprecated -pedantic -std=c++11
all:
check test: vsb_test.cpp vector_safe_bool.hpp
$(CXX) $(CXXFLAGS) -I. vsb_test.cpp -DUSE_VECTOR_SAFE_BOOL
@rm -f a.out
$(CXX) $(CXXFLAGS) -I. vsb_test.cpp
@rm -f a.out
What I'm looking for:
- Can I make this more idiomatic? How?
- Can I make use of features from newer versions of C++?
- Did I forget any obscure corner-cases?
- Is there anything that I can make better in the GNUmakefile?
- Are there any other ways that I could improve this?
bool
as possible, but there is some limitations (e.g.,decltype
, template parameter deduction, etc.). In the end, there is no way to makebool
itself usable withstd::vector
, so unfortunately sometimes libraries have to reinventstd::vector
:( \$\endgroup\$bool
? \$\endgroup\$vector
. It intentionally does not have thebool
specialization. The common work-around is to usestd::deque
instead. \$\endgroup\$