6

I have a vector of bool which I want to copy in a int container of bigger size. Is there a fast way to do this?

To clarify, is there a smarter way to achieve this?

#include <vector>
#include <cstdint>
#include <iostream>
#include <climits>
#include <cassert>


inline size_t bool2size_t(std::vector<bool> in) {
    assert(sizeof(size_t)*CHAR_BIT >= in.size());
    size_t out(0);

    for (size_t vecPos = 0; vecPos < in.size(); vecPos++) {
        if (in[vecPos]) {
            out += 1 << vecPos;
        }
    }

    return out;
} 

int main () {
    std::vector<bool> A(10,0);
    A[2] = A[4] = 1;

    size_t B = bool2size_t(A);

    std::cout << (1 << 2) + (1 << 4) << std::endl;
    std::cout << B << std::endl;
}

I'm looking for something like a memcpy which I can use on a subbyte level.

magu_
  • 4,766
  • 3
  • 45
  • 79
  • you want to copy a vector to another vector? – Engineer2021 Jul 28 '14 at 11:54
  • 3
    Depending on whether you need a dynamically sized container, you should consider using std::bitset instead, with its to_ulong() method. – Sneftel Jul 28 '14 at 11:56
  • I wan't to copy the memory of `vector` into an `int` which was set to zero. The important part is that the size of it might be not divable by 8. – magu_ Jul 28 '14 at 11:56
  • @staticx: `vector`, unfortunately, isn't really a `vector`. Among others, it's implementation-defined whether you can get a `ForwardIterator` from it or not... – DevSolar Jul 28 '14 at 11:57
  • 1
    With C++11, you could probably use `std::hash()` on your boolean vector to achieve what you want. – jxh Jul 28 '14 at 12:07
  • @jxh. Sorry now you lost me. Could you elaborate a little more? – magu_ Jul 28 '14 at 12:12
  • To be honest, I am not sure I entirely understand your question. If you just want to turn the boolean vector into a number that has a particular form if it fits within a certain integer type, `std::hash()` might do it for you. If you want something else, then... – jxh Jul 28 '14 at 12:19
  • @jxh. Yes exactly that is what I want. But I'm afraid I can still not follow. – magu_ Jul 28 '14 at 12:39

2 Answers2

15

Here is an example using C++11:

#include <vector>
#include <iostream>
#include <numeric>

using namespace std;

int main() {
    vector<bool> b(10,0);
    b[2] = b[4] = 1;
    int i;
    i = accumulate(b.rbegin(), b.rend(), 0, [](int x, int y) { return (x << 1) + y; });
    cout << i << endl;
}

Another solution that uses GCC internals for vector<bool> and is more efficient:

#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

int main() {
    vector<bool> b(10,0);
    b[2] = 1;
    b[4] = 1;
    auto p = b.begin()._M_p;
    cout << *p << endl;
}

Note though that it is not recommended to use vector<bool> since it is a problematic specialization of vector<T> and has a slightly different API. I recommend using vector<char> instead, or creating your own Bool wrapper class with implicit cast to and from bool.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
tohava
  • 5,344
  • 1
  • 25
  • 47
  • Are you positive this is going to work? I was once taught to basically stay away from any kind of iterators in relation to `vector`... – DevSolar Jul 28 '14 at 12:02
  • I didn't do any performance rating but isn't this about as slow as the loop? Maybe I'm wrong tough and I misunderstood something. – magu_ Jul 28 '14 at 12:43
  • You are right, it will likely be as slow. I thought by "smarter way" you meant shorter, not faster. – tohava Jul 28 '14 at 12:48
  • @magu_ - I added a more efficient solution. It only works for gcc though. – tohava Jul 28 '14 at 12:53
  • 2
    Just be aware that the solution is implementation specific and probably not portable across compilers. For example, `clang` will *not* compile that code – Krumelur Jul 28 '14 at 13:03
4

The implementation may store the vector<bool> as a bit set the way you want, but it is not required to do so. If you can change the type, look at the bitset template class, which works the same way, but implements e.g. to_ulong.

See this question.

Edit: If Boost is OK, there is dynamic_bitset, which will do the chunking for you if you need to store more than a unsigned long can hold.

Community
  • 1
  • 1
Krumelur
  • 31,081
  • 7
  • 77
  • 119
  • Hm I was trying to avoid bitset since I need to dynamically allocate the vector. Is it possible to dynamically allocate bitset - I don't need to resize it. – magu_ Jul 28 '14 at 11:58
  • Well, an unsigned long will only hold 64 bits. If you exceed that you would have to use some other means, such as chunking them. – Krumelur Jul 28 '14 at 11:59
  • Hm yes, true. I don't really want to use boost. But I might simply implement `bitset` and live with the overhead. There are luckely not so many in memory of them at once. – magu_ Jul 28 '14 at 12:14