Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the disjunction assignment operator |= not work with vectors of bools?

If I have a vector<bool> vec_bool then I cannot modify the contents of the vector using the |= assignment operator. That is, the lines

vec_bool[0] |= true;
vec_bool[0] |= vec_bool[1];

give compiler errors, while the lines

bool a = false;
a |= true;
a |= vec_bool[0];
vec_bool[0] = vec_bool[0] | vec_bool[1];
vec_bool[0] = vec_bool[0] || vec_bool[1];

vector<int> vec_int(3);
vec_int[0] |= vec_int[1];

do not. What is the reason for this?

The error given (by gcc) is:

test.cpp:21:17: error: no match for ‘operator|=’ (operand types are ‘std::vector::reference {aka std::_Bit_reference}’ and ‘bool’)

like image 738
Mees de Vries Avatar asked Oct 03 '17 09:10

Mees de Vries


1 Answers

The reference returned from operator[] of std::vector<bool> is not an alias for bool&, as it is for the primary specialization of std::vector. It is rather specified by the C++ standard as this:

// bit reference:
class reference {
  friend class vector;
  reference() noexcept;
public:
  ~reference();
  operator bool() const noexcept;
  reference& operator=(const bool x) noexcept;
  reference& operator=(const reference& x) noexcept;
  void flip() noexcept;     // flips the bit
};

And as you can see, there is no operator |= declared. So you can't apply it on the reference returned from vec_bool[0].

The reason that vec_bool[0] = vec_bool[0] | vec_bool[1]; works is that there are overloads above that facilitate it. operator bool() converts the two operands of the built-in | into bool values. And then the assignment operator of reference assigns the result back to vec_bool[0].

As specified by the C++ standard, std::vector<bool> isn't a particularly good abstraction, IMO.

like image 105
StoryTeller - Unslander Monica Avatar answered Sep 28 '22 01:09

StoryTeller - Unslander Monica