Andre
Andre

Reputation: 23

A template to call a function with arguments from an iterator

I am trying to come up with a template to call functions with arguments generated from iterators. Here is an example:

// These are some functions to be called.
void f(int x) { ... }
void f(int x, int y) { ... }
void f(int x, int y, int z) { ... }

// This is a template to call functions.
template<typename I, size_t n> void apply(I iterator) {
  int a_1 = *iterator;
  int a_2 = *++iterator;
  ...
  int a_n = *++iterator;
  f(a_1, a_2,...a_n);
}

// This is an example of a function call.
apply<iterator, 2>(i);

If my iterator is a random access iterator then this task can be accomplished as this:

template<typename I, size_t ...a> void apply(I iterator) {
  f(*(iterator + a)...);
}

apply<iterator, 0, 1>(i);

I wonder if there is a way to accomplish this task for a plain input iterator.

Upvotes: 1

Views: 51

Answers (1)

Jarod42
Jarod42

Reputation: 217275

You might do something like:

template <typename It, size_t ...Is>
decltype(auto) apply_impl(std::index_sequence<Is...>, It& iterator) {
    decltype(*iterator) values[] = {(static_cast<void>(Is), *iterator++)...};
    return f(values[Is]...);
}

template <size_t N, typename It>
decltype(auto) apply(It& iterator) {
    return apply_impl(std::make_index_sequence<N>(), iterator);
}

Note: Evaluation order in function call is not guarantied, so

f((Is, *iterator++)...); // Incorrect, even in C++17

but evaluation order is left to right in initializer_list.

Upvotes: 3

Related Questions