1v0
1v0

Reputation: 352

Using iterator_traits to deduce value type from pair of iterators

I have a type

typedef std::pair<ConstIterator, ConstIterator> Range;

with

typedef typename std::vector<T>::const_iterator ConstIterator;

I would now like to use std::iterator_traits to deduce the type the iterators of a Range are pointing to.

Could anybody please tell me how I can achieve this, from an object of type Range?

Upvotes: 1

Views: 473

Answers (3)

Quentin
Quentin

Reputation: 63154

You're explicitly allowed to add template specializations to the std namespace for user-defined types (thanks Barry for the precision !). If you rework your Range to be an actual type (not just a typedef), you can do this :

struct Range : std::pair<ConstIterator, ConstIterator> {
    using std::pair<ConstIterator, ConstIterator>::pair;
};

namespace std {
    template <>
    struct iterator_traits<Range> : iterator_traits<ConstIterator> {};
}

When you buff your Range a bit, I expect this to evolve into :

namespace std {
    template <class T>
    struct iterator_traits<Range<T>> : iterator_traits<T> {};
}

Upvotes: 0

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275896

This will support both your pair based ranges, and most iterables:

template<class R>
struct value_type {
  using iterator_type = decltype( std::begin(std::declval<R>()) );
  using type=typename std::iterator_traits<iterator_type>::value_type;
};
template<class It>
struct value_type<std::pair<It,It>> {
  using type=typename std::iterator_traits<It>::value_type;
};
template<class X>
using value_t = typename value_type<X>::type;

note that the value type of a const iterator is a non-const value.

The above is not SFINAE friendly -- an industrial quality one would be.

Upvotes: 0

Barry
Barry

Reputation: 303890

You can write a type trait, partially specialized on a pair:

template <typename T>
struct value_type {
    using type = typename std::iterator_traits<T>::value_type;
};

template <typename T>
struct value_type<std::pair<T, T>>
: value_type<T>
{ };

Upvotes: 1

Related Questions