Search code examples
c++boostboost-bindboost-range

Combination of boost range for_each, bind, copy and a back_inserter fails


I want to copy all the integers contained in a into b.

#include <vector>
#include <iterator>
#include <boost/bind.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/algorithm/copy.hpp>
void test()
{
        std::vector<std::vector<int> > a;
        std::vector<int> b;
        boost::for_each(a, boost::bind(boost::copy, _1, std::back_inserter(b)));
}

It looks so simple. I'd like to have a C++ 98 compatible one liner.

Why doesn't this compile? I have a long list of error regarding boost::bind, which I don't understand, moreover, it is multiple pages long.

The error starts with :

error C2780: 'boost::_bi::bind_t<_bi::dm_result::type,boost::_mfi::dm,_bi::list_av_1::type> boost::bind(M T::* ,A1)' : expects 2 arguments - 3 provided


Solution

  • There is a directly related question here: Can I use (boost) bind with a function template?. The error message in that question is identical, and the problem differs in that their template function is not a library one.

    The trick here is that you are intending to bind a template function boost::copy<>(), which, according to the linked question, isn't possible because the template function must be instantiated in order to be passed as a function pointer. This is also indicated here, section "Binding a template function". So, unfortunately, you need to resort to a rather long construct, which can be slightly shortened with the use of typedef (since you're in C++98, no decltype is available either):

    int main()
    {
            typedef std::vector<int> IntVec;
            std::vector<IntVec> a;
            IntVec b;
            boost::for_each(a,
                boost::bind(boost::copy<IntVec,
                std::back_insert_iterator<IntVec> >, _1, std::back_inserter(b)));
    }