Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using my custom iterator with STL algorithms

I'm trying to create my own iterator, and I've got it working as expected with the std::generate algorithm. However, when I try std::max_element of std::find, I get some cryptic errors.

Here is the interface for my iterator:

template <typename GridT,
          typename GridPtr,
          typename GridRef,
          template <typename> class ShapeT>
class GridIterator
{
public:
    typedef GridIterator<GridT, GridPtr, GridRef, ShapeT> Iterator;

    // Iterator traits - typedefs and types required to be STL compliant
    typedef std::ptrdiff_t           difference_type;
    typedef typename GridT::Element  value_type;
    typedef typename GridT::Element* pointer;
    typedef typename GridT::Element& reference;
    typedef size_t                      size_type;
    std::forward_iterator_tag          iterator_category;


    GridIterator(GridT& grid,
                 ShapeT<typename GridT::Resolution> shape,
                 Index iterStartIndex);

    ~GridIterator();

    Iterator& operator++();
    Iterator  operator++(int);

    typename GridT::Element& operator*();
    typename GridT::Element* operator->();

    bool operator!=(const GridIterator& rhs) const;
    bool operator==(const GridIterator& rhs) const;
    ....

}

Using std::find, I get this error:

In file included from /usr/include/c++/4.6/algorithm:63:0, from ./grid/Map_Grid.h:11, from main.cpp:4: /usr/include/c++/4.6/bits/stl_algo.h: In function ‘_IIter std::find(_IIter, _IIter, const _Tp&) [with _IIter = Map::GridIterator<Map::Grid<double, int>, Map::Grid<double, int>, Map::Grid<double, int>&, Map::Rectangle>, _Tp = int]’: main.cpp:103:50: instantiated from here /usr/include/c++/4.6/bits/stl_algo.h:4404:45: error: no matching function for call to ‘__iterator_category(Map::GridIterator<Map::Grid<double, int>, Map::Grid<double, int>, Map::Grid<double, int>&, Map::Rectangle>&)’ /usr/include/c++/4.6/bits/stl_algo.h:4404:45: note: candidate is: /usr/include/c++/4.6/bits/stl_iterator_base_types.h:202:5: note: template typename std::iterator_traits::iterator_category std::__iterator_category(const _Iter&)

With std::max_element :

In file included from /usr/include/c++/4.6/bits/char_traits.h:41:0, from /usr/include/c++/4.6/ios:41, from /usr/include/c++/4.6/ostream:40, from /usr/include/c++/4.6/iostream:40, from ./grid/Map_GridIterator.h:7, from ./grid/Map_Grid.h:8, from main.cpp:4: /usr/include/c++/4.6/bits/stl_algobase.h: In function ‘const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = Map::GridIterator<Map::Grid<double, int>, Map::Grid<double, int>, Map::Grid<double, int>&, Map::Rectangle>]’: main.cpp:102:60: instantiated from here /usr/include/c++/4.6/bits/stl_algobase.h:215:7: error: no match for ‘operator<’ in ‘__a < __b’ /usr/include/c++/4.6/bits/stl_algobase.h:215:7: note: candidates are: /usr/include/c++/4.6/bits/stl_pair.h:207:5: note: template<class _T1, class _T2> constexpr bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) /usr/include/c++/4.6/bits/stl_iterator.h:291:5: note: template bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&) /usr/include/c++/4.6/bits/stl_iterator.h:341:5: note: template<class _IteratorL, class _IteratorR> bool std::operator<(const std::reverse_iterator<_IteratorL>&, const std::reverse_iterator<_IteratorR>&) /usr/include/c++/4.6/bits/stl_iterator.h:1049:5: note: template<class _IteratorL, class _IteratorR> bool std::operator<(const std::move_iterator<_IteratorL>&, const std::move_iterator<_IteratorR>&) /usr/include/c++/4.6/bits/stl_iterator.h:1055:5: note: template bool std::operator<(const std::move_iterator<_Iterator>&, const std::move_iterator<_Iterator>&) /usr/include/c++/4.6/bits/basic_string.h:2510:5: note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::basic_string<_CharT, _Traits, _Alloc>&, const std::basic_string<_CharT, _Traits, _Alloc>&) /usr/include/c++/4.6/bits/basic_string.h:2522:5: note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::basic_string<_CharT, _Traits, _Alloc>&, const _CharT) /usr/include/c++/4.6/bits/basic_string.h:2534:5: note: template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const _CharT*, const std::basic_string<_CharT, _Traits, _Alloc>&) /usr/include/c++/4.6/bits/stl_vector.h:1290:5: note: template<class _Tp, class _Alloc> bool std::operator<(const std::vector<_Tp, _Alloc>&, const std::vector<_Tp, _Alloc>&) /usr/include/c++/4.6/tuple:586:5: note: template<class ... _TElements, class ... _UElements> bool std::operator<(const std::tuple<_TElements ...>&, const std::tuple<_Elements ...>&)

like image 686
Q-bertsuit Avatar asked Oct 21 '25 04:10

Q-bertsuit


1 Answers

You are missing a typedef keyword for declaring an alias indicating the iterator category:

// Iterator traits - typedefs and types required to be STL compliant
//...
typedef std::forward_iterator_tag iterator_category;
~~~~~~^

Without the typedef, you are actually declaring a data member.

To avoid such mistakes, you can utilize the std::iterator class template as a base class, instead of defining those aliases on your own:

class GridIterator : public std::iterator<std::forward_iterator_tag
                                        , typename GridT::Element>
like image 131
Piotr Skotnicki Avatar answered Oct 23 '25 20:10

Piotr Skotnicki



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!