Modernes C++ programmieren

Okt 23, 2024

lst-1049-godb.cpp

//#(compile) c++; compiler:g132; options:"-std=c++20"; libs:-
// https://godbolt.org/z/4ed3oWK7q 
#include <coroutine>
#include <iostream>
struct Routine { // Koroutinen-Rückgabetyp
  struct promise_type;                     // weiter unten definiert
  Routine(auto h) : hdl_(h) {}             // Konstruktor
  ~Routine() { if(hdl_) hdl_.destroy(); }  // Destruktor
  Routine(const Routine&) = delete;        // keine Kopien
  Routine(Routine&&) = delete;             // keine Verschiebungen
  // Schnittstelle für den Aufrufer:
  bool more() {                            // Koroutine fortsetzen
    if(!hdl_ || hdl_.done()) return false; // - nichts mehr zu tun
    hdl_.resume();                         // - blockierender Aufruf
    return !hdl_.done();                   // - signalisiert fertig oder nicht
  }
private:
  using handle_type_ = std::coroutine_handle<promise_type>;
  handle_type_ hdl_;     // zum Steuern der Koroutine
};
struct Routine::promise_type {             // notwendiger promise_type
  auto get_return_object() {               // initialisiert das Handle
    return Routine{ handle_type_::from_promise(*this) };
  }
  auto initial_suspend() { return std::suspend_never{}; } // sofort starten
  auto final_suspend() noexcept { return std::suspend_always{}; } // Normalfall
  void unhandled_exception() {}                 // keine Exception-Behandlung
  void return_void() {}                         // Koroutine hat keine Rückgabe
};
Routine counter() {  // Rückgabetyp ist unsere Wrapperklasse mit dem promise_type
  for (unsigned i = 0;; ++i) {
    co_await std::suspend_always{};             // Koroutine pausieren
    std::cout << "counter: " << i << std::endl;
  }
}

int main() {
  Routine routine = counter();                  // Koroutine erzeugen und starten
  for (int i = 0; i < 3; ++i) {
      std::cout << "Hallo main!\n";
      routine.more();                           // Koroutine fortsetzen
  }
}