Question

I have a container of As with

struct A { int f(); }

The container offers iterators and we can for this example assume it's an std::vector. So:

std::vector<A> As;

Now I want to copy the values provided by A::f into a second container

std::vector<int> fs;

Although I could simply iterate, as an exercide I tried to solve this with boost bind / boost iterator. What I tried so far is this:

std::copy(
     boost::make_transform_iterator
         (As.begin(), boost::bind(&A::f, _1)),
     boost::make_transform_iterator
         (As.begin(), boost::bind(&A::f, _1)),
     std::back_inserter( fs )
);

Anyone know how this can be done?

Was it helpful?

Solution

If I change the second make_transform iterator to point to end() instead of begin(), everything appears to work.

#include <boost/iterator/transform_iterator.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <vector>

struct A {
    int f() {
        static int x = 0;
        return x++;
    };
};

int main() {
    std::vector<A> As;
    As.push_back(A());
    As.push_back(A());
    As.push_back(A());

    std::vector<int> fs;

    std::copy(
            boost::make_transform_iterator(As.begin(), boost::bind(&A::f, _1)),
            boost::make_transform_iterator(As.end(),   boost::bind(&A::f, _1)),
            std::back_inserter(fs)
            );

    for (int const & x : fs)
        std::cout << x << std::endl;
}

Output

0
1
2

Alternative Solutions

You could also solve this with a functor:

struct Functor {
    int operator()(A & value) const {
        return value.f();
    }
};

std::transform(As.begin(), As.end(), std::back_inserter(fs), Functor());

or with a lambda:

std::transform(As.begin(), As.end(), std::back_inserter(fs), [](A & a) { return a.f(); });

OTHER TIPS

You want the function-like object you pass to make_transform_iterator to take an A and return the result of calling f on that A. While you can do this as you have done with bind, you can do it more explicitly with std::mem_fn:

std::copy(
  boost::make_transform_iterator
    (As.begin(), std::mem_fn(&A::f)),
  boost::make_transform_iterator
    (As.end(), std::mem_fn(&A::f)),
  std::back_inserter( fs )
);

Note that the second transform iterator should adapt As.end().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top