I have a question, which very likely has been asked like this before, because I think what I want is something that a considerable amount of people would want. However I could n
Sure, we can just write our own iterator:
template
class func_iterator
: std::iterator<
std::random_access_iterator_tag,
typename std::result_of::type,
Value,
typename std::result_of::type,
typename std::result_of::type>
{ .. };
This iterator needs three things: a function (F f
), the current value and the step (Value value, step
). Dereferencing will calculate the value of the function each time:
using T = typename std::result_of::type;
T operator*() { return f(value); }
Selected iterating functions (omitting postfix since they look the same):
func_iterator& operator++() {
value += step;
return *this;
}
func_iterator& operator--() {
value -= step;
return *this;
}
func_iterator operator+(Value amt) {
return func_iterator{f, value + amt * step, step};
}
Difference between iterators (for std::distance
) and equality:
Value operator-(const func_iterator& rhs) {
assert(step == rhs.step);
return (value - rhs.value) / step;
}
bool operator==(const func_iterator& rhs) {
return value == rhs.value && step == rhs.step;
}
And finally a function to make an iterator for us:
template
func_iterator make_func_iterator(F f, Value v, Value s = 1) {
return func_iterator{f, v, s};
}
Putting that together, I can do something like:
auto sq_it = make_func_iterator([](int x){return x*x;}, 1);
std::vector squares{sq_it, sq_it + 10}; // v now holds {1, 4, 9, 16, ..., 100}
Or just:
// get a bunch of even numbers, complicatedly:
auto ident = make_func_iterator([](int x){return x;}, 2, 2);
std::vector evens{ident, ident+200}; // holds {2, 4, ..., 400}