OvenでPythonで言うところのenumerate関数を作る。(何番煎じ?)

enumerate.hpp

#ifndef HWM_ENUMERATE_HPP_
#define HWM_ENUMERATE_HPP_

#include <boost/tuple/tuple.hpp>
#include <pstade/pass_by.hpp>
#include <pstade/result_of.hpp>
#include <pstade/oven/any_range.hpp>
#include <pstade/oven/counting.hpp>
#include <pstade/oven/distance.hpp>
#include <pstade/oven/pack.hpp>
#include <pstade/oven/range_value.hpp>
#include <pstade/oven/range_traversal.hpp>
#include <pstade/oven/zipped.hpp>
#include <pstade/oven/zipped_with.hpp>

namespace hwm
{
namespace enumerate_detail
{
 using namespace pstade;
 using namespace pstade::oven;

 struct little
 {
  template< class Myself, class Range, class BinaryFun = void>
  struct apply
  {
   typedef
    typename range_value<Range>::type
   org_value_t;

   typedef
    typename range_traversal<Range>::type
   org_traversal_t;

   typedef
    typename pass_by_value<BinaryFun>::type
   fun_t;

   typedef
    typename any_range<
     typename result_of<fun_t const(unsigned int, org_value_t)>::type,
     org_traversal_t
    > const
   range_t;

   typedef range_t type;
  };

  template< class Result, class Range, class BinaryFun >
  Result call(Range &r, BinaryFun &f) const
  {
   return pack(counting((unsigned int)0, (unsigned int)(r|distance)), r)|zipped_with(f);
  }

  template< class Myself, class Range >
  struct apply<Myself, Range>
  {
   typedef 
    typename range_value<Range>::type
   org_value_t;

   typedef
    typename range_traversal<Range>::type
   org_traversal_t;

   typedef
    typename any_range<
     boost::tuples::tuple<unsigned int, org_value_t>,
     org_traversal_t
    > const
   range_t;

   typedef range_t type;
  };

  template<class Result, class Range>
  Result call(Range &r) const
  {
   return pack(counting((unsigned int)0, (unsigned int)(r|distance)), r)|zipped;
  }
 };

} //namespace enumerate_detail
PSTADE_OVEN_LITTLE_TO_ADAPTOR(enumerate, (enumerate_detail::little))
} //namespace hwm

#endif //HWM_ENUMERATE_HPP_

test.cpp

#include <iostream>
#include <vector>
#include <boost/tuple/tuple_io.hpp>
#include <pstade/oven/foreach.hpp>
#include <pstade/oven/io.hpp>

#include "enumerate.hpp"

struct pack_
{
 pack_(int i, int j)
  : i_(i)
  , j_(j)
 {}
 
 pack_() {}

 int i_;
 int j_;
};

namespace std
{
 ostream& operator<<(ostream& ost, ::pack_ const &p)
 {
  return ost << '(' << p.i_ << ',' << p.j_ << ')';
 }
}

struct make_pack_
{
 typedef pack_ result_type;
 result_type operator()(int i, int j) const {
  return pack_(i, j);
 }
};

int plus_(int i, int j) { return i + j; }

int main()
{
 using namespace pstade::oven;
 int v[] = {5, 6, 7, 8, 9};

 PSTADE_OVEN_FOREACH(elem, v|hwm::enumerate) {
  std::cout << elem << std::endl;
 }

 PSTADE_OVEN_FOREACH(elem, v|hwm::enumerate(&::plus_)) {
  std::cout << elem << std::endl;
 }
 
 PSTADE_OVEN_FOREACH(elem, v|hwm::enumerate(make_pack_())) {
  std::cout << elem << std::endl;
 }
}

さて、この実装ではインデックス(に使ってるcounting_range)かなんかの型の違いで警告が出てしまいまする・・・どう回避したものか・・・


ところで携帯からの投稿なのでうまくいくかどうか