0

I have the problem with redefining operator[] in my class which has vector as private member. So plan is to have vector of bools which is going to contain only true or false value. Here is minimal code that you could understand problem that i have.

class A{
   private:
     std::vector<bool> _object;
   public:
   bool& operator[](size_t i) {return _object[i];};
   };

Compiler error is: Non-cost lvalue reference to type bool cannot be bind to a temporary of 'reference' (aka 'std::_Bit_reference')

I don't understand how _object[i] can be temporary in this situation.

AC Voltage
  • 339
  • 3
  • 9
  • 3
    `vector` doesn't behave like you think it does. See [why-is-vectorbool-not-a-stl-container](http://stackoverflow.com/questions/17794569/why-is-vectorbool-not-a-stl-container) for more. – John3136 Jan 07 '16 at 23:26
  • This was a design mistake that is retained for backwards-compatibility. The problem is that `vector` does not necessarily hold a vector of bools. – Joel Cornett Jan 08 '16 at 00:14
  • `deque` might suit your scenario. – Deqing Jan 08 '16 at 01:31

3 Answers3

4

Unlike every other std::vector<T>, std::vector<bool>::operator[] does not return a T& (in this case bool&), but some implementation defined reference proxy class which need not be (and, on your platform, is not) able to bind to bool&. This is because std::vector<bool> is allowed to be a space efficient specialization of std::vector instead of your naive array of bools. For reference, see this.

This is widely considered at least a poor choice of name by the standard committee because it breaks expectations people reasonably have when looking at an std::vector.

Unfortunately, there is no idiomatic fix for this. If you want normal std::vector behavior, you probably either need to write a small wrapper class or just use a std::vector<char> instead. I am aware that both of those are unpleasant and I strongly feel like introducing that specialization was a mistake.

If possible, you can use boost::container::vector<bool> instead of std::vector<bool>. Fortunately, Boost has not repeated that inconvenient mistake and gave the space efficient variant a proper name instead.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
1

This is because only for std::vector< bool > STL optimize storage capacity such that every value stored in a single bit. But the minimal size of the object in C++ is sizeof(char). So the library needs to construct the object and the reference will be temporary.

SashaMN
  • 708
  • 5
  • 16
1

Well, you can't really reference a specific bit, whereas a char is the smallest unit of addressable memory.

The std::vector<bool> implementation may differ from the standard container guarantees as mentioned in the notes from the reference documentation:

Since its representation may by optimized, std::vector<bool> does not necessarily meet all Container or SequenceContainer requirements. For example, because std::vector<bool>::iterator is implementation-defined, it may not satisfy the ForwardIterator requirement. Use of algorithms such as std::search that require ForwardIterators may result in either compile-time or run-time errors.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190