std::vector<bool> does not obey the standard container rules.
In particular, its iterators' operator* do not return bool&.
The loop in the invalid code
#include <vector>
#include <iostream>
int main() {
std::vector<bool> boolVector(10);
for (auto& i: boolVector)
std::cout << i;
}
can be rewritten in any of three ways to iterate through the values:
(read-only)
for (auto const i: boolVector)
std::cout << i;
(read-only, possibly inefficient¹)
for (auto const& i: boolVector)
std::cout << i;
(read/write²)
for (auto&& i: boolVector)
std::cout << i;
The choice between the first and last is down to whether you need to modify the values in the vector, or just to read them.
Notes:
I say "possibly inefficient" because it has an unnecessary level of indirection. Any decent optimizer ought to create the same code as for the first sample.
for (auto i: boolVector) also gives a read/write view on the vector (because we have made a copy of the proxy object). But I don't recommend that, because readers will likely expect such writes to have only local effect, as would happen with standard containers.
And that's why I use auto const i for the read-only case; alternatively we could obtain a proxy-of-const using boolVector | std::views::as_const (since C++23) or by using a const reference to the vector (for (auto const& v = boolVector; auto i: v)).