The following code example is taken from the book
 
  C++20 - The Complete Guide
 by Nicolai M. Josuttis,
 Leanpub, 2021 
 
 The code is licensed under a
 
     Creative Commons Attribution 4.0 International License.
      
 
 
// raw code
 
#include <coroutine> 
#include <exception>  // for terminate()  
#include <cassert>    // for assert()  
 
template<typename T> 
class [[nodiscard]] Generator { 
 public: 
  // customization points:  
  struct promise_type { 
    T coroValue{};                  // last value from co_yield  
     
    auto yield_value(T val) {        // reaction to co_yield   
      coroValue = val;               // - store value locally  
      return std::suspend_always{};  // - suspend coroutine  
    } 
 
    auto get_return_object() { 
      return std::coroutine_handle<promise_type>::from_promise(*this); 
    } 
    auto initial_suspend() { return std::suspend_always{}; } 
    void return_void() { } 
    void unhandled_exception() { std::terminate(); } 
    auto final_suspend() noexcept { return std::suspend_always{}; } 
  }; 
 
 private: 
  std::coroutine_handle<promise_type> hdl;  // native coroutine handle  
 
 public: 
  // constructors and destructor:  
  Generator(auto h) : hdl{h} { } 
  ~Generator() { if (hdl) hdl.destroy(); } 
 
  // no copy or move supported:  
  Generator(const Generator&) = delete; 
  Generator& operator=(const Generator&) = delete; 
 
  // API to resume the coroutine and access its values:  
  // - iterator interface with begin() and end()  
  struct iterator { 
    std::coroutine_handle<promise_type> hdl;  // nullptr on end  
    iterator(auto p) : hdl{p} { 
    } 
    void getNext() { 
      if (hdl) { 
        hdl.resume();        // RESUME  
        if (hdl.done()) { 
          hdl = nullptr; 
        } 
      } 
    } 
    T operator*() const { 
      assert(hdl != nullptr); 
      return hdl.promise().coroValue; 
    } 
    iterator operator++() { 
      getNext();             // resume for next value  
      return *this; 
    } 
    bool operator== (const iterator& i) const = default; 
  }; 
 
  iterator begin() const { 
    if (!hdl || hdl.done()) { 
      return iterator{nullptr}; 
    } 
    iterator itor{hdl};      // initialize iterator  
    itor.getNext();          // resume for first value  
    return itor; 
  } 
 
  iterator end() const { 
    return iterator{nullptr}; 
  } 
};