Boost logo

Boost Users :

Subject: [Boost-users] Implementing python's enumerate with iterator adaptors
From: Jens Auer (jensa_at_[hidden])
Date: 2012-04-17 08:03:15


Hi,

I am implementing something similar to python's enumerate using boost iterator adapter, but I am running into two problems I am unable to solve. Both problems use my Enumerate-adaptor defined as:
#include <utility>

#include <boost/iterator/iterator_adaptor.hpp>

namespace Iterator
{
// some simple wrapper to have better names than std::pair
template<typename T, typename X>
struct Enumerated
{
   Enumerated(T i, X x):
      count(i),
      value(x)
   {

   }

   T count;
   X value;
};

template< typename Iterator, typename T = typename Iterator::difference_type>
class Enumerator:
   public boost::iterator_adaptor<Enumerator<Iterator, T>,
                                  Iterator,
                                  Enumerated<T, typename Iterator::value_type>,
                                  boost::use_default,
                                  Enumerated<T, typename Iterator::reference> >
{
public:
   Enumerator():
      mCount(),
      mPos(),
      mStep()
   {

   }

   template<typename It>
   explicit Enumerator(It i, T start=T(), T step=T(1) ):
      mCount(start),
      mPos(i),
      mStep(step)
   {

   }

private:
   friend class boost::iterator_core_access;

   Enumerated<T, typename Iterator::reference > dereference() const
   {
      return Enumerated<T, typename Iterator::reference >(mCount, *mPos);
   }

   Enumerated<T, typename Iterator::reference > dereference()
   {
      return Enumerated<T, typename Iterator::reference >(mCount, mPos);
   }

   bool equal(Enumerator<Iterator, T> const& other) const
   {
      return mPos == mPos;
   }

   void increment()
   {
      mCount += mStep;
      mPos += 1;
   }

   void decrement()
   {
      mCount -= mStep;
      mPos -= 1;
   }

   void advance(typename Iterator::difference_type step)
   {
      mCount += step * mStep;
      mPos += step;
   }

   typename Iterator::difference_type distance_to(Enumerator<Iterator, T> const& other) const
   {
      return std::distance(mPos, other.mPos);
   }

   T mCount;
   Iterator mPos;
   typename Iterator::difference_type mStep;
};

template<typename Iterator, typename T>
Enumerator<Iterator, T> enumerate(Iterator i, T start=0, T step=1)
{
   return Enumerator<Iterator, T>(i, start, step);
}

When I compile the following sample program, msvc (VS2010) prints an error, but g++ does not have any problems.
#include <vector>
#include <iostream>
#include <algorithm>

void foo()
{
   std::vector<int> v;

   auto i = Iterator::enumerate(v.begin(), 0, 1);
   auto j = Iterator::enumerate(v.end(), 0, 1);

   std::for_each( i, j, [](decltype(*i) e)
   {
      std::cout << e.count << ", " << e.value << std::endl;
   });
}
Error 1 error C2665: 'std::_Debug_range2' : none of the 2 overloads could convert all the argument types d:\programme\microsoft visual studio 10.0\vc\include\xutility 728

My second problem can be reproduced with the following sample program on both msvc and g++:

#include <vector>
#include <iostream>
#include <algorithm>

void foo()
{
   std::vector<int> v;

   auto i = Iterator::enumerate(v.begin(), 0, 1);

   auto y = i->count;
   auto z = i->value;
}
MSVC:
Error 3 error C2664: 'boost::implicit_cast' : cannot convert parameter 1 from 'Iterator::Enumerated<T,X> *' to 'boost::detail::operator_arrow_proxy<T>' c:\software development\externals\include\boost\iterator\iterator_facade.hpp 326

G++:
In file included from /usr/include/boost/iterator/iterator_adaptor.hpp:15:0,
                 from Enumerate.h:18,
                 from Enumerate.cpp:1:
/usr/include/boost/iterator/iterator_facade.hpp: In static member function 'static boost::detail::operator_arrow_result<ValueType, Reference, Pointer>::type boost::detail::operator_arrow_result<ValueType, Reference, Pointer>::make(Reference) [with ValueType = Iterator::Enumerated<int, int>, Reference = Iterator::Enumerated<int, int&>, Pointer = Iterator::Enumerated<int, int>*, boost::detail::operator_arrow_result<ValueType, Reference, Pointer>::type = boost::detail::operator_arrow_proxy<Iterator::Enumerated<int, int> >]':
/usr/include/boost/iterator/iterator_facade.hpp:648:49: instantiated from 'boost::iterator_facade<I, V, TC, R, D>::pointer boost::iterator_facade<I, V, TC, R, D>::operator->() const [with Derived = Iterator::Enumerator<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, int>, Value = Iterator::Enumerated<int, int>, CategoryOrTraversal = boost::random_access_traversal_tag, Reference = Iterator::Enumerated<int, int&>, Difference = int, boost::iterator_facade<I, V, TC, R, D>::pointer = boost::detail::operator_arrow_proxy<Iterator::Enumerated<int, int> >]'
Enumerate.cpp:27:14: instantiated from here
/usr/include/boost/iterator/iterator_facade.hpp:327:49: error: no matching function for call to 'implicit_cast(Iterator::Enumerated<int, int&>*)'

Any help would be greatly appreciated,
Bets regards,
  Jens



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net