c++vectorbooleanconstantsextraction-operator

Why are non-const vector<bool> elements const?


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+ (?).


Solution

  • Despite the name, vector<bool> contains no bools, 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&.