CharmCityChile
CharmCityChile

Reputation: 41

C++ iterator to specific type

How do you create an iterator that restricts the underlying type? For example, I want to create functions like the following:

void functionThatOperatesOnPointSequence(PointIterator begin, PointIterator end);

Where the sequence of Point objects may be stored in different ways. My use case would have the additional complexity that Point would be a templated type. i.e. Point<int> or Point<double> would be equally valid.

Solutions using C++11/14 or Boost are valid and preferable.

Upvotes: 4

Views: 878

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275310

Here is a bit of template metaprogramming. is_template_instance takes a template that takes only types, and a type, and returns true if that second type is an instance of the first template.

template<template<class...>class Z, class T>
struct is_template_instance:std::false_type{};
template<template<class...>class Z, class...Ts>
struct is_template_instance<Z,Z<Ts...>>:std::true_type{};

Now, we want to query the value type of the iterator. We can use std::iterator_traits directly, or use an alias like this:

template<class It>
using it_value_type = typename std::iterator_traits<It>::value_type;

We compose the two above to write a is_point_iterator template:

template<class It>
using is_point_iterator = is_template_instance< Point, it_value_type<It> >;

Note that if you pass this non-iterators, it may not fail in a friendly manner, or it may return the wrong result (std::iterator_traits does not guarantee sensible return values for non-iterators).

But that tends to be caught in template bodies.

template<class PointIterator,
  class=std::enable_if_t< is_point_iterator<PointIterator>::value >
>
void functionThatOperatesOnPointSequence(PointIterator begin, PointIterator end) {
  // ...
}

there is only limited usefulness.

You could extract the value type from the PointIterator in a more SFINAE friendly manner, for example:

template<class It>
using it_value_type = std::decay_t<decltype(*std::declval<It>())>;

if you need SFINAE support.

Upvotes: 2

Related Questions