1

I'm attempting to use adata() function found in virtually all other std::vector specializations, but I've come to find that there is no data() function for the bool specialization.

The documentation states:

The specialization has the same member functions as the unspecialized vector, except data, emplace, and emplace_back, that are not present in this specialization.

What is the technical reason behind this? Why could it not simply return a pointer to it's first element?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Colin Basnett
  • 4,052
  • 2
  • 30
  • 49

2 Answers2

5

std::vector<bool> is specialized for space-efficiency. It doesn't provide data() function.

You cannot address its elements because each of them is of 1 bit size, and there is nothing on machine like pointer to single bit.

The manner in which std::vector is made space efficient (as well as whether it is optimized at all) is implementation defined. One potential optimization involves coalescing vector elements such that each element occupies a single bit instead of sizeof(bool) bytes.

You can access its elements using

std::vector<bool>::reference

This embedded class is the type returned by members of non-const vector when directly accessing its elements. It accesses individual bits with an interface that emulates a reference to a bool.


Normally data() returns a T* which here would be bool* but IS NOT because the reference and pointer types are not really references and pointers to bool. For example on my implementation bit type is a typedef for unsigned long

typedef unsigned long _Bit_type;

and this is what is used by a reference to bits called struct _Bit_reference. This struct is used by struct _Bit_iterator which is an iterator to elements. You can see here what it means to dereference this iterator and get element of std::vector<bool> on this implementation:

//  typedef unsigned long _Bit_type;
// struct _Bit_reference
// {
//   _Bit_type * _M_p;
// ...
// };
//  typedef _Bit_reference  reference;

reference
    _Bit_iterator::operator*() const
    { return reference(_M_p, 1UL << _M_offset); }
4pie0
  • 29,204
  • 9
  • 82
  • 118
  • Even if each byte contained 8 "elements", isn't it a given that a pointer to the first element would be byte-aligned, and thus *would* be reliably addressable? – Colin Basnett Mar 19 '14 at 01:02
  • there is no pointer to bit. The smallest thing that machine can address is char – 4pie0 Mar 19 '14 at 01:07
  • Right, but the *first element* would be byte-aligned, and thus could be accurately addressed, no? – Colin Basnett Mar 19 '14 at 01:08
  • std::vector even does not necessarily store its data in a single contiguous chunk of memory – 4pie0 Mar 19 '14 at 01:10
  • @cmbasnett: Do you know if the _first element_ is a byte, 32-bit int, or 64-bit int? You don't because it's an implementation detail. What exactly should `data()` return? – Blastfurnace Mar 19 '14 at 01:19
  • normally it returns a T* which here would be bool* but IS NOT because the reference and pointer types are not really references and pointers to bool. In my implementation bit type is : typedef unsigned long _Bit_type; – 4pie0 Mar 19 '14 at 01:22
  • @Blastfurnace I suppose that makes sense, ideally it would return a `void*`, but I suppose at that point it's useless since none of the implementation details are known. Point taken. – Colin Basnett Mar 19 '14 at 01:30
  • @Blastfurnace Yeah right. Which implementation doesn't store them contiguously? I guess char might be 14 bits and the floating point numbers might have the sign bit at bit 18, too? – doug65536 Mar 18 '23 at 23:43
1

There can't be referencable data for particular bits. Maybe you're better off using std::bitset<> instead of specialized std::vector<bool> (which actually boils down to an equivalent of std::vector<uint8_t> specialization).

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