mercredi 16 mars 2016

How to implement flatmap using rangev3 ranges

I have a pretty simple flatmap function implemented in C++ for std::vectors, but it has been suggested that ranges are generally better. Here's the vector based solution.

// flatmap: [A] -> (A->[B]) -> [B]    
template<typename T, typename FN>
static auto flatmap(const std::vector<T> &vec, FN fn) 
     -> std::vector<typename std::remove_reference<decltype(fn(T())[0])>::type> {
    std::vector<typename std::remove_reference<decltype(fn(T())[0])>::type> result;
    for(auto x : vec) {
        auto y = fn(x);
        for( auto v : y ) {
            result.push_back(v);
        }
    }
    return result;
};

It has also been suggested that I use iterators, but that breaks the nice composability of the function: map(filter(flatmap( V, fn), fn2), fn3)

I would assume that in a range-v3 world I'd be aiming for writing the above as

auto result = v | flatmap(fn) | filter(fn2) | transform(fn3);

It feels like flatmap should just be a trivial combination of views::for_each, yield_from and transform, but I'm struggling to work out how to hook them all together.

Aucun commentaire:

Enregistrer un commentaire