mardi 3 janvier 2017

Map an iterator to an iterator over a specific field (can use Boost)

Suppose I have a particular algorithm that works over a range of integers. The function will then take two iterators over this range and do its work.

template <typename It>
void doWork(It begin, It end) {
    int x = *begin; // range is over integers
    // ...
}

Assume then I have two data structures:

struct S { int x; }

using TupleList = std::vector<std::tuple<int, double>>;
using SList = std::vector<S>;

I'd like to use the algorithm on both a TupleList and a SList (separately). However, direct iterators won't work as TupleList and SList do not directly contain integers.

One solution would be to additionally pass to the algorithm a functor to unwrap the iterators:

template <typename It, typename Unwrap>
void doWork(It begin, It end, Unwrap unwrap) {
    int x = unwrap(*begin);
    // And so on
}
// -----
auto Sunwrapper = [](const S& s) { return s.x; }
doWork(begin(Slist), end(Slist), Sunwrapper);

But I'd prefer to keep the function tidy. Is there a way in C++ (plus Boost) to automatically create an iterator from such an unwrapper function?

auto unwrappedBegin = some_magical_factory(begin(Slist), Sunwrapper);
auto unwrappedEnd   = some_magical_factory(end  (Slist), Sunwrapper);

doWork(unwrappedBegin, unwrappedEnd);

Aucun commentaire:

Enregistrer un commentaire