Tuesday 30 August 2016

c++ - 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 GridPtr,
typename GridRef,
template class ShapeT>
class GridIterator
{
public:
typedef GridIterator 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 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*,
Map::Grid&, 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*, Map::Grid&, 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*,
Map::Grid&, 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 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 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 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 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 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 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 bool std::operator<(const std::vector<_Tp, _Alloc>&, const std::vector<_Tp, _Alloc>&) /usr/include/c++/4.6/tuple:586:5: note: template bool std::operator<(const std::tuple<_TElements
...>&, const std::tuple<_Elements ...>&)



Answer




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                                        , typename GridT::Element>

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...