#include <iostream>
#include <experimental/coroutine>

struct fmt_cor {
	struct promise_type {
		char _value;

		fmt_cor get_return_object() {
			return fmt_cor(std::experimental::coroutine_handle<promise_type>::from_promise(*this));
		}

		auto initial_suspend() { return std::experimental::suspend_never(); }
		auto final_suspend()   { return std::experimental::suspend_always(); }

		void return_void() {}
		void unhandled_exception() {}
	};

	struct get {
		promise_type * _promise = nullptr;

		bool await_ready() noexcept {
			return false;
		}

		void await_suspend(std::experimental::coroutine_handle<promise_type> _coroutine) noexcept {
			_promise = &_coroutine.promise();
		}
		char await_resume() noexcept {
			assert(_promise);
			return _promise->_value;
		}
	};

	std::experimental::coroutine_handle<promise_type> _coroutine = nullptr;

	explicit fmt_cor(std::experimental::coroutine_handle<promise_type> coroutine)
		: _coroutine(coroutine)
	{}

	~fmt_cor() {
		if(_coroutine) {
			_coroutine.destroy();

		}
	}

	fmt_cor() = default;
	fmt_cor(fmt_cor const &) = delete;
	fmt_cor& operator=(fmt_cor const &) = delete;

	fmt_cor(fmt_cor&& other) {
		std::swap(_coroutine, other._coroutine);
	}

	fmt_cor& operator=(fmt_cor&& other) {
		if(&other != this) {
			_coroutine = other._coroutine;
			other._coroutine = nullptr;
		}
		return *this;
	}

	void send(char a) {
		_coroutine.promise()._value = a;
		_coroutine.resume();
	}
};

fmt_cor Fmt() {
	struct locals {
		int g, b;

		~locals() {
			if (g != 0 | b != 0) {
				std::cout << "\n";
			}
		}
	} l;
	for(;;) {
		for(l.g = 0; l.g < 5; l.g++) {
			for(l.b = 0; l.b < 4; l.b++) {
				std::cout << co_await fmt_cor::get();
			}
			std::cout << "  ";
		}
		std::cout << std::endl;
	}
}

int main() {
	auto fmt = Fmt();
	for(int i = 0; i < 41; i++) {
		fmt.send('a');
	}
}