Listings Josuttis/C++20

Listing 1: Verwenden von Concepts und auto in Funktionen
template <typename T>
concept IsContainer = requires(const T& t) {
    { t.begin() }; 
    { t.end() }; 
};

void print(const IsContainer auto& coll) {
    for (const auto& elem : coll) {
      std::cout << elem << ' ';  
    }
}

-------

Listing 2: Iteration mit einer Ranges-View
// Spezifikation einer View:
rng::filter_view over36View{coll | rng::views::filter(isOver36)};

// Verwendung der View (hier wird iteriert):
for (int i : over36View) {
  std::cout << "over Limits: " << i << '\n';
}

-------

Listing 3: Definition einer Modulschnittstelle
export module My.Account;

export class Customer {
      std::string name;
    public:
      Customer(std::string name);
      std::string getName() const;
};

export void print(const Customer&);

void helper(); // private in module

-------

Listing 4: Modul in mehreren Dateien implementieren
// 1. Datei mit Modulimplementierungen
module My.Account;

#include <iostream>

void print(const Customer& c) {
    std::cout << c << '\n';
}

// 2. Datei mit Modulimplementierungen
module My.Account;

void helper() { 
    ...
}

-------

Listing 5: Eine Koroutine hält die Ausgabe an und setzt sie später wieder fort
IntGen nextElemGen(const auto& coll) 
{
    for (int elem : coll) {
      co_yield elem;  // hält Schleife und Funktion mit elem als Zwischenergebnis an
    }
}

-------

Listing 6: Beispiel-Generator für eine Coroutine
class IntGen {
    public:
      struct promise_type {
        int current_value;
        ...
        auto yield_value(int value) {
          current_value = value;
          return std::suspend_always{};
        }
      };
    private;
      using handle = std::coroutine_handle<promise_type>;
      handle coro;
      IntGen(handle h) : coro{h} {
      }
    public:
      bool nextValue() { 
        return  coro ? (coro.resume(), !coro.done()) : false;
      }
      int getValue() {
        return coro.promise().current_value;
      }
      ...
      using iterator = ...   // ++ setzt die Coroutine fort
      iterator begin();
      iterator end();
};

-------

Listing 7: Vergleichsoperatoren in Klassentemplates
template<typename T1, typename T2>
class P {
    private: 
      T1 x1;
      T2 x2;
    public:
    ...
      friend auto operator<=>(const P&, const P&) = default;
};

-------

Listing 8: Jede Sequenz von Integern verdoppeln
std::vector<int> v{42, 43, 44, 45};
doubleContent(v);

std::array<int,4> a{-14, 55, 24, 67};
doubleContent(a);

int arr[]{0, 8, 15};
doubleContent(arr);

-------

Listing 9: Latch mit zehn Threads, von denen fünf fertig werden müssen
#include <latch>

// Menge von Threads:
const int numThreads{10};
std::vector<std::jthread> threads;

// 5 muessen fertig werden:
std::latch ready{5};

// alle Threads starten, die dann fertig melden:
for (int i=0; i<numThreads; ++i) {
    threads.push_back(std::jthread{[&ready]{
      doSomeStuff();
      ready.count_down();
      }});
}
// warten, dass 5 fertig sind:
ready.wait();

...  // Reaktion auf mindestens 5 fertige Threads

-------

Listing 10: Limitierung auf je drei parallel laufende Threads
std::counting_semaphore sem{3};
for (int i=0; i<numThreads; ++i) {
    threads.push_back(std::jthread{[&sem]{
      sem.acquire();
      doSomeStuff();
      sem.release();
    }});
}

