c++booleanstdvector

How to dump std::vector<bool> in a binary file?


I write tools to dump and load common objects in a binary file. In a first quick implementation, I wrote the following code for std::vector<bool>. It works, but it is clearly not optimized in memory.

template <>
void binary_write(std::ofstream& fout, const std::vector<bool>& x)
{
    std::size_t n = x.size();
    fout.write((const char*)&n, sizeof(std::size_t));
    for(std::size_t i = 0; i < n; ++i)
    {
        bool xati = x.at(i);
        binary_write(fout, xati);
    }
}

template <>
void binary_read(std::ifstream& fin, std::vector<bool>& x)
{
    std::size_t n;
    fin.read((char*)&n, sizeof(std::size_t));
    x.resize(n);
    for(std::size_t i = 0; i < n; ++i)
    {
        bool xati;
        binary_read(fin, xati);
        x.at(i) = xati;
    }
}

How can I copy the internal memory of a std::vector<bool> in my stream ?

Note : I don't want to replace std::vector<bool> by something other.


Solution

  • Answering my own question, currently validated as the best answer, but it can change if someone provides somthing better.

    A way to do that is the following. It requires to access each value, but it works.

    template <>
    void binary_write(std::ofstream& fout, const std::vector<bool>& x)
    {
        std::vector<bool>::size_type n = x.size();
        fout.write((const char*)&n, sizeof(std::vector<bool>::size_type));
        for(std::vector<bool>::size_type i = 0; i < n;)
        {
            unsigned char aggr = 0;
            for(unsigned char mask = 1; mask > 0 && i < n; ++i, mask <<= 1)
                if(x.at(i))
                    aggr |= mask;
            fout.write((const char*)&aggr, sizeof(unsigned char));
        }
    }
    
    template <>
    void binary_read(std::ifstream& fin, std::vector<bool>& x)
    {
        std::vector<bool>::size_type n;
        fin.read((char*)&n, sizeof(std::vector<bool>::size_type));
        x.resize(n);
        for(std::vector<bool>::size_type i = 0; i < n;)
        {
            unsigned char aggr;
            fin.read((char*)&aggr, sizeof(unsigned char));
            for(unsigned char mask = 1; mask > 0 && i < n; ++i, mask <<= 1)
                x.at(i) = aggr & mask;
        }
    }