1

I have a problem similar to the one mentioned in the question Convert vector of vector to pointer of pointer.

The only difference is that I have to use booleans instead of shorts.

But if I compile this code:

#include <vector>

/* C like api */
void foo(bool **psPtr, const int x, const int y);

int main()
{
  const int x = 2, y = 3;
  std::vector<std::vector<bool>> vvsVec(x, std::vector<bool>(y, 0));
  std::vector<bool *> vpsPtr(x, nullptr);

  /* point vpsPtr to the vector */
  int c = 0;
  for (auto &vsVec : vvsVec)
    vpsPtr[c++] = vsVec.data();

  /* api call */
  foo(vpsPtr.data(), x, y);

  return 0;
}

I get the following error:

./dummy/main.cpp:15: error: assigning to '__gnu_cxx::__alloc_traits<std::allocator<bool *> >::value_type' (aka 'bool *') from incompatible type 'void'

and

./dummy/main.cpp:15: error: void value not ignored as it ought to be vpsPtr[c++] = vsVec.data();

Please, can someone explain me what I'm doing wrong and how to fix this?

Thanks.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Federico Nardi
  • 510
  • 7
  • 19
  • 1
    This might explain it: https://stackoverflow.com/questions/16568986/what-happens-when-you-call-data-on-a-stdvectorbool – Timbo Jul 27 '21 at 08:35
  • A common solution to this dilemma is to represent a vector of booleans as a `std::vector`. If strong typing is desired, `enum class fake_bool : char { fake_false, fake_true };` or something similar can be used. For more convenience you can implement conversion operators to/from `bool`. – Konrad Rudolph Jul 27 '21 at 08:44
  • @KondradRudolph I was thinking about the usual replacements, but when the aim is to get a `bool**` I am not sure if any of them is applicable – 463035818_is_not_an_ai Jul 27 '21 at 08:46

2 Answers2

1

std::vector<bool> is a specialization of std::vector that does not behave like other std::vectors do. It does not necessarily store the elements contiguously. From cppreference:

std::vector<bool> behaves similarly to std::vector, but in order to be space efficient, it:

  • Does not necessarily store its elements as a contiguous array.
  • Exposes class std::vector<bool>::reference as a method of accessing individual bits. In particular, objects of this class are returned by operator[] by value.
  • Does not use std::allocator_traits::construct to construct bit values.
  • Does not guarantee that different elements in the same container can be modified concurrently by different threads.

The savings in space come at a relatively high price. For example, you cannot use data() to get a pointer to a contiguous array of bools. If you want such an array you need to set it up yourself.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

The problem is that std::vector<bool> is a specialization of the generic std::vector template, and it stores bool values in a space-efficient way unlike any other data-types (it stores one bit per bool value). That means std::vector<bool> can't be used in all the same contexts as any other vector.

You need to create your own dynamically allocated arrays to handle it:

std::vector<bool*> vpsPtr(vvsVec.size());
for (size_t i = 0; i < vvsVec.size(); ++i)
{
    vpsPtr[i] = new bool[vvsVec[i].size()];
    // TODO: Copy each and every vector element vvsVec[i][j] into vpsPtr[i][j]
}

Don't forget to delete[] the memory when you're finished with it.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621