Boost logo

Boost Users :

Subject: Re: [Boost-users] Implementing python's enumerate with iterator adaptors
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2012-04-17 10:37:31


On Tue, Apr 17, 2012 at 5:03 AM, Jens Auer <jensa_at_[hidden]> wrote:

> 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 = typenameIterator::difference_type>
>
****
>
> class Enumerator:****
>
> public boost::iterator_adaptor<Enumerator<Iterator, T>,****
>
> Iterator,****
>
> Enumerated<T, typenameIterator::value_type>,
> ****
>
> boost::use_default,****
>
> Enumerated<T, typenameIterator::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);**
> **
>
> }
>

Pretty sure this latter overload of dereference will never get called, and
it wouldn't compile anyway ("mPos" should be "*mPos").

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

Error already noted here.

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

Consider ++mPos?

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

Similarly, consider --mPos?

> ****
>
> ** **
>
> 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
>

Can you give more context to the error message?

> ****
>
> 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
>

As Mateusz has noted, I believe you're running into

https://svn.boost.org/trac/boost/ticket/5697

which was just recently fixed in trunk. See if that resolves your problem.

[snip compiler trace]

- Jeff



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