Search code examples
c++11boostboost-tuples

copying data between different types of containers


I am trying to copy data from one container type to another container type, the containers are both double dimensional vectors, i am using boost::combine and boost::tie to iterate over the containers, the code builds fine but throws a bad_alloc when run. i am not able to understand why a simple code like below throw bad_alloc, what am i doing wrong ?? also what are the other strategies to copy data between containers when they are multi-dimensional.

#include <vector>
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/range/combine.hpp>
#include <algorithm>
#include <tuple>

int
main(int ac, char **av)
{
    std::vector<std::vector<int>> bv(1, std::vector<int>(4, 99));
    boost::container::small_vector<boost::container::small_vector<int, 4>, 1> bvv;
    decltype(bv)::value_type v1;
    decltype(bvv)::value_type v2;
    BOOST_FOREACH(boost::tie(v1, v2), boost::combine(bv, bvv)){
        for ( auto &e : v1 )
            v2.push_back( e );
    }
    return 0;
}

Solution

  • boost::combine expects the passed arguments have the same size. In your case bv has 1 vector<int> but bvv has 0 elements of boost::container::small_vector type. And for this reason program crashed. You can add 1 to constructor of small_vector

    boost::container::small_vector<boost::container::small_vector<int, 4>, 1> bvv(1);
    

    then program works, but it doesn't do what you expected. v2 vector is created as new local variable in main function and it is filled by elements of first vector from bv container. I think you want to fill bvv vector by elements from bv container.

    If you want to modify bvv vector you should pass it as parameter to boost::tie function.

        BOOST_FOREACH(boost::tie(bv[0], bvv[0]), boost::combine(bv, bvv)){
           std::copy (bv[0].begin(), bv[0].end(), std::back_inserter(bvv[0]));
        }
    

    but it only works if bvv and bv have one element.

    Maybe you should not use boost::combine and just write loop to iterate over all elements in bv and add them to bvv container.

        for (const auto& v : bv)
        {
            bvv.push_back(boost::container::small_vector<int, 4>());
            std::copy (v.begin(), v.end(), std::back_inserter(bvv.back()));
        }