Почему оператор присваивания дизъюнкций | = не работает с векторами bools?

Если у меня есть vector<bool> vec_bool, то я не могу изменить содержимое вектора, используя оператор присваивания |=. То есть, строки

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

выдают ошибки компилятора, а строки

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

нет. В чем причина этого?

Приведенная ошибка (по gcc):

test.cpp: 21:17: error: нет соответствия для 'operator | = (типы операндов: std::vector:: reference {aka std:: _ Bit_reference} и' bool)

Ответы

Ответ 1

reference, возвращаемый из operator[] из std::vector<bool>, не является псевдонимом для bool&, как и для первичной специализации std::vector. Это скорее указано стандартом С++ как это:

// 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
};

И как вы можете видеть, не объявлено operator |=. Поэтому вы не можете применить его к ссылке, возвращаемой с vec_bool[0].

Причина, по которой работает vec_bool[0] = vec_bool[0] | vec_bool[1];, заключается в том, что есть вышеперечисленные перегрузки, которые облегчают ее. operator bool() преобразует два операнда встроенного значения | в значения bool. А затем оператор присваивания reference возвращает результат обратно в vec_bool[0].

Как указано стандартом С++, std::vector<bool> не является особенно хорошей абстракцией, IMO.