読者です 読者をやめる 読者になる 読者になる

adjacent_zipped

C++

OvenToBoostのexperimentalに少し前から入っていたadjacent_zipped Rangeアダプタを、コードを整理し、ドキュメントを書いて本流に移動しました。
このRangeアダプタは、元となったRangeを、隣接要素のタプルのRangeに変換します。

#include <iostream>
#include <vector>
#include <boost/range/adaptor/adjacent_zipped.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/tuple/tuple_io.hpp>

void print(const boost::tuple<int, int>& t)
{
    std::cout << t << std::endl;
}

int main()
{
    const std::vector<int> v = {1, 2, 3, 4, 5};
    boost::for_each(v | boost::adaptors::adjacent_zipped, print);
}
(1 2)
(2 3)
(3 4)
(4 5)

これは内部的には、[begin(r), prior(end(r)))とr | dropped(1)をzipしたものです(0要素でも扱えるようにしてあります)。
boost::zip_iteratorには異なる長さのRangeを渡せないので、prior()が必要になっています。それによってRangeの要件がForwardRangeではなくBidirectionalRangeになっています。


要素がタプルのままだと使いにくいので、fused_for_each()でタプルを展開するといいでしょう。

#include <iostream>
#include <vector>
#include <boost/range/adaptor/adjacent_zipped.hpp>
#include <boost/range/algorithm_ext/fused_for_each.hpp>
#include <boost/fusion/include/boost_tuple.hpp>

void print(int first, int second)
{
    std::cout << '(' << first << ' ' << second << ')' << std::endl;
}

int main()
{
    const std::vector<int> v = {1, 2, 3, 4, 5};
    boost::fused_for_each(v | boost::adaptors::adjacent_zipped, print);
}
(1 2)
(2 3)
(3 4)
(4 5)