#include <iostream>
#include <iterator>
#include <type_traits>
template<typename Fn>
struct CallRepeatedlyIterator
{
using difference_type = unsigned;
using value_type = typename std::result_of<Fn()>::type;
using pointer = value_type *;
using reference = value_type &;
using iterator_category = std::input_iterator_tag;
bool is_end;
union {
Fn fn;
};
union {
value_type buffer;
};
value_type operator*() const
{
return buffer;
}
CallRepeatedlyIterator & operator++()
{
buffer = fn();
return *this;
}
CallRepeatedlyIterator()
: is_end(true)
{}
explicit CallRepeatedlyIterator(Fn f)
: is_end(false)
{
new (&fn) Fn(f);
new (&buffer) value_type(fn());
}
bool operator==(CallRepeatedlyIterator const & other) const
{
return is_end && other.is_end;
}
bool operator!=(CallRepeatedlyIterator const & other) const
{
return !(*this == other);
}
};
int foo()
{
static int i = 42;
std::cerr << "foo() called" << std::endl;
return ++i;
}
int main() {
using fn_type = decltype(foo);
CallRepeatedlyIterator<fn_type *> it(foo);
CallRepeatedlyIterator<fn_type *> the_end;
int calls = 4;
for (; it != the_end; ++it)
{
std::cout << *it << std::endl;
if (! (--calls)) break;
}
}