Это работает, но может быть довольно неэффективно в зависимости от типов итераторов:
template <typename Range>
auto make_adjacent_range(Range const & r) {
auto n = boost::size(r);
auto b = boost::begin(r);
auto r1 = boost::make_iterator_range(b, boost::next(b, n-1));
auto r2 = r1;
r2.advance_begin(1);
r2.advance_end(1);
return boost::combine(r1, r2);
}
Live On Coliru
#include <boost/range.hpp>
#include <boost/range/combine.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <iostream>
#include <forward_list>
template <typename Range>
auto make_adjacent_range(Range const & r) {
auto n = boost::size(r);
auto b = boost::begin(r);
auto r1 = boost::make_iterator_range(b, boost::next(b, n-1));
auto r2 = r1;
r2.advance_begin(1);
r2.advance_end(1);
return boost::combine(r1, r2);
}
int main() {
std::forward_list<int> v{1,2,3,4};
for (auto p : make_adjacent_range(v))
std::cout << p.get<0>() << " " << p.get<1>() << "\n";
}
Печать
1 2
2 3
3 4
Возможно, было бы лучше сделать адаптер итератора.