Reputation: 23
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
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