When I iterate over a vector<bool>
, I find that the elements, dereferenced through the iterator, are recognized as if they were const. Why is that? Change either the container or the element type, such as list<bool>
or vector<short>
, and the elements are non-const. This code shows what I'm talking about:
typedef bool T;
#define C vector
istringstream &operator>>(istringstream &iss, T &v)
{
cout << "non-const" << endl;
return iss;
}
istringstream &operator>>(istringstream &iss, const T &v)
{
cout << "const" << endl;
return iss;
}
istringstream &operator>>(istringstream &iss, C<T> &c)
{
for (C<T>::iterator it = c.begin(); it != c.end(); ++it)
{
iss >> *it;
}
return iss;
}
int main()
{
C<T> c(1);
istringstream iss("1");
iss >> c;
}
For vector<bool>
, this program prints "const" to the console. Change the typedef and manifest constant at the top to anything but those two combinations, and it prints "non-const." Also, if I replace the line, iss >> *it
, with T v; iss >> v; *it = v;
, it works as expected--all combinations print "non-const."
I see the same behavior with GCC 4.1.2 C++98 (via codepad.org) and VS2015 C++14+ (?).
Despite the name, vector<bool>
contains no bool
s, and dereferencing its iterator doesn't give you a bool&
. Instead, it gives you an object of type vector<bool>::reference
, which tries to imitate the behavior of bool&
as much as it can.
There's no way to convert a vector<bool>::reference
to a bool&
, so the non-const overload doesn't work. vector<bool>::reference
can, however, be converted to a bool
, which can then bind to the const bool&
.