6

Trying to use std::vector<bool> I have a compiler error that is very surprising to me.

In short taking the address of an element of a std::vector<unsigned char> and assigning it to a unsigned char pointer:

std::vector<unsigned char> test(10);
unsigned char *pb = &test[0];

works perfectly well, while trying to do the same thing with a std::vector<bool> results in a compiler error:

int main() {

    std::vector<bool> test(10);
    bool *pb = &test[0];    // line 4, compile error

    return 0;
}

On Visual Studio, it says something like:

std::vector bool cannot convert std::_Vb_reference<_Alloc> * to bool *

while codepad (see example at http://codepad.org/vaiN3iEq) says:

cc1plus: warnings being treated as errors
In function 'int main()':
Line 4: warning: taking address of temporary
Line 4: error: cannot convert '__gnu_norm::_Bit_reference*' to 'bool*' in initialization
compilation terminated due to -Wfatal-errors.

I thought both bool and unsigned char were internally the same (just a 1 byte type, with some compiler stuffs to enforce bool to allow only true/false values). But I was not expecting such problem! Any idea why?!

Note that I know of bitsets and am not interested in using them here.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
nbonneel
  • 3,286
  • 4
  • 29
  • 39
  • possible duplicate of [Why vector not a STL container?](http://stackoverflow.com/questions/17794569/why-vectorbool-not-a-stl-container) – Zac Howland Jan 13 '14 at 23:57
  • On the other hand, I'd prefer using iterators rather than address of operators. Using iterators gives a better scalable design. – Yogesh Sajanikar Jan 14 '14 at 00:44
  • @YogeshSajanikar this is quite out of topic here, but I first see iterators as unreadable (between a `for (int i=0; i<10; i++) a[i]=0;` and `for (std::vector::iterator it=a.begin(); it!=a.end(); ++it) *it=0` , the first one is *much* more readable) and I guess they incur a performance hit (especially in debug with all the different checks etc.) which is a pain for something as simple as putting/accessing a value at a given location in memory. They may become useful for other contains (std::map etc), but for std::vectors, I just hate them. ;) – nbonneel Jan 14 '14 at 01:17

1 Answers1

7

Yes, bool and unsigned char typically take the same amount of memory on their own, but that does not make vector<bool> and vector<unsigned char> the same!

vector<bool> is given very, very special treatment by the standard in order to pack elements as close as possible (which someone in the 1990s thought would be clever, since a bool has one of only two states), and the result is what you've seen: its elements are non-addressable.

Avoid!

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • thanks! I didn't mean the vectors to be the same and I can still do double* v = (double*) my_unsigned_char_vector[0] and that would compile. What do you mean by "packing elements as close as possible" ? These are not bitsets, and the closest possible way to arrange series of 8bits variables is to put them contiguously... – nbonneel Jan 13 '14 at 23:59
  • 2
    @WhitAngl The standard requires that `vector` is a bitset. So its `operator[]` returns a proxy object (since you can return a reference to a bit field). And you cannot take the address of that proxy in the expression you have since it is an rvalue. – Praetorian Jan 14 '14 at 00:03
  • @WhitAngle `vector` is a specialization designed to allow bits to be packed together. That is, it might internally store 8 bit `char`s and use each bit as a `bool`. – Joseph Mansfield Jan 14 '14 at 00:03
  • @WhitAngl: Why do you assert "these are not bitsets"? – Lightness Races in Orbit Jan 14 '14 at 00:19
  • @LightnessRacesinOrbit I was assuming so, but was apparently wrong. I thought of std::vector as just a plain array of elements, and that seems to be the case for all other types. – nbonneel Jan 14 '14 at 01:13
  • @WhitAngl the specialization of `std::bool` is recognized as a mistake by nearly everyone now. Unfortunately you can't go back in time and revoke it, it's an accepted part of the standard. – Mark Ransom Jan 14 '14 at 01:16
  • @WhitAngl: Yep. It's just for bool. – Lightness Races in Orbit Jan 14 '14 at 08:54
  • @MarkRansom: There's no such thing as `std::bool`. – Lightness Races in Orbit Jan 14 '14 at 08:56
  • LightnessRacesinOrbit and @WhitAngl, argh! Naturally I meant to say `std::vector`. Next time I'll be careful not to any words out. – Mark Ransom Jan 14 '14 at 13:17