Today, I will require your help to improve an iterator adapter. The goal of the adapter (I called it get_iterator
) is to adapt std::map
iterators for example: map iterators return std::pair
instances, a get_iterator<0, std::map<...>::iterator>
will provide an iterator which iterates through the keys while a get_iterator<1, std::map<...>::iterator>
will provide an iterator which iterates through the values. Here is my implementation:
Here is the header file:
template<std::size_t N, typename Iterator>
class get_iterator:
public std::iterator<
typename std::iterator_traits<Iterator>::iterator_category,
typename std::remove_reference<decltype(std::get<N>(*Iterator{}))>::type,
typename std::iterator_traits<Iterator>::difference_type>
{
private:
Iterator _current;
public:
using iterator_type = Iterator;
using value_type = typename std::remove_reference<decltype(std::get<N>(*_current))>::type;
using pointer = value_type*;
using reference = value_type&;
get_iterator();
explicit get_iterator(Iterator it);
template<typename U>
get_iterator(const get_iterator<N, U>& other);
template<typename U>
auto operator=(const get_iterator<N, U>& other)
-> get_iterator&;
auto base() const
-> Iterator;
auto operator*() const
-> reference;
auto operator->() const
-> pointer;
auto operator++()
-> get_iterator&;
auto operator++(int)
-> get_iterator&;
auto operator--()
-> get_iterator&;
auto operator--(int)
-> get_iterator&;
};
And here is the implementation file:
template<std::size_t N, typename Iterator>
get_iterator<N, Iterator>::get_iterator()
= default;
template<std::size_t N, typename Iterator>
get_iterator<N, Iterator>::get_iterator(Iterator it):
_current(it)
{}
template<std::size_t N, typename Iterator>
template<typename U>
get_iterator<N, Iterator>::get_iterator(const get_iterator<N, U>& other):
_current(other.base())
{}
template<std::size_t N, typename Iterator>
template<typename U>
auto get_iterator<N, Iterator>::operator=(const get_iterator<N, U>& other)
-> get_iterator&
{
if (&other != this)
{
_current = other.base();
}
return *this;
}
template<std::size_t N, typename Iterator>
auto get_iterator<N, Iterator>::base() const
-> Iterator
{
return _current;
}
template<std::size_t N, typename Iterator>
auto get_iterator<N, Iterator>::operator*() const
-> reference
{
return std::get<N>(*_current);
}
template<std::size_t N, typename Iterator>
auto get_iterator<N, Iterator>::operator->() const
-> pointer
{
return &(operator*());
}
template<std::size_t N, typename Iterator>
auto get_iterator<N, Iterator>::operator++()
-> get_iterator&
{
++_current;
return *this;
}
template<std::size_t N, typename Iterator>
auto get_iterator<N, Iterator>::operator++(int)
-> get_iterator&
{
auto tmp = *this;
++_current;
return tmp;
}
template<std::size_t N, typename Iterator>
auto get_iterator<N, Iterator>::operator--()
-> get_iterator&
{
--_current;
return *this;
}
template<std::size_t N, typename Iterator>
auto get_iterator<N, Iterator>::operator--(int)
-> get_iterator&
{
auto tmp = *this;
--_current;
return tmp;
}
I don't provide operator==
, operator<
and their friends in this question since their implementation is trivial and mimicks this of std::reverse_iterator
. Are there functions lacking in the interface or things to be improved in the implementation? Also, do you have any idea of a more suitable name for such an iterator adaptor?