Skip to content

Instantly share code, notes, and snippets.

@kerrytazi
Last active February 1, 2026 14:07
Show Gist options
  • Select an option

  • Save kerrytazi/df82b823c4488406ba19886f1df5a6d8 to your computer and use it in GitHub Desktop.

Select an option

Save kerrytazi/df82b823c4488406ba19886f1df5a6d8 to your computer and use it in GitHub Desktop.
#pragma once
template <
typename TResult,
typename TState,
typename TAdvance,
typename TProjStateToResult = decltype([](const TState& state) -> TResult { return state; })>
class simple_generator
{
public:
constexpr simple_generator(TState&& initial_state, TAdvance&& advance_func)
: initial_state_{ static_cast<TState&&>(initial_state) }
, advance_func_{ static_cast<TAdvance&&>(advance_func) }
{
}
constexpr explicit simple_generator(TAdvance&& advance_func)
: simple_generator(TState{}, static_cast<TAdvance&&>(advance_func))
{
}
struct simple_iterator
{
simple_generator* gen;
TState state;
constexpr simple_iterator(simple_generator* _gen)
: gen{ _gen }
{
if (gen)
state = gen->initial_state_;
}
constexpr simple_iterator& operator++()
{
gen->advance_func_(state, [this]() { gen = nullptr; });
return *this;
}
constexpr bool operator==(const simple_iterator& other) const
{
if (gen != other.gen)
return false;
if (!gen)
return true;
return state == other.state;
}
constexpr TResult operator*() const
{
return gen->proj_state_to_result_(state);
}
};
constexpr simple_iterator begin() { return simple_iterator(this); }
constexpr simple_iterator end() { return simple_iterator(nullptr); }
private:
[[no_unique_address]] TState initial_state_;
[[no_unique_address]] TAdvance advance_func_;
[[no_unique_address]] TProjStateToResult proj_state_to_result_;
};
template <typename TResultState, typename TAdvance>
constexpr auto make_simple_generator(TAdvance&& advance_func)
{
return simple_generator<TResultState, TResultState, TAdvance>(static_cast<TAdvance&&>(advance_func));
}
template <typename TResultState, typename TAdvance>
constexpr auto make_simple_generator(TResultState&& initial_state, TAdvance&& advance_func)
{
return simple_generator<TResultState, TResultState, TAdvance>(static_cast<TResultState&&>(initial_state), static_cast<TAdvance&&>(advance_func));
}
template <
typename TResult,
typename TState,
typename TProjStateToResult,
typename TAdvance>
constexpr auto make_simple_generator(TAdvance&& advance_func)
{
return simple_generator<TResult, TState, TAdvance, TProjStateToResult>(static_cast<TAdvance&&>(advance_func));
}
template <
typename TResult,
typename TState,
typename TProjStateToResult,
typename TAdvance>
constexpr auto make_simple_generator(TState&& initial_state, TAdvance&& advance_func)
{
return simple_generator<TResult, TState, TAdvance, TProjStateToResult>(static_cast<TState&&>(initial_state), static_cast<TAdvance&&>(advance_func));
}
#include <type_traits>
#include <iostream>
constexpr auto gen1(int max)
{
return make_simple_generator<int>([max](auto& state, auto mark_done) {
state++;
if (state >= max)
mark_done();
});
}
template <int max>
constexpr auto gen2()
{
return make_simple_generator<int>([](auto& state, auto mark_done) {
state++;
if (state >= max)
mark_done();
});
}
consteval int sum(int max)
{
int result = 0;
for (auto v : gen1(10))
result += v;
return result;
}
int main()
{
std::cout << "sizeof(gen1): " << sizeof(gen1(10)) << "\n";
for (auto v : gen1(10))
std::cout << v << " ";
std::cout << "\n";
std::cout << "sizeof(gen2): " << sizeof(gen2<10>()) << "\n";
for (auto v : gen2<10>())
std::cout << v << " ";
std::cout << "\n";
std::cout << sum(10) << "\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment