17

When writing generic functions for "iterator" ranges I usually do:

template <typename Iter> auto func(Iter &first, Iter &last)
{
    using IterType = typename std::decay<decltype(*first)>::type;
    ...
}

Another way seems to be:

template <typename Iter> auto func(Iter &first, Iter &last)
{
    using IterType = typename std::iterator_traits<Iter>::value_type;
    ...
}

And yet a third:

template <typename Iter> auto func(Iter &first, Iter &last)
{
    using IterType = typename Iter::value_type;
    ...
}

Without applying iterator_traits.

In theory, my functions should only receive iterators as first and last and the second form would ideally (imho) the most idiomatic way to get the type. But is using typename std::decay<decltype(*first)>::type the most generic idiom in order to not impose restrictions to Iter like having a value_type defined?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mementum
  • 3,153
  • 13
  • 20

2 Answers2

22

The second is the most idiomatic one.

  • The first does not work with proxies (std::vector < bool > )
  • The third does not work with pointers.
10

None of these are quite idiomatic; you should be passing iterators by value, not by reference. Here's the signature for for_each in gcc 4.9:

template<typename _InputIterator, typename _Function>
_Function
for_each(_InputIterator __first, _InputIterator __last, _Function __f)

As you can see, it's passed by value. Your functions will not work in the idiomatic usage:

func(v.begin(), v.end()); // error, binding non-const ref to rvalue!

Also, going through iterator_traits is more than just idiomatic, it's basically required. Insofar as the STL is concerned, such typedefs are defined solely through iterator_traits: http://en.cppreference.com/w/cpp/concept/ForwardIterator. iterator_traits provides reasonable defaults for the generic case, but it can be specialized (as it is for pointers) to do different things. Not going through iterator_traits basically means someone could write a compliant iterator that worked with the STL but not your code.

Nir Friedman
  • 17,108
  • 2
  • 44
  • 72