for_eachでループカウンタを付加する方法

std::for_eachにループカウンタを入れる方法 - 名古屋313の日記


元ネタの質問というのがどういうものなのか見てないですけど、
よくある要望としては、for_eachでコンテナの要素とループカウンタの両方がほしい、というところじゃないかと思います。
この要望に対する回答としては、以下のように、RangeとCounting Rangeを綴じ合わせ、
要素にループカウンタの情報を付加する、というものになります。


Ovenの場合はcountingとzippedを使う

#include <iostream>
#include <vector>
#include <pstade/oven/algorithm.hpp>
#include <pstade/oven/initial_values.hpp>
#include <pstade/oven/zipped.hpp>
#include <pstade/oven/counting.hpp>

namespace oven = pstade::oven;

void disp(boost::tuples::tuple<int, int> t)
{
    int x, i;
    boost::tie(x, i) = t;

    std::cout << x << "," << i << std::endl;
}

int main()
{
    const std::vector<int> v = oven::initial_values(3, 1, 4);

    oven::for_each(boost::make_tuple(v, oven::counting(0, v.size())) | oven::zipped, &disp);
}
3,0
1,1
4,2


Boost.RangeExの場合はcounting_rangeとcombineを使う

#include <iostream>
#include <vector>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/combine.hpp>
#include <boost/range/counting_range.hpp>
#include <boost/assign/std/vector.hpp>

void disp(boost::tuples::tuple<int, int> t)
{
    int x, i;
    boost::tie(x, i) = t;

    std::cout << x << "," << i << std::endl;
}

using namespace boost::assign;

int main()
{
    std::vector<int> v;
    v += 3, 1, 4;

    boost::for_each(
        boost::combine(v, boost::counting_range(0, static_cast<int>(v.size()))), &disp);
}

Ovenの場合には、boost::zip_iteratorが異なる要素数をもつRange同士のイテレーションをサポートしてくれれば
oven::countingの代わりにoven::iterationを使えて、(sizeを計算しなくていいので)さらに効率よくできそうですね。
RangeExにはiterationないです。



追記:

ScalaにはzipWithIndexというズバリそのものな関数が用意されているようです。

http://www.scala-lang.org/docu/files/api/scala/Iterator.html#zipWithIndex

http://twitter.com/bleis/statuses/13316669682