1
votes

If I have a range and I want to transform adjacent pairs is there a boost range adaptor to do this?

for example

std::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);

auto b = a 
   | boost::range::transformed([](int x, int y){return x+y;});

and the output would be

3, 5

EDIT

I have made an attempt at a range adaptor

    // Base class for holders
template< class T >
struct holder
{
    T val;
    holder( T t ) : val(t)
    { }
};


// Transform Adjacent

template <typename BinaryFunction> struct transformed_adjacent_holder 
    : holder
    {
    transformed_adjacent_holder(BinaryFunction fn) : holder<BinaryFunction>(fn)
};

template <typename BinaryFunction> transform_adjacent
   (BinaryFunction fn) 
   { return transformed_adjacent_holder<BinaryFunction>(fn); }

template< class InputRng, typename BinFunc>
inline auto Foo(const InputRng& r, const transformed_adjacent_holder<BinFunc> & f)
    -> boost::any_range
    < std::result_of(BinFunc)
    , boost::forward_traversal_tag
    , int
    , std::ptrdiff_t
    > 

{
    typedef boost::range_value<InputRng>::type T;
    T previous;
    auto unary = [&](T const & t) {auto tmp = f.val(previous, t); previous = t; return tmp; };
    return r | transformed(unary);
}

However I don't know how to deduce the return type of the | operator. If I can do this then the adaptor is almost solved.

2
There isn't a boost::range::adjacent_differenced, akin to std::adjacent_difference, like there is boost::range::transformed (which is akin to std::transform)Caleth

2 Answers

2
votes

You can maintain a dummy variable

 int prev=0;
 auto b = a | transformed([&prev](int x){int what = x+prev;prev=x;return what;});
2
votes

No. But you can use the range algorithm:

Live On Wandbox

#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <vector>
#include <iostream>

using namespace boost::adaptors;

int main() {
    std::vector<int> a { 1,2,3 };

    auto n = a.size();
    if (n > 0) {
        auto out = std::ostream_iterator<int>(std::cout, "\n");
        boost::transform(a, a | sliced(1, n), out, [](int x, int y) { return x + y; });
    }
}

This uses the binary transform on a and a slice of itself.

Prints

3
5