Modernes C++ programmieren

Okt 23, 2024

lst-1057-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y8KK3nEG3
void sortData(std::ranges::random_access_range auto &&data) {
    std::ranges::sort(data);
}

Okt 23, 2024

lst-1043-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9Ys4s5qjs 
#include <future>
#include <thread>
#include <iostream>
#include <exception>
int ack(int m, int n); // Ackermannfunktion
void langeBerechnung(std::promise<int> intPromise) {
  try {
    int result = ack(3,12);
    intPromise.set_value(result);                        // Ergebnis mitteilen
  } catch (std::exception &e) {
    intPromise.set_exception(make_exception_ptr(e));     // Exception mitteilen
  } catch ( ... ) {
    intPromise.set_exception(std::current_exception());  // Exc. ohne Namen
  }
}
int main () {
  std::promise<int> intPromise;                          // Promise erzeugen
  std::future<int> intFuture = intPromise.get_future();  // Future anfordern
  std::jthread th{ langeBerechnung,                      // starten
             std::move(intPromise) };                    // Promise übergeben
  th.detach();                                           // weiterlaufen lassen
  // könnte eine Exception werfen:
  int result = intFuture.get();                          // Ergebnis anfordern
  std::cout << result << std::endl;
}

Okt 23, 2024

lst-1030-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/af6jK9dKo 
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <deque>
#include <iostream>
#include <syncstream>   // osyncstream
std::deque<int> g_data{};          // Datenaustausch zwischen Threads
std::condition_variable g_condvar; // benachrichtigen
std::mutex g_mx;                   // schützt g_data während Veränderungen
void produziere(int limit) {
  std::vector prims{2};          // bisherige Prims als Prüfteiler
  for(int kandidat=3; kandidat < limit; kandidat+=2) {
    for(int teiler : prims) {
      if(teiler*teiler > kandidat) {          // kandidat ist prim
        std::lock_guard lk{g_mx};             // data schützen
        g_data.push_back(kandidat);           // füllen
        g_condvar.notify_one();               // benachrichtigen
        prims.push_back(kandidat);            // für interne Berechnungen
        break; // nächster Prim-Kandidat
      } else if(kandidat % teiler == 0) {     // nicht prim
        break;                                // nächster Prim-Kandidat
      } else {
        // nächster Prüfteiler
      }
    }
  }
  // ganze Arbeit fertig mitteilen
  std::lock_guard lk{g_mx};          // data schützen
  g_data.push_back(0);               // mit Endemarkierung füllen
  g_condvar.notify_all();            // benachrichtigen
}
void konsumiere(char l, char r) {
  while(true) {                      // für immer
    std::unique_lock lk{g_mx};
    g_condvar.wait(lk, []{ return !g_data.empty();});
    int prim = g_data.front();       // Daten holen
    if(prim == 0) return;            // fertig; 0 drin lassen für andere Konsumenten
    g_data.pop_front();
    lk.unlock();                     // Sperre freigeben
    std::osyncstream osync{std::cout};  // Ausgabe synchronisieren
    osync << l << prim << r <<' ';
  }
}
int main() {
  // ein Produzent:
  std::jthread thProd{produziere, 1'000};
  // drei Konsumenten
  std::jthread thKon1{konsumiere, '[', ']' };
  std::jthread thKon2{konsumiere, '<', '>' };
  std::jthread thKon3{konsumiere, '{', '}' };
  // warten und beenden
  thProd.join();
  thKon1.join(); thKon2.join(); thKon3.join();
  std::cout << '\n';
}

Okt 23, 2024

lst-1046-book.cpp

// https://godbolt.org/z/3Y5WP6qWM 
#include <iostream>
#include <atomic>

struct CArray { int a[100]; };
struct Einfach { int x, y; };

int main() {
    std::atomic<CArray> carray{};
    std::cout << (carray.is_lock_free() ? "sperrfrei" : "sperrt")
        << '\n';                                        // Ausgabe: sperrt
    std::atomic<Einfach> einfach{};
    std::cout << (einfach.is_lock_free() ? "sperrfrei" : "sperrt")
        << '\n';                                        // Ausgabe: sperrfrei
}

Okt 23, 2024

lst-1044-book.cpp

// https://godbolt.org/z/9s94nbrx3 
#include <future>
#include <thread>
#include <iostream>
int ack(int m, int n); // Ackermannfunktion
int main () {
    std::packaged_task<int(void)> task1 {          // Signatur der Restfunktion
    []{ return ack(3,11);}  };                     // ack(3,11) vorbereiten
  auto f1 = task1.get_future();                    // Kommunikationskanal
  std::jthread th1 { move(task1) };                // in neuen Thread
  std::cout << "  ack(3,11):" << f1.get()          // Ergebnis abholen
      << '\n';                                     // Ausgabe: ack(3,11):16381
}

Okt 23, 2024

lst-1045-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bq1hn5rjo 
#include <future>
#include <thread>
#include <iostream>
int ack(int m, int n); // Ackermannfunktion
int main () {
  std::packaged_task<int(int,int)> task2 { &ack }; // andere Signatur
  auto f2 = task2.get_future();
  std::jthread th2 { move(task2), 3, 12 };         // Parameter hier
  std::cout << "  ack(3,12):" << f2.get() << '\n'; // Ausgabe: ack(3,12):32765
  th2.join();
}

Okt 23, 2024

lst-1035-book.cpp

// https://godbolt.org/z/Gh9Y5srd7 
#include <iostream>
#include <future>  // async
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    auto f40 = std::async(fib, 40);
    auto f41 = std::async(fib, 41);
    auto f42 = std::async(fib, 42);
    auto f43 = std::async(fib, 43);
    /* ... an dieser Stelle können weitere Berechnungen stehen ... */
    cout << "fib(40): " << f40.get() << endl; // Ausgabe: fib(40): 102334155
    cout << "fib(41): " << f41.get() << endl; // Ausgabe: fib(41): 165580141
    cout << "fib(42): " << f42.get() << endl; // Ausgabe: fib(42): 267914296
    cout << "fib(43): " << f43.get() << endl; // Ausgabe: fib(43): 433494437
}

Okt 23, 2024

lst-1035-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gh9Y5srd7 
#include <iostream>
#include <future>  // async
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    auto f40 = std::async(fib, 40);
    auto f41 = std::async(fib, 41);
    auto f42 = std::async(fib, 42);
    auto f43 = std::async(fib, 43);
    /* ... an dieser Stelle können weitere Berechnungen stehen ... */
    cout << "fib(40): " << f40.get() << endl; // Ausgabe: fib(40): 102334155
    cout << "fib(41): " << f41.get() << endl; // Ausgabe: fib(41): 165580141
    cout << "fib(42): " << f42.get() << endl; // Ausgabe: fib(42): 267914296
    cout << "fib(43): " << f43.get() << endl; // Ausgabe: fib(43): 433494437
}

Okt 23, 2024

lst-1049-book.cpp

// 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
  }
}

Okt 23, 2024

lst-1040-book.cpp

// https://godbolt.org/z/Pj63xfn7x 
#include <future> // async
#include <vector>
#include <algorithm> // max
#include <iostream>

int berechneHoehe(int count, int maxCount, int scale) {
  if(maxCount == 0)
      throw std::logic_error("Alle Hoehen 0");
  return (count * scale) / maxCount;
}

void balken(const std::vector<int> &counts) {
  // Berechnung starten
  auto maxCount = *std::max_element(counts.begin(), counts.end());
  std::vector< std::future<int> > futs;
  for(int count : counts) {
    futs.push_back(
          std::async(std::launch::async,
              berechneHoehe, count, maxCount, 200) );
  }

  // Ergebnisse einsammeln
  for(auto &fut : futs) {
    std::cout << fut.get() << ' ';                // löst Exception aus
  }
  std::cout << '\n';
}

int main() {
  try {
    balken(std::vector {10,23,13,0,33,4 });       // Ausgabe: 60 139 78 0 200 24
    balken(std::vector { 0, 0, 0, 0 });           // löst Exception aus
  } catch(std::exception &ex) {
    std::cout << "Fehler: " << ex.what() << '\n'; // Ausgabe: Fehler: Alle Hoehen 0
  }
}

Okt 23, 2024

lst-1037-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/P9MjGe6Mn 
#include <iostream>
#include <future>  // async
#include <vector>
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
int main() {
    // Aufgaben vorbereiten
    std::vector< std::future<long> > fibs;
    for(int n=0; n<50; ++n) {
        auto fut = std::async(std::launch::deferred, fib, n);
        fibs.push_back( std::move(fut) );
    }
    // nur das benötigte Ergebnis abholen
    cout << "fib(42): " << fibs[42].get() << endl; // Ausgabe: fib(42): 267914296
}

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
  }
}

Okt 23, 2024

lst-1028-book.cpp

// https://godbolt.org/z/1j8W7GjTf 
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
thread_local unsigned int usage = 0;
static std::mutex cout_mutex;
void use(const std::string thread_name) {
    ++usage;
    std::lock_guard lock(cout_mutex); // Ausgabe schützen
    std::cout << thread_name << ": " << usage << '\n';
}
int main() {
    std::jthread a{use, "a"}, b{use, "b"};
    use("main");
}

Okt 23, 2024

lst-1046-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3Y5WP6qWM 
#include <iostream>
#include <atomic>

struct CArray { int a[100]; };
struct Einfach { int x, y; };

int main() {
    std::atomic<CArray> carray{};
    std::cout << (carray.is_lock_free() ? "sperrfrei" : "sperrt")
        << '\n';                                        // Ausgabe: sperrt
    std::atomic<Einfach> einfach{};
    std::cout << (einfach.is_lock_free() ? "sperrfrei" : "sperrt")
        << '\n';                                        // Ausgabe: sperrfrei
}

Okt 23, 2024

lst-1044-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9s94nbrx3 
#include <future>
#include <thread>
#include <iostream>
int ack(int m, int n); // Ackermannfunktion
int main () {
    std::packaged_task<int(void)> task1 {          // Signatur der Restfunktion
    []{ return ack(3,11);}  };                     // ack(3,11) vorbereiten
  auto f1 = task1.get_future();                    // Kommunikationskanal
  std::jthread th1 { move(task1) };                // in neuen Thread
  std::cout << "  ack(3,11):" << f1.get()          // Ergebnis abholen
      << '\n';                                     // Ausgabe: ack(3,11):16381
}

Okt 23, 2024

lst-1039-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xzY8hj9oP 
#include <chrono>
#include <future>
#include <mutex>
#include <vector>
#include <iostream>
std::timed_mutex mtx;
long fibX(long n) { return n < 2L ? 1L : fibX(n-1L) + fibX(n-2L); }
long fibCall(long n) {
    using namespace std::chrono; // Suffixe
    if(mtx.try_lock_for(1000ms)) {
        auto res = fibX(n);
        mtx.unlock();
        return res;
    } else {
        return 0L;
    }
}

int main() {
    std::vector< std::future<long> > fs;
    for(long n=1; n<= 42; ++n) {
        fs.emplace_back( std::async(std::launch::async, fibCall, n) );
    }
    for(auto &f : fs) {
        std::cout << f.get() << " ";
    }
    std::cout << std::endl;
}

Okt 23, 2024

Okt 23, 2024

lst-1037-book.cpp

// https://godbolt.org/z/P9MjGe6Mn 
#include <iostream>
#include <future>  // async
#include <vector>
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
int main() {
    // Aufgaben vorbereiten
    std::vector< std::future<long> > fibs;
    for(int n=0; n<50; ++n) {
        auto fut = std::async(std::launch::deferred, fib, n);
        fibs.push_back( std::move(fut) );
    }
    // nur das benötigte Ergebnis abholen
    cout << "fib(42): " << fibs[42].get() << endl; // Ausgabe: fib(42): 267914296
}

Okt 23, 2024

lst-1038-book.cpp

// https://godbolt.org/z/o9oYrvMcj 
#include <iostream>
#include <future>  // async
#include <chrono>
using std::cout; using std::endl; using namespace std::chrono;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
int main() {
    auto f43 = std::async(fib, 43);
    while(true) {
        auto fertig = f43.wait_for(500ms);
        if(fertig==std::future_status::timeout) {
            std::cout << "noch nicht..." << std::endl;
        } else {
            break;
        }
    }
    // abholen, ist sofort da
    cout << "fib(43): " << f43.get() << endl; // Ausgabe: fib(43): 701408733
}

Okt 23, 2024

lst-1047-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/W47YTYcEb 
#include <atomic>
class SpinlockMutex {
  std::atomic_flag flag_;
public:
  SpinlockMutex()
  : flag_{ATOMIC_FLAG_INIT}
  {}
  void lock() {                                 // z. B. von lock_guard aufgerufen
    while(flag_.test_and_set(std::memory_order_acquire)) // hauptsächlich lesen
      { /* nothing */ }
  }
  void unlock() {
    flag_.clear(std::memory_order_release);              // Schreiboperation
  }
};

Okt 23, 2024

lst-1041-book.cpp

// https://godbolt.org/z/ndc4f8T3P 
#include <future> // async
#include <iostream>

int berechneHoehe(int count, int maxCount, int scale) {
  if(maxCount == 0)
      throw std::logic_error("maxCount ist 0");
  return (count * scale) / maxCount;
}

int main() {
  auto fut = std::async(std::launch::async, berechneHoehe, 0, 0, 200); //                 (ERR)  wirft
  try {
    std::cout << fut.get() << '\n';               // löst Exception aus
  } catch(std::exception &ex) {
    std::cout << "Fehler: " << ex.what() << '\n'; // Ausgabe: Fehler: maxCount ist 0
  }
}

Okt 23, 2024

lst-1036-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7Mea1Y3Mn 
#include <iostream>
#include <future>  // async
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    auto f40 = std::async(fib, 40);
    auto f41 = std::async(fib, 41);
    auto f42 = std::async(fib, 42);
    auto f43 = std::async(fib, 43);
    cout << "fib(40): " << f40.get() << endl; // Ausgabe: fib(40): 102334155
} // wartet auch auf f41, f42 und f43.

Okt 23, 2024

lst-1043-book.cpp

// https://godbolt.org/z/9Ys4s5qjs 
#include <future>
#include <thread>
#include <iostream>
#include <exception>
int ack(int m, int n); // Ackermannfunktion
void langeBerechnung(std::promise<int> intPromise) {
  try {
    int result = ack(3,12);
    intPromise.set_value(result);                        // Ergebnis mitteilen
  } catch (std::exception &e) {
    intPromise.set_exception(make_exception_ptr(e));     // Exception mitteilen
  } catch ( ... ) {
    intPromise.set_exception(std::current_exception());  // Exc. ohne Namen
  }
}
int main () {
  std::promise<int> intPromise;                          // Promise erzeugen
  std::future<int> intFuture = intPromise.get_future();  // Future anfordern
  std::jthread th{ langeBerechnung,                      // starten
             std::move(intPromise) };                    // Promise übergeben
  th.detach();                                           // weiterlaufen lassen
  // könnte eine Exception werfen:
  int result = intFuture.get();                          // Ergebnis anfordern
  std::cout << result << std::endl;
}

Okt 23, 2024

lst-1041-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ndc4f8T3P 
#include <future> // async
#include <iostream>

int berechneHoehe(int count, int maxCount, int scale) {
  if(maxCount == 0)
      throw std::logic_error("maxCount ist 0");
  return (count * scale) / maxCount;
}

int main() {
  auto fut = std::async(std::launch::async, berechneHoehe, 0, 0, 200); //                 (ERR)  wirft
  try {
    std::cout << fut.get() << '\n';               // löst Exception aus
  } catch(std::exception &ex) {
    std::cout << "Fehler: " << ex.what() << '\n'; // Ausgabe: Fehler: maxCount ist 0
  }
}

Okt 23, 2024

lst-1038-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/o9oYrvMcj 
#include <iostream>
#include <future>  // async
#include <chrono>
using std::cout; using std::endl; using namespace std::chrono;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
int main() {
    auto f43 = std::async(fib, 43);
    while(true) {
        auto fertig = f43.wait_for(500ms);
        if(fertig==std::future_status::timeout) {
            std::cout << "noch nicht..." << std::endl;
        } else {
            break;
        }
    }
    // abholen, ist sofort da
    cout << "fib(43): " << f43.get() << endl; // Ausgabe: fib(43): 701408733
}

Okt 23, 2024

lst-1036-book.cpp

// https://godbolt.org/z/7Mea1Y3Mn 
#include <iostream>
#include <future>  // async
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    auto f40 = std::async(fib, 40);
    auto f41 = std::async(fib, 41);
    auto f42 = std::async(fib, 42);
    auto f43 = std::async(fib, 43);
    cout << "fib(40): " << f40.get() << endl; // Ausgabe: fib(40): 102334155
} // wartet auch auf f41, f42 und f43.

Okt 23, 2024

lst-1030-book.cpp

// https://godbolt.org/z/af6jK9dKo 
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <deque>
#include <iostream>
#include <syncstream>   // osyncstream
std::deque<int> g_data{};          // Datenaustausch zwischen Threads
std::condition_variable g_condvar; // benachrichtigen
std::mutex g_mx;                   // schützt g_data während Veränderungen
void produziere(int limit) {
  std::vector prims{2};          // bisherige Prims als Prüfteiler
  for(int kandidat=3; kandidat < limit; kandidat+=2) {
    for(int teiler : prims) {
      if(teiler*teiler > kandidat) {          // kandidat ist prim
        std::lock_guard lk{g_mx};             // data schützen
        g_data.push_back(kandidat);           // füllen
        g_condvar.notify_one();               // benachrichtigen
        prims.push_back(kandidat);            // für interne Berechnungen
        break; // nächster Prim-Kandidat
      } else if(kandidat % teiler == 0) {     // nicht prim
        break;                                // nächster Prim-Kandidat
      } else {
        // nächster Prüfteiler
      }
    }
  }
  // ganze Arbeit fertig mitteilen
  std::lock_guard lk{g_mx};          // data schützen
  g_data.push_back(0);               // mit Endemarkierung füllen
  g_condvar.notify_all();            // benachrichtigen
}
void konsumiere(char l, char r) {
  while(true) {                      // für immer
    std::unique_lock lk{g_mx};
    g_condvar.wait(lk, []{ return !g_data.empty();});
    int prim = g_data.front();       // Daten holen
    if(prim == 0) return;            // fertig; 0 drin lassen für andere Konsumenten
    g_data.pop_front();
    lk.unlock();                     // Sperre freigeben
    std::osyncstream osync{std::cout};  // Ausgabe synchronisieren
    osync << l << prim << r <<' ';
  }
}
int main() {
  // ein Produzent:
  std::jthread thProd{produziere, 1'000};
  // drei Konsumenten
  std::jthread thKon1{konsumiere, '[', ']' };
  std::jthread thKon2{konsumiere, '<', '>' };
  std::jthread thKon3{konsumiere, '{', '}' };
  // warten und beenden
  thProd.join();
  thKon1.join(); thKon2.join(); thKon3.join();
  std::cout << '\n';
}

Okt 23, 2024

lst-1040-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Pj63xfn7x 
#include <future> // async
#include <vector>
#include <algorithm> // max
#include <iostream>

int berechneHoehe(int count, int maxCount, int scale) {
  if(maxCount == 0)
      throw std::logic_error("Alle Hoehen 0");
  return (count * scale) / maxCount;
}

void balken(const std::vector<int> &counts) {
  // Berechnung starten
  auto maxCount = *std::max_element(counts.begin(), counts.end());
  std::vector< std::future<int> > futs;
  for(int count : counts) {
    futs.push_back(
          std::async(std::launch::async,
              berechneHoehe, count, maxCount, 200) );
  }

  // Ergebnisse einsammeln
  for(auto &fut : futs) {
    std::cout << fut.get() << ' ';                // löst Exception aus
  }
  std::cout << '\n';
}

int main() {
  try {
    balken(std::vector {10,23,13,0,33,4 });       // Ausgabe: 60 139 78 0 200 24
    balken(std::vector { 0, 0, 0, 0 });           // löst Exception aus
  } catch(std::exception &ex) {
    std::cout << "Fehler: " << ex.what() << '\n'; // Ausgabe: Fehler: Alle Hoehen 0
  }
}

Okt 23, 2024

lst-1048-godb.cpp

//#(compile) c++; compiler:gsnapshot; options:"-std=c++23"; libs:-
// https://godbolt.org/z/Gfazq6GE7 
#include <generator>
#include <iostream>
#include <vector>

std::generator<int> fib(int n) { // generiert int-Werte
  int a = 0, b = 1;
  while (--n) {
    co_yield b;                  // macht diese Funktion zu einer Koroutine
    auto tmp = a;
    a = b;
    b += tmp;
  }
}
int main() {
  for (auto i : fib(10)) std::cout << i << ' ';
  std::cout << '\n';             // Ausgabe: 1 1 2 3 5 8 13 21 34 55
}

Okt 23, 2024

lst-1047-book.cpp

// https://godbolt.org/z/W47YTYcEb 
#include <atomic>
class SpinlockMutex {
  std::atomic_flag flag_;
public:
  SpinlockMutex()
  : flag_{ATOMIC_FLAG_INIT}
  {}
  void lock() {                                 // z. B. von lock_guard aufgerufen
    while(flag_.test_and_set(std::memory_order_acquire)) // hauptsächlich lesen
      { /* nothing */ }
  }
  void unlock() {
    flag_.clear(std::memory_order_release);              // Schreiboperation
  }
};

Okt 23, 2024

lst-1045-book.cpp

// https://godbolt.org/z/bq1hn5rjo 
#include <future>
#include <thread>
#include <iostream>
int ack(int m, int n); // Ackermannfunktion
int main () {
  std::packaged_task<int(int,int)> task2 { &ack }; // andere Signatur
  auto f2 = task2.get_future();
  std::jthread th2 { move(task2), 3, 12 };         // Parameter hier
  std::cout << "  ack(3,12):" << f2.get() << '\n'; // Ausgabe: ack(3,12):32765
  th2.join();
}

Okt 23, 2024

lst-1052-book.cpp

// https://godbolt.org/z/veEq4dcET 
struct Tag {
    Tag(int a, int b) : Tag{} {       // delegiert
        if(a==0 || b == 0)
            throw 666;                // löst Ausnahme aus
    }
    Tag() {}
};
int main() {
    try {
        Tag tag{1,2};
    } catch(int) { }
}

Okt 23, 2024

lst-1028-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1j8W7GjTf 
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
thread_local unsigned int usage = 0;
static std::mutex cout_mutex;
void use(const std::string thread_name) {
    ++usage;
    std::lock_guard lock(cout_mutex); // Ausgabe schützen
    std::cout << thread_name << ": " << usage << '\n';
}
int main() {
    std::jthread a{use, "a"}, b{use, "b"};
    use("main");
}

Okt 23, 2024

lst-1039-book.cpp

// https://godbolt.org/z/xzY8hj9oP 
#include <chrono>
#include <future>
#include <mutex>
#include <vector>
#include <iostream>
std::timed_mutex mtx;
long fibX(long n) { return n < 2L ? 1L : fibX(n-1L) + fibX(n-2L); }
long fibCall(long n) {
    using namespace std::chrono; // Suffixe
    if(mtx.try_lock_for(1000ms)) {
        auto res = fibX(n);
        mtx.unlock();
        return res;
    } else {
        return 0L;
    }
}

int main() {
    std::vector< std::future<long> > fs;
    for(long n=1; n<= 42; ++n) {
        fs.emplace_back( std::async(std::launch::async, fibCall, n) );
    }
    for(auto &f : fs) {
        std::cout << f.get() << " ";
    }
    std::cout << std::endl;
}

Okt 23, 2024

lst-1048-book.cpp

// https://godbolt.org/z/Gfazq6GE7 
#include <generator>
#include <iostream>
#include <vector>

std::generator<int> fib(int n) { // generiert int-Werte
  int a = 0, b = 1;
  while (--n) {
    co_yield b;                  // macht diese Funktion zu einer Koroutine
    auto tmp = a;
    a = b;
    b += tmp;
  }
}
int main() {
  for (auto i : fib(10)) std::cout << i << ' ';
  std::cout << '\n';             // Ausgabe: 1 1 2 3 5 8 13 21 34 55
}

Okt 23, 2024

lst-1052-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/veEq4dcET 
struct Tag {
    Tag(int a, int b) : Tag{} {       // delegiert
        if(a==0 || b == 0)
            throw 666;                // löst Ausnahme aus
    }
    Tag() {}
};
int main() {
    try {
        Tag tag{1,2};
    } catch(int) { }
}

Okt 23, 2024

lst-1027-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/38qMMWoz6 
#include <mutex> // recursive_mutex
#include <iostream>
struct MulDiv {
    std::recursive_mutex mx_;
    int value_;
    explicit MulDiv(int value) : value_{value} {}
    void mul(int x) {
        std::lock_guard lk1(mx_);  // innen
        value_ *= x;
    }
    void div(int x) {
        std::lock_guard lk2(mx_);  // innen
        value_ /= x;
    }
    void muldiv(int x, int y){
        std::lock_guard lk3(mx_);  // außen
        mul(x);
        div(y);
    }
};
int main() {
   MulDiv m{42}; // 3*7*2 *5
   m.muldiv(5, 15);
   std::cout << m.value_ << '\n';  // Ausgabe: 14
}

Okt 23, 2024

lst-1004-book.cpp

// https://godbolt.org/z/Kv84eb96E 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
auto makeThread(std::string wer) {
    return std::jthread{ [wer] {
        std::this_thread::sleep_for(1s);
        std::cout << "Viel Glueck, " << wer << std::endl;
    } };
}
int main() {
    auto th = makeThread("Jim"); // Ausgabe: Viel Glueck, Jim
    th.join();
}

Okt 23, 2024

lst-1002-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GnsWYvecv 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
struct Zustand {
    int zaehler;
};
void zeigeZustand(const Zustand& zustand) {
    for(auto i : { 5,4,3,2,1 }) {
        std::cout << "zaehler: " << zustand.zaehler << std::endl;
        std::this_thread::sleep_for(1s);
    }
}
int main() {
    Zustand zustand { 4 };
    std::jthread th{zeigeZustand, std::ref(zustand)}; // bleibt Referenz auf zustand
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 501;
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 87;
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 2;
}

Okt 23, 2024

lst-1005-book.cpp

// https://godbolt.org/z/39x4bafco 
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
void kobraUebernehmenSie(std::jthread job) {
    job.join();
}
int main() {
     std::jthread th{ [] {
        std::this_thread::sleep_for(1s);
        std::cout << "Viel Glueck, Dan" << std::endl;
    } };
    kobraUebernehmenSie( std::move(th) );  // Zuständigkeit übertragen
}

Okt 23, 2024

lst-1004-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Kv84eb96E 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
auto makeThread(std::string wer) {
    return std::jthread{ [wer] {
        std::this_thread::sleep_for(1s);
        std::cout << "Viel Glueck, " << wer << std::endl;
    } };
}
int main() {
    auto th = makeThread("Jim"); // Ausgabe: Viel Glueck, Jim
    th.join();
}

Okt 23, 2024

lst-1026-book.cpp

// https://godbolt.org/z/TcsrefEPh 
#include <mutex> // once_flag, call_once
#include <memory>
struct Connection {
    void csend(const char *data) {} // dummy
    const char* crecv() {} // dummy
};
class Sender {
    std::shared_ptr<Connection> conn_;
    std::once_flag connInitFlag_;
    void open() {
        conn_.reset( new Connection{} );
    }
public:
    void send(const char* data) {
        std::call_once(connInitFlag_, &Sender::open, this); // Methodenzeiger
        conn_->csend(data);
    }
    const char* recv() {
        std::call_once(connInitFlag_, [this] {this->open();} ); // Lambda
        return conn_->crecv();
    }
};

Okt 23, 2024

lst-1003-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/j5Y15Esx7 
//  includes 
#include <thread>
using namespace std::chrono; // seconds, suffix s
struct Image {
    std::vector<char> data_; // Kopie teuer
    explicit Image() : data_(1'000'000) {}
};
void zeigeImage(Image img) {
    std::cout << img.data_.size() << '\n';
}
void zeigeIptr(std::unique_ptr<int> iptr) {
    std::cout << *iptr << '\n';
}
int main() {
    // teuer zu kopieren, aber dafür gut zu verschieben:
    Image image{};
    std::cout << image.data_.size() << std::endl;    // Ausgabe: 1000000
    std::jthread th1{ zeigeImage, std::move(image) };// Ausgabe: 1000000
    std::this_thread::sleep_for(1s);
    std::cout << image.data_.size() << std::endl;    // Ausgabe: 0
    th1.join();  // explizit warten, bis der Thread fertig ist
    // unmöglich zu kopieren, aber gut zu verschieben:
    auto iptr = std::make_unique<int>( 657 );
    std::cout << (bool)iptr << std::endl;            // Ausgabe: 1 für wahr
    std::jthread th2{ zeigeIptr, std::move(iptr) };  // Ausgabe: 657
    std::this_thread::sleep_for(1s);
    std::cout << (bool)iptr.get() << std::endl;      // Ausgabe: 0 für falsch
}

Okt 23, 2024

lst-1001-book.cpp

// https://godbolt.org/z/hvq5dbzde 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s

void delayPrint(seconds s, const char* msg) { //                     (ERR)  roher Zeiger
    std::this_thread::sleep_for(s);
    std::cout << msg << std::endl;            //                     (ERR)  das klappt nicht
}

void lauf() {
    const char risiko[] = "Das geht nicht gut...";
    std::jthread m{ delayPrint, 1s, risiko }; //                     (ERR)  roher Zeiger
    m.detach();
    // hier wird der Bereich von 'risiko' verlassen
}
int main() {
    lauf();
    std::this_thread::sleep_for(2s);          // noch 2 Sekunden warten
}

Okt 23, 2024

lst-1022-book.cpp

// https://godbolt.org/z/9PMcz1cqP 
friend void swap(MxStack& re, MxStack& li) {
    if(&re==&li) return; // Adresse dieselbe? Mit sich selbst tauschen unnötig
    std::lock( re.mx_, li.mx_ );   // mehrere Sperren gleichzeitig
    std::lock_guard lkre{re.mx_, std::adopt_lock}; // schon gesperrt
    std::lock_guard lkli{li.mx_, std::adopt_lock}; // schon gesperrt
    std::swap(li.data_, re.data_); // vertauschen ausführen
}

Okt 23, 2024

lst-0999-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PP4GT3oc6 
#include <iostream>
#include <thread>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long n) {
    auto r = fib(n);
    cout << "fib("<<n<<")=" << r << endl;
}
long ack(long m, long n) { // Ackermannfunktion
    if(m==0) return n+1;
    if(n==0) return ack(m-1, 1);
    return ack(m - 1, ack(m, n-1));
}
void runAck(long m, long n) {
    auto r = ack(m, n);
    cout << "ack("<<m<<','<<n<<")=" << r << endl;
}

int main() {
    std::jthread f40{ runFib, 40 };
    std::jthread f41{ runFib, 41 };
    std::jthread f42{ runFib, 42 };

    f40.join(); f41.join(); f42.join();

    std::thread a1{ runAck, 4, 0 };
    std::thread a2{ runAck, 4, 1 };
    std::thread a3{ runAck, 2, 700 };
    std::thread a4{ runAck, 3, 10 };
}

Okt 23, 2024

lst-0997-book.cpp

// https://godbolt.org/z/1aj16d7Ga 
#include <iostream>
#include <thread>
#include <vector>
#include <exception>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }

void hauptprogramm() {
    std::thread th{ &aufgabe1 };
    try {
        std::vector data{ 0,1,2 };
        data.at(666);                 //             (ERR)  löst out_of_range aus
    } catch(std::runtime_error &ex) { // passt nicht auf out_of_range
         /* ... */                        // speziellen Fehler hier behandeln
    } catch( ... ) {
        th.join();
        throw;                        // Fehlerbehandlung außen fortsetzen
    }
    th.join();                        // wartet nach Okay oder speziellem Fehler
}

int main() {
    try {
        hauptprogramm();
    } catch( ... ) {
        std::cout << "Ein Fehler ist aufgetreten\n";
    }
}

Okt 23, 2024

lst-1016-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4j7njd763 
#include <vector>

template<class T>
class MxStack {
public:
    bool isEmpty() const;
    void push(const T&);
    void pop();
    const T& top() const;
};

Okt 23, 2024

lst-1025-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3vcnzfqfM 
#include <mutex> // once_flag, call_once
std::shared_ptr<BigData> bigData{};
std::once_flag bigDataInitFlag;
void initBigData() {
    bigData = std::make_shared<BigData>();
}
int useBigData() {
    std::call_once(bigDataInitFlag, initBigData);
    // bigData->…
}

Okt 23, 2024

lst-1019-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xGv9drh73 
#include <vector>
#include <thread>
#include <mutex>
#include <iostream>
#include <numeric>  // iota

/* T: noexcept kopier- und zuweisbar */
template<typename T>
class MxStack {
    std::vector<T> data_;
    std::mutex mx_;

public:
    MxStack() : data_{} {}

    bool isEmpty() const { return data_.empty(); }

    void push(const T& val) {
        std::lock_guard<std::mutex> g{mx_};
        data_.push_back(val);
    }

    T pop() {
        std::lock_guard g{mx_};
        if(data_.empty())
            throw std::length_error{"empty stack"};
        T tmp{std::move(data_.back())};
        data_.pop_back();
        return tmp;
    }
};

int main() {
    // Stack vorbereiten
    MxStack<int> mxs{};
    for(int i=1; i<=1'000'000; ++i) mxs.push(i);
    // Berechnung definieren
    auto sumIt = [&mxs](long &sum) {
        int val{};
        try {
            while( ! mxs.isEmpty()) {
                sum += mxs.pop(); // könnte immer noch werfen
            }
        } catch(std::length_error &ex) {}
    };
    // Berechnen
    long sum1 = 0;          // fürs Teilergebnis
    std::jthread th1{sumIt, std::ref(sum1)};
    long sum2 = 0;          // fürs Teilergebnis
    std::thread th2{sumIt, std::ref(sum2)};
    th1.join(); th2.join();
    long sum = sum1 + sum2; // Gesamtergebnis
    // Ergebnis
    std::cout << "Sollergebnis: "
        << (1'000'000L*1'000'001)/2 << '\n'; // Ausgabe: 500000500000
    std::cout << "Tatsaechlich: "
        << sum << '\n';                      // Ausgabe: 500000500000
}

Okt 23, 2024

lst-1012-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/v3b6sxEab 
#include <thread>
/* exakte Zählung nicht so wichtig */
int count = 0; // wird simultan verändert
void run() {
    for(int i=0; i<1'000; ++i) {
        count += 1; // ungeschützt
        if(count > 1000) return;  //                 (ERR)  Endbedingung
        for(int j=0; j<1'000; ++j)
            ;
    }
}

int main() {
    std::thread th1{ run };
    std::thread th2{ run };
    std::thread th3{ run };
    th1.join(); th2.join(); th3.join();
}

Okt 23, 2024

lst-1027-book.cpp

// https://godbolt.org/z/38qMMWoz6 
#include <mutex> // recursive_mutex
#include <iostream>
struct MulDiv {
    std::recursive_mutex mx_;
    int value_;
    explicit MulDiv(int value) : value_{value} {}
    void mul(int x) {
        std::lock_guard lk1(mx_);  // innen
        value_ *= x;
    }
    void div(int x) {
        std::lock_guard lk2(mx_);  // innen
        value_ /= x;
    }
    void muldiv(int x, int y){
        std::lock_guard lk3(mx_);  // außen
        mul(x);
        div(y);
    }
};
int main() {
   MulDiv m{42}; // 3*7*2 *5
   m.muldiv(5, 15);
   std::cout << m.value_ << '\n';  // Ausgabe: 14
}

Okt 23, 2024

lst-1010-book.cpp

// https://godbolt.org/z/TM6c7cdss 
#include <thread>
#include <iostream>
int main() {
    std::cout << "Main: " << std::this_thread::get_id() << '\n';
    std::jthread th{ []{
        std::cout << "Thread: " << std::this_thread::get_id() << '\n';
    }};
}

Okt 23, 2024

lst-1009-book.cpp

// https://godbolt.org/z/Gen1rfEn6 
#include <thread>
#include <iostream>
#include <vector>
#include <chrono>  // steady_clock
using std::cout; using std::endl; using namespace std::chrono;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
  cout << std::thread::hardware_concurrency() << '\n';
  for(int nthreads : { 1,2,3,4,5,6 }) {
    cout << "Threads: ";
    const auto start = steady_clock::now();

    std::vector<std::jthread> threads;
    for(int ti = 1; ti <= nthreads; ++ti) {
      threads.emplace_back( std::jthread{fib, 40});
      cout << ti << "... "; cout.flush();
    }
    for(auto &th : threads) th.join(); // explizit joinen vor der Zeitmessung

    const auto now = steady_clock::now();
    cout << "  Zeit:  " << duration_cast<milliseconds>(
        now-start).count()<<"ms\n";
  }
}

Okt 23, 2024

lst-1011-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7GEs9a4n6 
#include <thread>
#include <iostream>

int count = 0; // wird simultan verändert

void run() {
    for(int i=0; i<1'000'000; ++i) {
        count += 1;   // ungeschützt
    }
}

int main() {
    std::cout << "Start: " << count << '\n';  // Ausgabe: Start: 0
    std::thread th1{ run };
    std::thread th2{ run };
    std::thread th3{ run };
    th1.join(); th2.join(); th3.join();
    std::cout << "Ende: " << count << '\n';  // Ausgabe sicher nicht: 3000000
}

Okt 23, 2024

lst-1015-book.cpp

// https://godbolt.org/z/3fz5a4vYv 
#include <mutex> // mutex, lock_guard
#include <list>
#include <algorithm> // find
using std::lock_guard; using std::mutex; using std::find;
class MxIntList {
    std::list <int> data_;
    mutable mutex mx_;
public:
    void add(int value) {
        lock_guard guard{mx_};  // schützt bis Ende der Methode
        data_.push_back(value);
    }
    bool contains(int searchVal) const {
        lock_guard guard{mx_};  // schützt bis Ende der Methode
        return find(data_.begin(), data_.end(), searchVal) != data_.end();
    }
};

Okt 23, 2024

lst-1006-book.cpp

// https://godbolt.org/z/YrEPnYMaP 
#include <iostream>
#include <thread>
#include <vector>
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long n) { auto r = fib(n); cout << "fib("<<n<<")=" << r << endl; }
int main() {
    std::vector<std::jthread> threads;
    // starten
    for( auto n : { 38, 39, 40, 41, 42, 43, }) {
        threads.emplace_back( runFib, n );
    }
}

Okt 23, 2024

lst-1022-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9PMcz1cqP 
friend void swap(MxStack& re, MxStack& li) {
    if(&re==&li) return; // Adresse dieselbe? Mit sich selbst tauschen unnötig
    std::lock( re.mx_, li.mx_ );   // mehrere Sperren gleichzeitig
    std::lock_guard lkre{re.mx_, std::adopt_lock}; // schon gesperrt
    std::lock_guard lkli{li.mx_, std::adopt_lock}; // schon gesperrt
    std::swap(li.data_, re.data_); // vertauschen ausführen
}

Okt 23, 2024

lst-1017-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1boeTMMvf 
MxStack<int> mxs{};
// 
// mehr Code
// 
if( ! mxs.isEmpty()) {            //                 (ERR)  nicht sicher
    const auto value = mxs.top(); //                 (ERR)  nicht sicher
    mxs.pop();                    //                 (ERR)  nicht sicher
    // 
    // mehr Code
    // 
}

Okt 23, 2024

lst-1012-book.cpp

// https://godbolt.org/z/v3b6sxEab 
#include <thread>
/* exakte Zählung nicht so wichtig */
int count = 0; // wird simultan verändert
void run() {
    for(int i=0; i<1'000; ++i) {
        count += 1; // ungeschützt
        if(count > 1000) return;  //                 (ERR)  Endbedingung
        for(int j=0; j<1'000; ++j)
            ;
    }
}

int main() {
    std::thread th1{ run };
    std::thread th2{ run };
    std::thread th3{ run };
    th1.join(); th2.join(); th3.join();
}

Okt 23, 2024

lst-1019-book.cpp

// https://godbolt.org/z/xGv9drh73 
#include <vector>
#include <thread>
#include <mutex>
#include <iostream>
#include <numeric>  // iota

/* T: noexcept kopier- und zuweisbar */
template<typename T>
class MxStack {
    std::vector<T> data_;
    std::mutex mx_;

public:
    MxStack() : data_{} {}

    bool isEmpty() const { return data_.empty(); }

    void push(const T& val) {
        std::lock_guard<std::mutex> g{mx_};
        data_.push_back(val);
    }

    T pop() {
        std::lock_guard g{mx_};
        if(data_.empty())
            throw std::length_error{"empty stack"};
        T tmp{std::move(data_.back())};
        data_.pop_back();
        return tmp;
    }
};

int main() {
    // Stack vorbereiten
    MxStack<int> mxs{};
    for(int i=1; i<=1'000'000; ++i) mxs.push(i);
    // Berechnung definieren
    auto sumIt = [&mxs](long &sum) {
        int val{};
        try {
            while( ! mxs.isEmpty()) {
                sum += mxs.pop(); // könnte immer noch werfen
            }
        } catch(std::length_error &ex) {}
    };
    // Berechnen
    long sum1 = 0;          // fürs Teilergebnis
    std::jthread th1{sumIt, std::ref(sum1)};
    long sum2 = 0;          // fürs Teilergebnis
    std::thread th2{sumIt, std::ref(sum2)};
    th1.join(); th2.join();
    long sum = sum1 + sum2; // Gesamtergebnis
    // Ergebnis
    std::cout << "Sollergebnis: "
        << (1'000'000L*1'000'001)/2 << '\n'; // Ausgabe: 500000500000
    std::cout << "Tatsaechlich: "
        << sum << '\n';                      // Ausgabe: 500000500000
}

Okt 23, 2024

lst-1025-book.cpp

// https://godbolt.org/z/3vcnzfqfM 
#include <mutex> // once_flag, call_once
std::shared_ptr<BigData> bigData{};
std::once_flag bigDataInitFlag;
void initBigData() {
    bigData = std::make_shared<BigData>();
}
int useBigData() {
    std::call_once(bigDataInitFlag, initBigData);
    // bigData->…
}

Okt 23, 2024

lst-1014-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/d3dc1Tsj8 
#include <thread>
#include <barrier>
#include <iostream>
#include <vector>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

constexpr int anz = 8;             // 8 Worker
constexpr int max_n = 32;          // bis 32 berechnen
std::vector<long> ergebnisse(anz); // Puffer: Platz für 8 Ergebnisse

void ausgeben() {                  // Signalisierungsfunktion druckt Puffer
    for (auto n : ergebnisse) std::cout << n << ' ';
    std::cout << '\n';
}

std::barrier ba{anz, ausgeben};    // immer nach 8 ausgeben

void worker(std::stop_token st, int idx) {
    // n = 0, 9, 17, 25,  ; 1, 10, 18, 26, 
    for(int n = idx; n<max_n; n += anz) {
        if(st.stop_requested()) return;
        ergebnisse[idx] = fib(n);  // schreibe Ergebnis in Puffer
        ba.arrive_and_wait();      // warte, bis 8 Threads hier sind
    }
}

int main() {
    std::vector<std::jthread> threads;     // 8 Threads
    for (int idx=0; idx<anz; ++idx) {
        threads.emplace_back(worker, idx); // erzeuge Thread mit Index
    }
    for (auto& t : threads) t.join();      // warte, bis alle fertig sind
}

Okt 23, 2024

lst-1001-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hvq5dbzde 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s

void delayPrint(seconds s, const char* msg) { //                     (ERR)  roher Zeiger
    std::this_thread::sleep_for(s);
    std::cout << msg << std::endl;            //                     (ERR)  das klappt nicht
}

void lauf() {
    const char risiko[] = "Das geht nicht gut...";
    std::jthread m{ delayPrint, 1s, risiko }; //                     (ERR)  roher Zeiger
    m.detach();
    // hier wird der Bereich von 'risiko' verlassen
}
int main() {
    lauf();
    std::this_thread::sleep_for(2s);          // noch 2 Sekunden warten
}

Okt 23, 2024

lst-1024-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/T7vehq58b 
std::shared_ptr<BigData> bigData{};
BigData& getBigData() {
    if(!bigData) bigData.reset(new BigData{});
    return *bigData;
}
int useBigData() {
    auto bigData = getBigData();
    // bigData->…
}

Okt 23, 2024

lst-1024-book.cpp

// https://godbolt.org/z/T7vehq58b 
std::shared_ptr<BigData> bigData{};
BigData& getBigData() {
    if(!bigData) bigData.reset(new BigData{});
    return *bigData;
}
int useBigData() {
    auto bigData = getBigData();
    // bigData->…
}

Okt 23, 2024

lst-1013-book.cpp

// https://godbolt.org/z/rrfn4d5WP 
#include <thread>
#include <latch>
#include <iostream>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    std::latch la{ 3 };                                // wir erwarten 3 Threads
    std::jthread th1{ [&la] { fib(39); la.count_down(); } };
    std::jthread th2{ [&la] { fib(38); la.count_down(); } };
    std::jthread th3{ [&la] { fib(40); la.count_down(); } };
    fib(37); // Hauptthread
    std::cout << "Haupthread: fertig\n";
    la.wait();                                         // wartet bis la == 0
    std::cout << "Rest fertig\n";
}

Okt 23, 2024

lst-1026-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TcsrefEPh 
#include <mutex> // once_flag, call_once
#include <memory>
struct Connection {
    void csend(const char *data) {} // dummy
    const char* crecv() {} // dummy
};
class Sender {
    std::shared_ptr<Connection> conn_;
    std::once_flag connInitFlag_;
    void open() {
        conn_.reset( new Connection{} );
    }
public:
    void send(const char* data) {
        std::call_once(connInitFlag_, &Sender::open, this); // Methodenzeiger
        conn_->csend(data);
    }
    const char* recv() {
        std::call_once(connInitFlag_, [this] {this->open();} ); // Lambda
        return conn_->crecv();
    }
};

Okt 23, 2024

lst-1003-book.cpp

// https://godbolt.org/z/j5Y15Esx7 
// … includes …
#include <thread>
using namespace std::chrono; // seconds, suffix s
struct Image {
    std::vector<char> data_; // Kopie teuer
    explicit Image() : data_(1'000'000) {}
};
void zeigeImage(Image img) {
    std::cout << img.data_.size() << '\n';
}
void zeigeIptr(std::unique_ptr<int> iptr) {
    std::cout << *iptr << '\n';
}
int main() {
    // teuer zu kopieren, aber dafür gut zu verschieben:
    Image image{};
    std::cout << image.data_.size() << std::endl;    // Ausgabe: 1000000
    std::jthread th1{ zeigeImage, std::move(image) };// Ausgabe: 1000000
    std::this_thread::sleep_for(1s);
    std::cout << image.data_.size() << std::endl;    // Ausgabe: 0
    th1.join();  // explizit warten, bis der Thread fertig ist
    // unmöglich zu kopieren, aber gut zu verschieben:
    auto iptr = std::make_unique<int>( 657 );
    std::cout << (bool)iptr << std::endl;            // Ausgabe: 1 für wahr
    std::jthread th2{ zeigeIptr, std::move(iptr) };  // Ausgabe: 657
    std::this_thread::sleep_for(1s);
    std::cout << (bool)iptr.get() << std::endl;      // Ausgabe: 0 für falsch
}

Okt 23, 2024

lst-1010-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TM6c7cdss 
#include <thread>
#include <iostream>
int main() {
    std::cout << "Main: " << std::this_thread::get_id() << '\n';
    std::jthread th{ []{
        std::cout << "Thread: " << std::this_thread::get_id() << '\n';
    }};
}

Okt 23, 2024

lst-1000-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fbnbKzrs1 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s

void delayPrint(seconds s, const std::string& msg) {
    std::this_thread::sleep_for(s);
    std::cout << msg << std::endl;
}
int main() {
    std::jthread m1{ delayPrint, 1s, "Auf die Plaetze" };
    std::jthread m2{ delayPrint, 2s, std::string{"fertig"} };
    std::string los = "los";
    std::jthread m3{ delayPrint, 3s, los };
}

Okt 23, 2024

lst-1023-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/e7rraPGx4 
#include <thread>
#include <mutex>
#include <vector>
#include <numeric> // accumulate, iota
using std::mutex; using std::unique_lock;

std::vector<int> myData;             // geteilte Daten
mutex myMutex;                       // Mutex zu den Daten
unique_lock<mutex> bereiteDatenVor() {
    unique_lock lk1{myMutex};        // sperren
    myData.resize(1000);
    std::iota(myData.begin(), myData.end(), 1); // 1..1000
    return lk1;                                 // Sperre transferieren
}
int verarbeiteDaten() {
    unique_lock lk2 = bereiteDatenVor();        // Sperre transferiert
    return std::accumulate(myData.begin(), myData.end(), 0);
}

Okt 23, 2024

lst-1016-book.cpp

// https://godbolt.org/z/4j7njd763 
#include <vector>

template<class T>
class MxStack {
public:
    bool isEmpty() const;
    void push(const T&);
    void pop();
    const T& top() const;
};

Okt 23, 2024

lst-1005-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/39x4bafco 
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
void kobraUebernehmenSie(std::jthread job) {
    job.join();
}
int main() {
     std::jthread th{ [] {
        std::this_thread::sleep_for(1s);
        std::cout << "Viel Glueck, Dan" << std::endl;
    } };
    kobraUebernehmenSie( std::move(th) );  // Zuständigkeit übertragen
}

Okt 23, 2024

lst-1002-book.cpp

// https://godbolt.org/z/GnsWYvecv 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
struct Zustand {
    int zaehler;
};
void zeigeZustand(const Zustand& zustand) {
    for(auto i : { 5,4,3,2,1 }) {
        std::cout << "zaehler: " << zustand.zaehler << std::endl;
        std::this_thread::sleep_for(1s);
    }
}
int main() {
    Zustand zustand { 4 };
    std::jthread th{zeigeZustand, std::ref(zustand)}; // bleibt Referenz auf zustand
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 501;
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 87;
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 2;
}

Okt 23, 2024

lst-1014-book.cpp

// https://godbolt.org/z/d3dc1Tsj8 
#include <thread>
#include <barrier>
#include <iostream>
#include <vector>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

constexpr int anz = 8;             // 8 Worker
constexpr int max_n = 32;          // bis 32 berechnen
std::vector<long> ergebnisse(anz); // Puffer: Platz für 8 Ergebnisse

void ausgeben() {                  // Signalisierungsfunktion druckt Puffer
    for (auto n : ergebnisse) std::cout << n << ' ';
    std::cout << '\n';
}

std::barrier ba{anz, ausgeben};    // immer nach 8 ausgeben

void worker(std::stop_token st, int idx) {
    // n = 0, 9, 17, 25,  ; 1, 10, 18, 26, 
    for(int n = idx; n<max_n; n += anz) {
        if(st.stop_requested()) return;
        ergebnisse[idx] = fib(n);  // schreibe Ergebnis in Puffer
        ba.arrive_and_wait();      // warte, bis 8 Threads hier sind
    }
}

int main() {
    std::vector<std::jthread> threads;     // 8 Threads
    for (int idx=0; idx<anz; ++idx) {
        threads.emplace_back(worker, idx); // erzeuge Thread mit Index
    }
    for (auto& t : threads) t.join();      // warte, bis alle fertig sind
}

Okt 23, 2024

lst-0998-book.cpp

// https://godbolt.org/z/8TdzEGf3d 
void hauptprogramm() {
    std::jthread th{ &aufgabe1 };
    std::vector data{ 0,1,2 };
    data.at(666);                 //             (ERR)  löst out_of_range aus
}

Okt 23, 2024

lst-1013-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rrfn4d5WP 
#include <thread>
#include <latch>
#include <iostream>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    std::latch la{ 3 };                                // wir erwarten 3 Threads
    std::jthread th1{ [&la] { fib(39); la.count_down(); } };
    std::jthread th2{ [&la] { fib(38); la.count_down(); } };
    std::jthread th3{ [&la] { fib(40); la.count_down(); } };
    fib(37); // Hauptthread
    std::cout << "Haupthread: fertig\n";
    la.wait();                                         // wartet bis la == 0
    std::cout << "Rest fertig\n";
}

Okt 23, 2024

lst-1011-book.cpp

// https://godbolt.org/z/7GEs9a4n6 
#include <thread>
#include <iostream>

int count = 0; // wird simultan verändert

void run() {
    for(int i=0; i<1'000'000; ++i) {
        count += 1;   // ungeschützt
    }
}

int main() {
    std::cout << "Start: " << count << '\n';  // Ausgabe: Start: 0
    std::thread th1{ run };
    std::thread th2{ run };
    std::thread th3{ run };
    th1.join(); th2.join(); th3.join();
    std::cout << "Ende: " << count << '\n';  // Ausgabe sicher nicht: 3000000
}

Okt 23, 2024

lst-1009-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gen1rfEn6 
#include <thread>
#include <iostream>
#include <vector>
#include <chrono>  // steady_clock
using std::cout; using std::endl; using namespace std::chrono;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
  cout << std::thread::hardware_concurrency() << '\n';
  for(int nthreads : { 1,2,3,4,5,6 }) {
    cout << "Threads: ";
    const auto start = steady_clock::now();

    std::vector<std::jthread> threads;
    for(int ti = 1; ti <= nthreads; ++ti) {
      threads.emplace_back( std::jthread{fib, 40});
      cout << ti << "... "; cout.flush();
    }
    for(auto &th : threads) th.join(); // explizit joinen vor der Zeitmessung

    const auto now = steady_clock::now();
    cout << "  Zeit:  " << duration_cast<milliseconds>(
        now-start).count()<<"ms\n";
  }
}

Okt 23, 2024

lst-0999-book.cpp

// https://godbolt.org/z/PP4GT3oc6 
#include <iostream>
#include <thread>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long n) {
    auto r = fib(n);
    cout << "fib("<<n<<")=" << r << endl;
}
long ack(long m, long n) { // Ackermannfunktion
    if(m==0) return n+1;
    if(n==0) return ack(m-1, 1);
    return ack(m - 1, ack(m, n-1));
}
void runAck(long m, long n) {
    auto r = ack(m, n);
    cout << "ack("<<m<<','<<n<<")=" << r << endl;
}

int main() {
    std::jthread f40{ runFib, 40 };
    std::jthread f41{ runFib, 41 };
    std::jthread f42{ runFib, 42 };

    f40.join(); f41.join(); f42.join();

    std::thread a1{ runAck, 4, 0 };
    std::thread a2{ runAck, 4, 1 };
    std::thread a3{ runAck, 2, 700 };
    std::thread a4{ runAck, 3, 10 };
}

Okt 23, 2024

lst-1000-book.cpp

// https://godbolt.org/z/fbnbKzrs1 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s

void delayPrint(seconds s, const std::string& msg) {
    std::this_thread::sleep_for(s);
    std::cout << msg << std::endl;
}
int main() {
    std::jthread m1{ delayPrint, 1s, "Auf die Plaetze" };
    std::jthread m2{ delayPrint, 2s, std::string{"fertig"} };
    std::string los = "los";
    std::jthread m3{ delayPrint, 3s, los };
}

Okt 23, 2024

lst-0998-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8TdzEGf3d 
void hauptprogramm() {
    std::jthread th{ &aufgabe1 };
    std::vector data{ 0,1,2 };
    data.at(666);                 //             (ERR)  löst out_of_range aus
}

Okt 23, 2024

lst-1017-book.cpp

// https://godbolt.org/z/1boeTMMvf 
MxStack<int> mxs{};
// 
// mehr Code
// 
if( ! mxs.isEmpty()) {            //                 (ERR)  nicht sicher
    const auto value = mxs.top(); //                 (ERR)  nicht sicher
    mxs.pop();                    //                 (ERR)  nicht sicher
    // 
    // mehr Code
    // 
}

Okt 23, 2024

lst-1015-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3fz5a4vYv 
#include <mutex> // mutex, lock_guard
#include <list>
#include <algorithm> // find
using std::lock_guard; using std::mutex; using std::find;
class MxIntList {
    std::list <int> data_;
    mutable mutex mx_;
public:
    void add(int value) {
        lock_guard guard{mx_};  // schützt bis Ende der Methode
        data_.push_back(value);
    }
    bool contains(int searchVal) const {
        lock_guard guard{mx_};  // schützt bis Ende der Methode
        return find(data_.begin(), data_.end(), searchVal) != data_.end();
    }
};

Okt 23, 2024

lst-1006-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YrEPnYMaP 
#include <iostream>
#include <thread>
#include <vector>
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long n) { auto r = fib(n); cout << "fib("<<n<<")=" << r << endl; }
int main() {
    std::vector<std::jthread> threads;
    // starten
    for( auto n : { 38, 39, 40, 41, 42, 43, }) {
        threads.emplace_back( runFib, n );
    }
}

Okt 23, 2024

lst-1023-book.cpp

// https://godbolt.org/z/e7rraPGx4 
#include <thread>
#include <mutex>
#include <vector>
#include <numeric> // accumulate, iota
using std::mutex; using std::unique_lock;

std::vector<int> myData;             // geteilte Daten
mutex myMutex;                       // Mutex zu den Daten
unique_lock<mutex> bereiteDatenVor() {
    unique_lock lk1{myMutex};        // sperren
    myData.resize(1000);
    std::iota(myData.begin(), myData.end(), 1); // 1..1000
    return lk1;                                 // Sperre transferieren
}
int verarbeiteDaten() {
    unique_lock lk2 = bereiteDatenVor();        // Sperre transferiert
    return std::accumulate(myData.begin(), myData.end(), 0);
}

Okt 23, 2024

lst-0997-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1aj16d7Ga 
#include <iostream>
#include <thread>
#include <vector>
#include <exception>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }

void hauptprogramm() {
    std::thread th{ &aufgabe1 };
    try {
        std::vector data{ 0,1,2 };
        data.at(666);                 //             (ERR)  löst out_of_range aus
    } catch(std::runtime_error &ex) { // passt nicht auf out_of_range
         /* ... */                        // speziellen Fehler hier behandeln
    } catch( ... ) {
        th.join();
        throw;                        // Fehlerbehandlung außen fortsetzen
    }
    th.join();                        // wartet nach Okay oder speziellem Fehler
}

int main() {
    try {
        hauptprogramm();
    } catch( ... ) {
        std::cout << "Ein Fehler ist aufgetreten\n";
    }
}

Okt 23, 2024

lst-0994-book.cpp

// https://godbolt.org/z/6cqd7Tsae 
struct HintergrundAufgabe {
    void operator()(std::stop_token st) const { // Token fürs Kommunizieren
        aufgabe1();
        if(st.stop_requested()) return;
        aufgabe2();
        if(st.stop_requested()) return;
        aufgabe3();
    }
};
int main() {
    HintergrundAufgabe hintergrundAufgabe{};
    std::jthread meinThread{ hintergrundAufgabe };
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // warte 100ms
    meinThread.request_stop(); // bitte den Thread, sich zu beenden
}

Okt 23, 2024

lst-0961-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/o359TThMj 
#include <iostream>
#include <string>
#include <chrono>
#include <complex>
using std::cout;
int main() {
    { using namespace std;
      cout << "string"s << "\n";           // string
      cout << (1.2+3.4i) << "\n";          // complex
      }
    { using namespace std::chrono;
      cout << (35ms).count() << "ms\n";    // chrono
      }
    { using namespace std::literals;
      cout << (41s).count() << "ms\n";     // chrono seconds
      cout << "text"s << "\n";             // string
    }
    { using namespace std::chrono; 
      cout << (4h).count() << "h\n";       // chrono hours
    }
    { using namespace std::literals::chrono_literals; 
      cout << (16min).count() << "min\n";  // chrono minutes
    }
    { using std::literals::string_literals::operator""s; 
      cout << "buchstaben"s << "\n";        // string
    }
}

Okt 23, 2024

lst-0968-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n4v78WWod 
#include <system_error>
#include <string>

void create_dir(const std::string& pathname, std::error_code& ec) {
#if defined(_WIN32)
  // Windows-Implementierung, mit Windows-Fehlercodes
#elif defined(linux)
  // Linux-Implementierung, mit Linux-Fehlercodes
#else
  // allgemeingültiger 'generischer' Fall
  ec = std::make_error_code(std::errc::not_supported);
#endif
}

Okt 23, 2024

lst-0954-book.cpp

// https://godbolt.org/z/q1znGWb85 
#include <iostream>
#include <chrono>
int main() {
    using namespace std::chrono;
    time_point<system_clock, seconds> t1{10000s};
    time_point<system_clock, seconds> t2{50000s};
    auto dur = t2 - t1;
    std::cout << duration_cast<hours>(dur).count() << "h"; // Ausgabe: 11h
}

Okt 23, 2024

lst-0971-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a8zP84j1x 
#include <thread>
#include <iostream>
#include <system_error>
int main() {
    try {
        std::thread().detach(); // das wird fehlschlagen
    } catch(std::system_error& e) {
        std::cout
            << "system_error mit Code:" << e.code()
            << " Meldung:" << e.what()
            << '\n';
    }
}

Okt 23, 2024

lst-0977-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/j85P7b3oq 
#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <functional>
std::map<char,std::function<int(int,int)>> binOps { // zweistellige Operatoren
    {'+', std::plus<int>{} },
    {'-', std::minus<int>{} },
    {'*', std::multiplies<int>{} },
    {'/', std::divides<int>{} },
    {'%', std::modulus<int>{} },
    };
std::map<char,std::function<int(int)>> unOps { };    // einstellige Operatoren
auto val = [](auto n) { return [n](){ return n; };}; // gibt ein Lambda zurück
std::map<char,std::function<int()>> zeroOps {        // nullstellige Operatoren
  {'0', val(0)}, {'1', val(1)}, {'2', val(2)}, {'3', val(3)}, {'4', val(4)},
  {'5', val(5)}, {'6', val(6)}, {'7', val(7)}, {'8', val(8)}, {'9', val(9)},
  };
std::map<char,std::function<void(std::vector<int>&)>> stapelOps { 
  { ' ', [](auto &stapel) { } },           // keine Operation
  { 'c', [](auto &stapel) { stapel.clear(); } }, // Stapel ganz löschen
  { ':', [](auto &stapel) {                // obersten zwei Elemente vertauschen
            auto top = stapel.back(); stapel.pop_back();
            auto second = stapel.back(); stapel.pop_back();
            stapel.push_back(top);
            stapel.push_back(second);
  } },
  { '=', [](auto &stapel) {                // ganzen Stapel ausgeben
            for(int elem : stapel) { std::cout << elem; }
            std::cout << "\n";
  } },
};
void rechner(std::string input) {
  std::vector<int> stapel {};
  for(char c : input) {
    int top, second;
    if(auto it = unOps.find(c); it != unOps.end()) {
      // falls einstelliger Operator 
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); //  hole oberstes Element
      stapel.push_back(func(top));         //  wende func an, Ergebnis auf Stapel
    } else if(auto it = binOps.find(c); it != binOps.end()) {
      // falls zweistelliger Operator 
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); //  hole die obersten 2 Elemente
      second = stapel.back(); stapel.pop_back();
      stapel.push_back(func(second, top)); //  wende func an, Ergebnis auf Stapel
    } else if(auto it = zeroOps.find(c); it !=zeroOps.end()) {
      // falls nullstelliger Operator 
      auto func = it->second;
      stapel.push_back(func());            //  Ergebnis von func auf Stapel
    } else if(auto it = stapelOps.find(c); it !=stapelOps.end()) {
      // falls Stapeloperator
      auto func = it->second;
      func(stapel);                        //  wende func auf Stapel an
    } else {
      std::cout << "\n'" << c << "' verstehe ich nicht.\n";
    }
  } /* for c */
}
int main(int argc, const char* argv[]) {
    if(argc > 1) {
        rechner(argv[1]);
    } else {
        // 3+4*5+6 mit Punkt- vor Strichrechnung ergibt 29
        rechner("345*+6+=");
    }
    rechner("93-=");                     // 9  3 = Ausgabe: 6
    rechner("82/=");                     // 8 / 2 = Ausgabe: 4
    rechner("92%=");                     // 9 % 2 = Ausgabe: 1
}

Okt 23, 2024

lst-0963-book.cpp

// https://godbolt.org/z/TPWc5nexq 
#include <system_error> // error_code, errc
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
  std::error_code ec;
  create_dir("/some/path", ec);
  if(ec == std::errc::file_exists) {   // speziell …
  } else if(!ec) {                     // Erfolg …
  } else {                             // Misserfolg …
  }
}

Okt 23, 2024

lst-0996-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1jhrx1MMn 
#include <iostream>
#include <thread>
#include <vector>
#include <exception>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }

void hauptprogramm() {
    try {
        std::thread th{ &aufgabe1 };
        std::vector data{ 0,1,2 };
        data.at(666);                     //             (ERR)  löst out_of_range aus
        th.join();                        // würde warten
    } catch(std::runtime_error &ex) {           //             (ERR)  passt nicht auf out_of_range
         /*...*/
    }
}

int main() {
  try {
    hauptprogramm();
  } catch( ... ) {                               // so weit, so gut, sieht sicher aus
    std::cout << "Ein Fehler ist aufgetreten\n"; // bekommen Sie nicht zu Gesicht
  }
}

Okt 23, 2024

lst-0962-book.cpp

// https://godbolt.org/z/1xnY8vd8Y 
#include <system_error> // error_code
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
  std::error_code ec;
  create_dir("/some/path", ec);
  if(!ec) {  // Erfolg …
  } else {   // Misserfolg …
  }
}

Okt 23, 2024

lst-0994-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6cqd7Tsae 
struct HintergrundAufgabe {
    void operator()(std::stop_token st) const { // Token fürs Kommunizieren
        aufgabe1();
        if(st.stop_requested()) return;
        aufgabe2();
        if(st.stop_requested()) return;
        aufgabe3();
    }
};
int main() {
    HintergrundAufgabe hintergrundAufgabe{};
    std::jthread meinThread{ hintergrundAufgabe };
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // warte 100ms
    meinThread.request_stop(); // bitte den Thread, sich zu beenden
}

Okt 23, 2024

lst-0963-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TPWc5nexq 
#include <system_error> // error_code, errc
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
  std::error_code ec;
  create_dir("/some/path", ec);
  if(ec == std::errc::file_exists) {   // speziell 
  } else if(!ec) {                     // Erfolg 
  } else {                             // Misserfolg 
  }
}

Okt 23, 2024

lst-0974-book.cpp

// https://godbolt.org/z/n54566cqT 
#include <iostream>
#include <typeinfo>
#include <string>
#include <map>
#include <boost/core/typeinfo.hpp>
int main() {
  using std::string; using std::cout;
  std::map<int, string> namen;
  int ganz;
  double fliessend;
  // demangled_name
  using boost::core::demangled_name;
  cout<<demangled_name(BOOST_CORE_TYPEID(ganz))<<'\n';      // Ausgabe: int
  cout<<demangled_name(BOOST_CORE_TYPEID(fliessend))<<'\n'; // Ausgabe: double
  cout<<demangled_name(BOOST_CORE_TYPEID(string))<<'\n';  // Ausgabe: std::string
  cout<<demangled_name(BOOST_CORE_TYPEID(string{}.begin()))<<'\n';
  // Ausgabe: __gnu_cxx::__normal_iterator<char*, std::string>
  cout<<demangled_name(BOOST_CORE_TYPEID(namen))<<'\n';
  // Ausgabe: std::map<int, std::string, std::less<int>,
  //                                                         std::allocator<std::pair<int const, std::string> > >
  cout<<demangled_name(BOOST_CORE_TYPEID(666/0))<<'\n';  // Ausgabe: int
}

Okt 23, 2024

lst-0982-book.cpp

// https://godbolt.org/z/a3aTx7K7h 
#include <functional>
#include <iostream>
struct Zahlen {
    int dieZahl() {
        return 42;
    }
    int mehr(int n) {
        return n + data;
    }
    int data = 7;
};
int main() {
    auto func = std::mem_fn(&Zahlen::dieZahl);
    auto func2 = std::mem_fn(&Zahlen::mehr);
    auto zugriff = std::mem_fn(&Zahlen::data);
    Zahlen zahlen;
    std::cout << func(zahlen) << '\n';        // Ausgabe: 42
    std::cout << func2(zahlen, 66) << '\n';   // Ausgabe: 73
    std::cout << zugriff(zahlen) << '\n';     // Ausgabe: 7
}

Okt 23, 2024

lst-0971-book.cpp

// https://godbolt.org/z/a8zP84j1x 
#include <thread>
#include <iostream>
#include <system_error>
int main() {
    try {
        std::thread().detach(); // das wird fehlschlagen
    } catch(std::system_error& e) {
        std::cout
            << "system_error mit Code:" << e.code()
            << " Meldung:" << e.what()
            << '\n';
    }
}

Okt 23, 2024

lst-0983-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/P8d494P6c 
#include <variant> 
using std::get;
int main() {
    std::variant<int, float> v{};
    v = 12;                  // Zustand wechselt auf int
    auto i = get<int>(v);    // holt den int
    std::cout << i << '\n';  // Ausgabe: 12
    v = 3.456f;              // Zustand wechselt auf float
    std::cout << get<float>(v) << '\n';  // Ausgabe: 3.456
    get<double>(v);          //             (ERR)  Fehler
    get<3>(v);               //             (ERR)  Fehler
    std::variant<int, float> w{};
    w = get<float>(v);       // Zugriff über Typ
    w = get<1>(v);           // Zugriff geht auch über Index
    w = v;                   // ganze Zuweisung geht auch
    try {
        get<int>(w);         // löst Exception aus
    } catch (std::bad_variant_access&) { /* ... */ }
}

Okt 23, 2024

lst-0978-book.cpp

// https://godbolt.org/z/e6xT638ch 
#include <functional> // substract, minus, bind
#include <iostream>
using std::cout;
int substract(int a, int b) { return a - b; }
int main() {
    using namespace std::placeholders;
    cout << substract(9, 3) << '\n';  // Ausgabe: 6
    auto minus3 = std::bind(substract, _1, 3);
    cout << minus3(9) << '\n';        // Ausgabe: 6
    auto von9 = std::bind(substract, 9, _1);
    cout << von9(3) << '\n';          // Ausgabe: 6
    auto nochmalMinus3 = std::bind(std::minus<int>{}, _1, 3);
    cout << nochmalMinus3(9) << '\n'; // Ausgabe: 6
}

Okt 23, 2024

lst-0977-book.cpp

// https://godbolt.org/z/j85P7b3oq 
#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <functional>
std::map<char,std::function<int(int,int)>> binOps { // zweistellige Operatoren
    {'+', std::plus<int>{} },
    {'-', std::minus<int>{} },
    {'*', std::multiplies<int>{} },
    {'/', std::divides<int>{} },
    {'%', std::modulus<int>{} },
    };
std::map<char,std::function<int(int)>> unOps { };    // einstellige Operatoren
auto val = [](auto n) { return [n](){ return n; };}; // gibt ein Lambda zurück
std::map<char,std::function<int()>> zeroOps {        // nullstellige Operatoren
  {'0', val(0)}, {'1', val(1)}, {'2', val(2)}, {'3', val(3)}, {'4', val(4)},
  {'5', val(5)}, {'6', val(6)}, {'7', val(7)}, {'8', val(8)}, {'9', val(9)},
  };
std::map<char,std::function<void(std::vector<int>&)>> stapelOps { 
  { ' ', [](auto &stapel) { } },           // keine Operation
  { 'c', [](auto &stapel) { stapel.clear(); } }, // Stapel ganz löschen
  { ':', [](auto &stapel) {                // obersten zwei Elemente vertauschen
            auto top = stapel.back(); stapel.pop_back();
            auto second = stapel.back(); stapel.pop_back();
            stapel.push_back(top);
            stapel.push_back(second);
  } },
  { '=', [](auto &stapel) {                // ganzen Stapel ausgeben
            for(int elem : stapel) { std::cout << elem; }
            std::cout << "\n";
  } },
};
void rechner(std::string input) {
  std::vector<int> stapel {};
  for(char c : input) {
    int top, second;
    if(auto it = unOps.find(c); it != unOps.end()) {
      // falls einstelliger Operator 
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); //  hole oberstes Element
      stapel.push_back(func(top));         //  wende func an, Ergebnis auf Stapel
    } else if(auto it = binOps.find(c); it != binOps.end()) {
      // falls zweistelliger Operator 
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); //  hole die obersten 2 Elemente
      second = stapel.back(); stapel.pop_back();
      stapel.push_back(func(second, top)); //  wende func an, Ergebnis auf Stapel
    } else if(auto it = zeroOps.find(c); it !=zeroOps.end()) {
      // falls nullstelliger Operator 
      auto func = it->second;
      stapel.push_back(func());            //  Ergebnis von func auf Stapel
    } else if(auto it = stapelOps.find(c); it !=stapelOps.end()) {
      // falls Stapeloperator
      auto func = it->second;
      func(stapel);                        //  wende func auf Stapel an
    } else {
      std::cout << "\n'" << c << "' verstehe ich nicht.\n";
    }
  } /* for c */
}
int main(int argc, const char* argv[]) {
    if(argc > 1) {
        rechner(argv[1]);
    } else {
        // 3+4*5+6 mit Punkt- vor Strichrechnung ergibt 29
        rechner("345*+6+=");
    }
    rechner("93-=");                     // 9  3 = Ausgabe: 6
    rechner("82/=");                     // 8 / 2 = Ausgabe: 4
    rechner("92%=");                     // 9 % 2 = Ausgabe: 1
}

Okt 23, 2024

lst-0959-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rz38hc1cx 
auto res = fib(45);
// 
std::cout << "Zeit: " << duration_cast<seconds>(t1-t0).count() << "s\n";
// Ausgabe: Zeit: 7s (z. B.)
std::cout << "Zeit: " << duration<double>{t1-t0}.count() << "s\n";
// Ausgabe: Zeit: 7.35303s (z. B.)
}

Okt 23, 2024

lst-0979-book.cpp

// https://godbolt.org/z/xxfbGd9Ma 
#include <random>
#include <vector>
#include <iostream>
#include <functional>
void wuerfel() {
  std::default_random_engine engine{};
  std::vector<size_t> counts{0,0,0,0,0,0};
  std::uniform_int_distribution<int> w6{0, 5}; // gleichverteilte Ganzzahlen
  auto w = std::bind(w6, engine);              // w() = w6(engine)
  for(auto i=1200*1000; i>0; --i) ++counts[w()];
  for(auto c : counts) std::cout<<" "<<c;
  std::cout << '\n';
}
int main() {
    wuerfel();
}

Okt 23, 2024

lst-0991-book.cpp

// https://godbolt.org/z/qnadYPWh1 
#include <iostream>
#include <thread>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }
void aufgabe2() { auto r = fib(41); cout << "fib(41)=" << r << endl; }
void aufgabe3() { auto r = fib(42); cout << "fib(42)=" << r << endl; }

struct HintergrundAufgabe {
    void operator()() const {
        aufgabe1();
        aufgabe2();
        aufgabe3();
    }
};

int main() {
    HintergrundAufgabe hintergrundAufgabe{};  // Initialisierung, berechnet noch nichts
    std::jthread meinThread{ hintergrundAufgabe }; // Berechnung startet
}

Okt 23, 2024

lst-0976-book.cpp

// https://godbolt.org/z/Y3GsPd97d 
#include <set>
#include <string>
struct Drachen {
    std::string name_;
};
namespace std {
    template<> struct less<Drachen> { // Templatespezialisierung
        bool operator()(const Drachen &lhs, const Drachen &rhs) const {
            return lhs.name_ < rhs.name_;
} }; }
int main() {
  std::set<Drachen> drachen {
    Drachen{"Smaug"},Drachen{"Glaurung"},
        Drachen{"Ancalagon"},Drachen{"Scatha"}};
}

Okt 23, 2024

lst-0958-book.cpp

// https://godbolt.org/z/8hxd9bPb4 
#include <iostream>
#include <chrono>
long fib(long n) { return n<2L ? 1L : fib(n-1L)+fib(n-2L); }
int main() {
    using namespace std::chrono;
    auto t0 = steady_clock::now();  // Auf die Plätze, fertig …
    auto res = fib(17);             // … los!
    auto t1 = steady_clock::now();  // Stopp!
    std::cout << "Ergebnis: " << res << "\n"; // Ausgabe: Ergebnis: 2584
    std::cout << "Zeit: " << nanoseconds{t1-t0}.count() << "ns\n";
    // Ausgabe: Zeit: 50727ns (z. B.)
}

Okt 23, 2024

lst-0968-book.cpp

// https://godbolt.org/z/n4v78WWod 
#include <system_error>
#include <string>

void create_dir(const std::string& pathname, std::error_code& ec) {
#if defined(_WIN32)
  // Windows-Implementierung, mit Windows-Fehlercodes
#elif defined(linux)
  // Linux-Implementierung, mit Linux-Fehlercodes
#else
  // allgemeingültiger 'generischer' Fall
  ec = std::make_error_code(std::errc::not_supported);
#endif
}

Okt 23, 2024

lst-0960-book.cpp

// https://godbolt.org/z/1xbhhTdEv 
#include <iostream>
#include <chrono>
int main() {
    using namespace std::chrono;
    auto tp = time_point_cast<seconds>(system_clock::now());
    auto d = tp.time_since_epoch();
    std::cout << d.count() << "s\n";
    std::cout << duration<double,std::ratio<86400>>{d}.count() << "days\n";
}

Okt 23, 2024

lst-0995-book.cpp

// https://godbolt.org/z/Tzs93MzfK 
std::thread meinThread{ [] {  // purer Thread
    aufgabe1();
    aufgabe2();
    aufgabe3();
} };
meinThread.join();   // wartet auf das Ende des Threads

Okt 23, 2024

lst-0995-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Tzs93MzfK 
std::thread meinThread{ [] {  // purer Thread
    aufgabe1();
    aufgabe2();
    aufgabe3();
} };
meinThread.join();   // wartet auf das Ende des Threads

Okt 23, 2024

lst-0972-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cjh93oPcr 
#include <iostream>
#include <system_error> // std::make_error_condition, std::ios_errc
int main () {
  // umschalten auf Exceptions:
  std::cin.exceptions (std::ios::failbit|std::ios::badbit);
  try {
    std::cin.rdbuf(nullptr);       // löst eine Exception aus
  } catch (std::ios::failure& e) { // abgeleitet von system_error
    std::cerr << "Fehler: ";
    if (e.code() == std::make_error_condition(std::io_errc::stream)) {
      std::cerr << "stream\n";
    } else {
      std::cerr << "andere\n";
    }
  }
}

Okt 23, 2024

lst-0969-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vxTxT4ajW 
#include <system_error>
#include <iostream>
using std::error_code; using std::system_category;
namespace mylib {
    // eigene Errorcodes
    enum class errc { LOAD_ERR = 1, UNLOAD_ERR = 2, OTHER_ERR = 3 };
    error_code make_error_code(errc ec) {
        switch(ec) {
        case errc::LOAD_ERR: return error_code((int)ec, system_category());
        case errc::UNLOAD_ERR: return error_code((int)ec, system_category());
        case errc::OTHER_ERR: return error_code((int)ec, system_category());
        }
    }
    error_code run(int arg) {
        if(arg == 667) {
            return make_error_code(errc::OTHER_ERR);
        }
        return error_code{}; // alles gut.
    }
}
int main() {
    std::error_code ec = mylib::run(667);
    if(!ec) {
        std::cout << "Klasse, klappt!\n";
    } else if (ec == mylib::make_error_code(mylib::errc::OTHER_ERR)) {
        std::cout << "Anderer Fehler\n";
    } else {
        std::cout << "Nix los hier\n" << ec;
    }
}

Okt 23, 2024

lst-0984-book.cpp

// https://godbolt.org/z/ce3jETW6W 
#include <variant>
#include <iostream>
using std::cout;
struct TypGruss {
  void operator()(int) const { cout << "Hallo int"; }
  void operator()(float) const { cout << "Servus float"; }
};
int main() {
    std::variant<int, float> var{};
    var = 12;                                   // Zustand int
    std::visit([](auto a) { cout << a; }, var); // generisches Lambda
    cout << std::endl;
    var = 3.456f;                               // Zustand float
    std::visit(TypGruss{}, var);                // Funktor mit Überladungen
    cout << std::endl;
}

Okt 23, 2024

lst-0960-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xbhhTdEv 
#include <iostream>
#include <chrono>
int main() {
    using namespace std::chrono;
    auto tp = time_point_cast<seconds>(system_clock::now());
    auto d = tp.time_since_epoch();
    std::cout << d.count() << "s\n";
    std::cout << duration<double,std::ratio<86400>>{d}.count() << "days\n";
}

Okt 23, 2024

lst-0962-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xnY8vd8Y 
#include <system_error> // error_code
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
  std::error_code ec;
  create_dir("/some/path", ec);
  if(!ec) {  // Erfolg 
  } else {   // Misserfolg 
  }
}

Okt 23, 2024

lst-0991-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qnadYPWh1 
#include <iostream>
#include <thread>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }
void aufgabe2() { auto r = fib(41); cout << "fib(41)=" << r << endl; }
void aufgabe3() { auto r = fib(42); cout << "fib(42)=" << r << endl; }

struct HintergrundAufgabe {
    void operator()() const {
        aufgabe1();
        aufgabe2();
        aufgabe3();
    }
};

int main() {
    HintergrundAufgabe hintergrundAufgabe{};  // Initialisierung, berechnet noch nichts
    std::jthread meinThread{ hintergrundAufgabe }; // Berechnung startet
}

Okt 23, 2024

lst-0990-book.cpp

// https://godbolt.org/z/dcqenEd31 
#include <iostream>
#include <charconv>
#include <string_view>
#include <array>
int main() {
    std::array<char, 10> str {};
    if(auto [p, ec] = std::to_chars(str.data(), str.data() + str.size(), 42);
       ec == std::errc{} )
        std::cout << std::string_view(str.data(), p - str.data()) << "\n";
}

Okt 23, 2024

lst-0978-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/e6xT638ch 
#include <functional> // substract, minus, bind
#include <iostream>
using std::cout;
int substract(int a, int b) { return a - b; }
int main() {
    using namespace std::placeholders;
    cout << substract(9, 3) << '\n';  // Ausgabe: 6
    auto minus3 = std::bind(substract, _1, 3);
    cout << minus3(9) << '\n';        // Ausgabe: 6
    auto von9 = std::bind(substract, 9, _1);
    cout << von9(3) << '\n';          // Ausgabe: 6
    auto nochmalMinus3 = std::bind(std::minus<int>{}, _1, 3);
    cout << nochmalMinus3(9) << '\n'; // Ausgabe: 6
}

Okt 23, 2024

lst-0958-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8hxd9bPb4 
#include <iostream>
#include <chrono>
long fib(long n) { return n<2L ? 1L : fib(n-1L)+fib(n-2L); }
int main() {
    using namespace std::chrono;
    auto t0 = steady_clock::now();  // Auf die Plätze, fertig 
    auto res = fib(17);             //  los!
    auto t1 = steady_clock::now();  // Stopp!
    std::cout << "Ergebnis: " << res << "\n"; // Ausgabe: Ergebnis: 2584
    std::cout << "Zeit: " << nanoseconds{t1-t0}.count() << "ns\n";
    // Ausgabe: Zeit: 50727ns (z. B.)
}

Okt 23, 2024

lst-0993-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nPGY47r4K 
std::jthread meinThread{ [] {
    aufgabe1();
    aufgabe2();
    aufgabe3();
} };

Okt 23, 2024

lst-0976-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y3GsPd97d 
#include <set>
#include <string>
struct Drachen {
    std::string name_;
};
namespace std {
    template<> struct less<Drachen> { // Templatespezialisierung
        bool operator()(const Drachen &lhs, const Drachen &rhs) const {
            return lhs.name_ < rhs.name_;
} }; }
int main() {
  std::set<Drachen> drachen {
    Drachen{"Smaug"},Drachen{"Glaurung"},
        Drachen{"Ancalagon"},Drachen{"Scatha"}};
}

Okt 23, 2024

lst-0973-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/x1dq1Wof6 
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>
struct Base {
    virtual ~Base() {}
};
struct Derived_One : public Base {};
struct Derived_Two : public Base {};
int main() {
  using std::string; using std::cout; using std::type_index;
  std::map<std::type_index, string> namen {
      { type_index(typeid(int)), "int" },
      { type_index(typeid(double)), "double" },
      { type_index(typeid(Base)), "Base" },
      { type_index(typeid(Derived_One)), "Derived_One" },
      { type_index(typeid(Derived_Two)), "Derived_Two" },
      { type_index(typeid(string)), "string" },
      { type_index(typeid(string::const_iterator)), "string" },
  };
  namen[type_index(typeid(namen))] = "namen-map";
  int ganz;
  double fliessend;
  Base base{};
  Base *one = new Derived_One{};
  Base *two = new Derived_Two{};
  // typeid.name() ist implementierungs- und laufzeitabhängig:
  cout << typeid(ganz).name() << '\n';      // Bei mir: i
  cout << typeid(fliessend).name() << '\n'; // Bei mir: d
  cout << typeid(base).name() << '\n';      // Bei mir: 4Base
  cout << typeid(*one).name() << '\n';      // Bei mir: 11Derived_One
  cout << typeid(*two).name() << '\n';      // Bei mir: 11Derived_Two
  cout << typeid(string).name() << '\n';    // Bei mir: Ss
  cout << typeid(string{"Welt"}.begin()).name() << '\n';
      // Bei mir: N9__gnu_cxx17__normal_iteratorIPcSsEE
  cout << typeid(namen).name() << '\n';
      // Bei mir: St3mapISt10type_indexSsSt4lessIS0_ESaISt4pairIKS0_SsEEE
  cout << typeid(666/0).name() << '\n'; // Ausdruck wird nicht ausgeführt! Bei mir: i
  // type_index macht type_infos vergleichbar:
  cout << namen[type_index(typeid(ganz))] << '\n';      // Ausgabe: int
  cout << namen[type_index(typeid(fliessend))] << '\n'; // Ausgabe: double
  cout << namen[type_index(typeid(base))] << '\n';      // Ausgabe: Base
  cout << namen[type_index(typeid(*one))] << '\n';      // Ausgabe: Derived_One
  cout << namen[type_index(typeid(*two))] << '\n';      // Ausgabe: Derived_Two
  cout << namen[type_index(typeid(string))] << '\n';    // Ausgabe: string
  cout << namen[type_index(typeid(namen))] << '\n';     // Ausgabe: namen-map
}

Okt 23, 2024

lst-0984-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ce3jETW6W 
#include <variant>
#include <iostream>
using std::cout;
struct TypGruss {
  void operator()(int) const { cout << "Hallo int"; }
  void operator()(float) const { cout << "Servus float"; }
};
int main() {
    std::variant<int, float> var{};
    var = 12;                                   // Zustand int
    std::visit([](auto a) { cout << a; }, var); // generisches Lambda
    cout << std::endl;
    var = 3.456f;                               // Zustand float
    std::visit(TypGruss{}, var);                // Funktor mit Überladungen
    cout << std::endl;
}

Okt 23, 2024

lst-0959-book.cpp

// https://godbolt.org/z/rz38hc1cx 
auto res = fib(45);
// …
std::cout << "Zeit: " << duration_cast<seconds>(t1-t0).count() << "s\n";
// Ausgabe: Zeit: 7s (z. B.)
std::cout << "Zeit: " << duration<double>{t1-t0}.count() << "s\n";
// Ausgabe: Zeit: 7.35303s (z. B.)
}

Okt 23, 2024

lst-0982-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a3aTx7K7h 
#include <functional>
#include <iostream>
struct Zahlen {
    int dieZahl() {
        return 42;
    }
    int mehr(int n) {
        return n + data;
    }
    int data = 7;
};
int main() {
    auto func = std::mem_fn(&Zahlen::dieZahl);
    auto func2 = std::mem_fn(&Zahlen::mehr);
    auto zugriff = std::mem_fn(&Zahlen::data);
    Zahlen zahlen;
    std::cout << func(zahlen) << '\n';        // Ausgabe: 42
    std::cout << func2(zahlen, 66) << '\n';   // Ausgabe: 73
    std::cout << zugriff(zahlen) << '\n';     // Ausgabe: 7
}

Okt 23, 2024

lst-0954-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/q1znGWb85 
#include <iostream>
#include <chrono>
int main() {
    using namespace std::chrono;
    time_point<system_clock, seconds> t1{10000s};
    time_point<system_clock, seconds> t2{50000s};
    auto dur = t2 - t1;
    std::cout << duration_cast<hours>(dur).count() << "h"; // Ausgabe: 11h
}

Okt 23, 2024

lst-0973-book.cpp

// https://godbolt.org/z/x1dq1Wof6 
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>
struct Base {
    virtual ~Base() {}
};
struct Derived_One : public Base {};
struct Derived_Two : public Base {};
int main() {
  using std::string; using std::cout; using std::type_index;
  std::map<std::type_index, string> namen {
      { type_index(typeid(int)), "int" },
      { type_index(typeid(double)), "double" },
      { type_index(typeid(Base)), "Base" },
      { type_index(typeid(Derived_One)), "Derived_One" },
      { type_index(typeid(Derived_Two)), "Derived_Two" },
      { type_index(typeid(string)), "string" },
      { type_index(typeid(string::const_iterator)), "string" },
  };
  namen[type_index(typeid(namen))] = "namen-map";
  int ganz;
  double fliessend;
  Base base{};
  Base *one = new Derived_One{};
  Base *two = new Derived_Two{};
  // typeid.name() ist implementierungs- und laufzeitabhängig:
  cout << typeid(ganz).name() << '\n';      // Bei mir: i
  cout << typeid(fliessend).name() << '\n'; // Bei mir: d
  cout << typeid(base).name() << '\n';      // Bei mir: 4Base
  cout << typeid(*one).name() << '\n';      // Bei mir: 11Derived_One
  cout << typeid(*two).name() << '\n';      // Bei mir: 11Derived_Two
  cout << typeid(string).name() << '\n';    // Bei mir: Ss
  cout << typeid(string{"Welt"}.begin()).name() << '\n';
      // Bei mir: N9__gnu_cxx17__normal_iteratorIPcSsEE
  cout << typeid(namen).name() << '\n';
      // Bei mir: St3mapISt10type_indexSsSt4lessIS0_ESaISt4pairIKS0_SsEEE
  cout << typeid(666/0).name() << '\n'; // Ausdruck wird nicht ausgeführt! Bei mir: i
  // type_index macht type_infos vergleichbar:
  cout << namen[type_index(typeid(ganz))] << '\n';      // Ausgabe: int
  cout << namen[type_index(typeid(fliessend))] << '\n'; // Ausgabe: double
  cout << namen[type_index(typeid(base))] << '\n';      // Ausgabe: Base
  cout << namen[type_index(typeid(*one))] << '\n';      // Ausgabe: Derived_One
  cout << namen[type_index(typeid(*two))] << '\n';      // Ausgabe: Derived_Two
  cout << namen[type_index(typeid(string))] << '\n';    // Ausgabe: string
  cout << namen[type_index(typeid(namen))] << '\n';     // Ausgabe: namen-map
}

Okt 23, 2024

lst-0985-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1eco9Wcr3 
#include <any>
#include <iostream>
#include <vector>
#include <string>
int main() {
    std::any a = 5;
    std::cout << std::any_cast<int>(a) << '\n';
    a = 3.456;
    std::cout << std::any_cast<double>(a) << '\n';
    using namespace std::literals;
    std::vector<std::any> data { 4, 8.976, "Geronimo"s };
    std::cout << std::any_cast<double>( data[1] ) << '\n';
    std::cout << data[1].type().name()  << '\n';
}

Okt 23, 2024

lst-0988-book.cpp

// https://godbolt.org/z/r5PqK8M8o 
#include <charconv>
#include <vector>
#include <iostream>
#include <string>

std::vector<size_t> num_to_vec(const std::string& nums) {
    std::vector<size_t> result {};
    // ohne Leerzeichen am Ende
    const auto end = nums.data() + nums.find_last_not_of( ' ' ) + 1;
    const char* st = nullptr; // Zählpointer in der Schleife
    auto last = nums.data();  // letztes nicht übersetztes Zeichen
    size_t n;                 // konvertierte Zahl
    do {
        for(st = last; (st<end)&&(*st==' ' ); ++st); // überspringe ' '
        if (last = std::from_chars(st, end, n).ptr; last != st)
            result.push_back(n);                     // speichere Zahl
    } while (last != st);
    return result;
}

void fehlerDemo(const char* buf, size_t sz) {
    int n;
    auto [p, ec] = std::from_chars(buf, buf+sz, n);
    if (ec != std::errc{}) {
       const auto error = std::make_error_code(ec);
       std::cout << error.message() << '\n';
    }
}

int main() {
    auto result = num_to_vec("12 33 43");

    for(auto r : result) std::cout << r << " ";
    std::cout << '\n';
    // Ausgabe: 12 33 43

    fehlerDemo("XYZ", 4);
    // Ausgabe: Invalid argument

    fehlerDemo("123123123123123", 16);
    // Ausgabe: Numerical result out of range
}

Okt 23, 2024

lst-0961-book.cpp

// https://godbolt.org/z/o359TThMj 
#include <iostream>
#include <string>
#include <chrono>
#include <complex>
using std::cout;
int main() {
    { using namespace std;
      cout << "string"s << "\n";           // string
      cout << (1.2+3.4i) << "\n";          // complex
      }
    { using namespace std::chrono;
      cout << (35ms).count() << "ms\n";    // chrono
      }
    { using namespace std::literals;
      cout << (41s).count() << "ms\n";     // chrono seconds
      cout << "text"s << "\n";             // string
    }
    { using namespace std::chrono; 
      cout << (4h).count() << "h\n";       // chrono hours
    }
    { using namespace std::literals::chrono_literals; 
      cout << (16min).count() << "min\n";  // chrono minutes
    }
    { using std::literals::string_literals::operator""s; 
      cout << "buchstaben"s << "\n";        // string
    }
}

Okt 23, 2024

lst-0979-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xxfbGd9Ma 
#include <random>
#include <vector>
#include <iostream>
#include <functional>
void wuerfel() {
  std::default_random_engine engine{};
  std::vector<size_t> counts{0,0,0,0,0,0};
  std::uniform_int_distribution<int> w6{0, 5}; // gleichverteilte Ganzzahlen
  auto w = std::bind(w6, engine);              // w() = w6(engine)
  for(auto i=1200*1000; i>0; --i) ++counts[w()];
  for(auto c : counts) std::cout<<" "<<c;
  std::cout << '\n';
}
int main() {
    wuerfel();
}

Okt 23, 2024

lst-0972-book.cpp

// https://godbolt.org/z/cjh93oPcr 
#include <iostream>
#include <system_error> // std::make_error_condition, std::ios_errc
int main () {
  // umschalten auf Exceptions:
  std::cin.exceptions (std::ios::failbit|std::ios::badbit);
  try {
    std::cin.rdbuf(nullptr);       // löst eine Exception aus
  } catch (std::ios::failure& e) { // abgeleitet von system_error
    std::cerr << "Fehler: ";
    if (e.code() == std::make_error_condition(std::io_errc::stream)) {
      std::cerr << "stream\n";
    } else {
      std::cerr << "andere\n";
    }
  }
}

Okt 23, 2024

lst-0996-book.cpp

// https://godbolt.org/z/1jhrx1MMn 
#include <iostream>
#include <thread>
#include <vector>
#include <exception>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }

void hauptprogramm() {
    try {
        std::thread th{ &aufgabe1 };
        std::vector data{ 0,1,2 };
        data.at(666);                     //             (ERR)  löst out_of_range aus
        th.join();                        // würde warten
    } catch(std::runtime_error &ex) {           //             (ERR)  passt nicht auf out_of_range
         /*...*/
    }
}

int main() {
  try {
    hauptprogramm();
  } catch( ... ) {                               // so weit, so gut, sieht sicher aus
    std::cout << "Ein Fehler ist aufgetreten\n"; // bekommen Sie nicht zu Gesicht
  }
}

Okt 23, 2024

lst-0988-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r5PqK8M8o 
#include <charconv>
#include <vector>
#include <iostream>
#include <string>

std::vector<size_t> num_to_vec(const std::string& nums) {
    std::vector<size_t> result {};
    // ohne Leerzeichen am Ende
    const auto end = nums.data() + nums.find_last_not_of( ' ' ) + 1;
    const char* st = nullptr; // Zählpointer in der Schleife
    auto last = nums.data();  // letztes nicht übersetztes Zeichen
    size_t n;                 // konvertierte Zahl
    do {
        for(st = last; (st<end)&&(*st==' ' ); ++st); // überspringe ' '
        if (last = std::from_chars(st, end, n).ptr; last != st)
            result.push_back(n);                     // speichere Zahl
    } while (last != st);
    return result;
}

void fehlerDemo(const char* buf, size_t sz) {
    int n;
    auto [p, ec] = std::from_chars(buf, buf+sz, n);
    if (ec != std::errc{}) {
       const auto error = std::make_error_code(ec);
       std::cout << error.message() << '\n';
    }
}

int main() {
    auto result = num_to_vec("12 33 43");

    for(auto r : result) std::cout << r << " ";
    std::cout << '\n';
    // Ausgabe: 12 33 43

    fehlerDemo("XYZ", 4);
    // Ausgabe: Invalid argument

    fehlerDemo("123123123123123", 16);
    // Ausgabe: Numerical result out of range
}

Okt 23, 2024

lst-0990-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dcqenEd31 
#include <iostream>
#include <charconv>
#include <string_view>
#include <array>
int main() {
    std::array<char, 10> str {};
    if(auto [p, ec] = std::to_chars(str.data(), str.data() + str.size(), 42);
       ec == std::errc{} )
        std::cout << std::string_view(str.data(), p - str.data()) << "\n";
}

Okt 23, 2024

lst-0985-book.cpp

// https://godbolt.org/z/1eco9Wcr3 
#include <any>
#include <iostream>
#include <vector>
#include <string>
int main() {
    std::any a = 5;
    std::cout << std::any_cast<int>(a) << '\n';
    a = 3.456;
    std::cout << std::any_cast<double>(a) << '\n';
    using namespace std::literals;
    std::vector<std::any> data { 4, 8.976, "Geronimo"s };
    std::cout << std::any_cast<double>( data[1] ) << '\n';
    std::cout << data[1].type().name()  << '\n';
}

Okt 23, 2024

lst-0974-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n54566cqT 
#include <iostream>
#include <typeinfo>
#include <string>
#include <map>
#include <boost/core/typeinfo.hpp>
int main() {
  using std::string; using std::cout;
  std::map<int, string> namen;
  int ganz;
  double fliessend;
  // demangled_name
  using boost::core::demangled_name;
  cout<<demangled_name(BOOST_CORE_TYPEID(ganz))<<'\n';      // Ausgabe: int
  cout<<demangled_name(BOOST_CORE_TYPEID(fliessend))<<'\n'; // Ausgabe: double
  cout<<demangled_name(BOOST_CORE_TYPEID(string))<<'\n';  // Ausgabe: std::string
  cout<<demangled_name(BOOST_CORE_TYPEID(string{}.begin()))<<'\n';
  // Ausgabe: __gnu_cxx::__normal_iterator<char*, std::string>
  cout<<demangled_name(BOOST_CORE_TYPEID(namen))<<'\n';
  // Ausgabe: std::map<int, std::string, std::less<int>,
  //                                                         std::allocator<std::pair<int const, std::string> > >
  cout<<demangled_name(BOOST_CORE_TYPEID(666/0))<<'\n';  // Ausgabe: int
}

Okt 23, 2024

lst-0969-book.cpp

// https://godbolt.org/z/vxTxT4ajW 
#include <system_error>
#include <iostream>
using std::error_code; using std::system_category;
namespace mylib {
    // eigene Errorcodes
    enum class errc { LOAD_ERR = 1, UNLOAD_ERR = 2, OTHER_ERR = 3 };
    error_code make_error_code(errc ec) {
        switch(ec) {
        case errc::LOAD_ERR: return error_code((int)ec, system_category());
        case errc::UNLOAD_ERR: return error_code((int)ec, system_category());
        case errc::OTHER_ERR: return error_code((int)ec, system_category());
        }
    }
    error_code run(int arg) {
        if(arg == 667) {
            return make_error_code(errc::OTHER_ERR);
        }
        return error_code{}; // alles gut.
    }
}
int main() {
    std::error_code ec = mylib::run(667);
    if(!ec) {
        std::cout << "Klasse, klappt!\n";
    } else if (ec == mylib::make_error_code(mylib::errc::OTHER_ERR)) {
        std::cout << "Anderer Fehler\n";
    } else {
        std::cout << "Nix los hier\n" << ec;
    }
}

Okt 23, 2024

Okt 23, 2024

lst-0983-book.cpp

// https://godbolt.org/z/P8d494P6c 
#include <variant> 
using std::get;
int main() {
    std::variant<int, float> v{};
    v = 12;                  // Zustand wechselt auf int
    auto i = get<int>(v);    // holt den int
    std::cout << i << '\n';  // Ausgabe: 12
    v = 3.456f;              // Zustand wechselt auf float
    std::cout << get<float>(v) << '\n';  // Ausgabe: 3.456
    get<double>(v);          //             (ERR)  Fehler
    get<3>(v);               //             (ERR)  Fehler
    std::variant<int, float> w{};
    w = get<float>(v);       // Zugriff über Typ
    w = get<1>(v);           // Zugriff geht auch über Index
    w = v;                   // ganze Zuweisung geht auch
    try {
        get<int>(w);         // löst Exception aus
    } catch (std::bad_variant_access&) { /* ... */ }
}

Okt 23, 2024

lst-0914-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6ecxTsYzj 
#include <random>
#include <vector>
#include <iostream>
void wuerfel() {
  std::default_random_engine engine{};         // Zufall normaler Qualität
  std::vector<size_t> counts{0,0,0,0,0,0};
  std::uniform_int_distribution<int> w6{0, 5}; // gleichverteilte Ganzzahlen
  for(auto i=1200*1000; i>0; --i)
    ++counts[w6(engine)];
  for(auto c : counts) std::cout<<" "<<c;
  std::cout << '\n';
}
int main() {
    wuerfel();
}

Okt 23, 2024

lst-0944-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Md38b9zvf 
#include <chrono>
#include <iostream>
#include <format>
using namespace std::chrono;
int main() {
  auto ymd = last/February/2024;   // letzter Tag im Februar 2024: 29.2.2024
  std::cout << ymd << "\n";        // die Ausgabe mit << ist einfach
  std::cout << std::format("{:%Y-%m-%d}\n", ymd);  // format ist flexibler
  std::cout << std::format("{:%e. %B %y}\n", ymd); // viel flexibler!
}

Okt 23, 2024

lst-0911-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/v91WoqjPj 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
const regex muster{R"(^score\s+(\d+)\s+for\s+(\d+)\s+nights?\s+at\s+(.*))"};
void extract(const std::string &text) {
    cmatch res;
    regex_search(text.c_str(), res, muster);
    std::cout << res[1] << "," << res[2] << "," << res[3] << "\n";
}
int main() {
    extract("score 400 for 2 nights at Minas Tirith Airport");
    extract("score 84 for 1 night at Prancing Pony");
}

Okt 23, 2024

lst-0906-book.cpp

// https://godbolt.org/z/E9hcWGMW4 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_match; using std::regex_search;
int main() {
    std::cout << std::boolalpha;
    regex muster {"ello"};
    std::string text = "Hello world";
    auto b1 = regex_match (text.cbegin(), text.cend(), muster); // passt nicht
    std::cout << b1 << "\n"; // Ausgabe: false
    auto b2 = regex_search(text.cbegin(), text.cend(), muster); // gefunden
    std::cout << b2 << "\n"; // Ausgabe: true
}

Okt 23, 2024

lst-0912-book.cpp

// https://godbolt.org/z/TK6n4dG37 
const string scoreKeyword = R"(^score\s+)";
const string numberOfPoints = R"((\d+))";
const string forKeyword = R"(\s+for\s+)";
const string numberOfNights = R"((\d+))";
const string nightsAtKeyword = R"(\s+nights?\s+at\s+)";
const string hotelName = R"((.*))";
const regex muster{ scoreKeyword + numberOfPoints +
    forKeyword + numberOfNights + nightsAtKeyword + hotelName };
}

Okt 23, 2024

lst-0945-book.cpp

// https://godbolt.org/z/19vf9jfTM 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    for (int mo = 1; mo <= 12; ++mo) {
        year_month_weekday patch_tues{mo/Tuesday[2]/2024y};
        year_month_day ymd{sys_days{patch_tues}};
        std::cout << ymd.month() << " " << ymd.day() << "\n";
    }
}

Okt 23, 2024

lst-0918-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/W8WbbxY78 
#include <random>
#include <chrono>  // system_clock
#include <format>
#include <iostream>

using namespace std;
using namespace chrono;
const size_t LOOPS = 10*1000*1000;

template<typename ENGINE>
void messen(const string &title, ENGINE &engine) {
  const auto start = steady_clock::now();

  /* hart arbeiten */
  unsigned long long checksum = 0;
  size_t loops = LOOPS;
  while(loops-- > 0)
    checksum += engine();

  const auto now = steady_clock::now();
  nanoseconds dur_ns = now - start;
  cout << std::format("  {}: {:5} ns/loop  {:12} ns\n",
      title, dur_ns.count() / LOOPS, dur_ns.count());
}

int main() {
  { default_random_engine e{}; messen("      default", e ); }
  { random_device e{};         messen("       device", e ); }
  { minstd_rand0 e{};          messen(" minstd_rand0", e ); }
  { minstd_rand e{};           messen(" minstd_rand ", e ); }
  { mt19937 e{};               messen("   mt19937   ", e ); }
  { mt19937_64 e{};            messen("   mt19937_64", e ); }
  { ranlux24_base e{};         messen("ranlux24_base", e ); }
  { ranlux48_base e{};         messen("ranlux48_base", e ); }
  { ranlux24 e{};              messen("ranlux24     ", e ); }
  { ranlux48 e{};              messen("ranlux48     ", e ); }
  { knuth_b e{};               messen("      knuth_b", e ); }
  {
    using wide_t = unsigned long long ;
    independent_bits_engine<ranlux48, sizeof(wide_t)*8, wide_t> e{};
    messen("indep<ranlux>", e );
  }
  {
    using wide_t = unsigned long long;
    independent_bits_engine<
          default_random_engine,
          sizeof(wide_t)*8, wide_t>
      e {};
    messen("indep<default>", e );
  }
}

Okt 23, 2024

lst-0947-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hP7nhEW69 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
  auto fruehl = local_days{31d/March/2024} + 2h + 1min;
  try {
      auto zt = zoned_time{"Europe/Berlin", fruehl};
  } catch (const nonexistent_local_time& e) {
      std::cout << e.what() << '\n'; // Ausnahme geworfen: existiert nicht
  }
  auto herbst = local_days{27d/October/2024} + 2h + 1min;
  try {
      auto zt = zoned_time{"Europe/Berlin", herbst};
  } catch (const ambiguous_local_time& e) {
     std::cout << e.what() << '\n'; // Ausnahme geworfen: existiert doppelt
  }
  std::cout << zoned_time{"Europe/Berlin", herbst, choose::earliest} << '\n';
  // Ausgabe: 2024-10-27 02:01:00 CEST
  std::cout << zoned_time{"Europe/Berlin", herbst, choose::latest} << '\n';
  // Ausgabe: 2024-10-27 02:01:00 CET
}

Okt 23, 2024

lst-0938-book.cpp

// https://godbolt.org/z/5Wd1rKrMe 
#include <chrono>
#include <iostream>
using namespace std::chrono; using std::cout;
using seconds32 = duration<int32_t>;                // andere Repräsentation
using zehntag = duration<int,std::ratio<86400*10>>; // andere Zeiteinheit
using fseconds = duration<double>;                  // Fließkommarepräsentation
int main() {
  seconds32 s{5};
  cout << milliseconds(s).count() << "ms\n";
  zehntag z{1};
  hours h = z;                 // Umwandlung kostenlos
  cout << "1 Zehntag hat "<<h.count()<<" Stunden\n";              // …240…
  fseconds fs{23.75};
  cout << fs.count() << "s\n"; // Fließkommaausgabe
  auto printDur = [](fseconds f) { cout << f.count() << "s\n"; }; // Funktion
  printDur(45ms + 63us);       // Umwandlung in fseconds
  // Ausgabe: 0.045063s
}

Okt 23, 2024

lst-0938-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5Wd1rKrMe 
#include <chrono>
#include <iostream>
using namespace std::chrono; using std::cout;
using seconds32 = duration<int32_t>;                // andere Repräsentation
using zehntag = duration<int,std::ratio<86400*10>>; // andere Zeiteinheit
using fseconds = duration<double>;                  // Fließkommarepräsentation
int main() {
  seconds32 s{5};
  cout << milliseconds(s).count() << "ms\n";
  zehntag z{1};
  hours h = z;                 // Umwandlung kostenlos
  cout << "1 Zehntag hat "<<h.count()<<" Stunden\n";              // 240
  fseconds fs{23.75};
  cout << fs.count() << "s\n"; // Fließkommaausgabe
  auto printDur = [](fseconds f) { cout << f.count() << "s\n"; }; // Funktion
  printDur(45ms + 63us);       // Umwandlung in fseconds
  // Ausgabe: 0.045063s
}

Okt 23, 2024

lst-0913-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MszTjE3dv 
const regex muster{R"(^score)"
    R"(\s+)"
    R"((\d+))"          // Punkte
    R"(\s+)"
    R"(for)"
    R"(\s+)"
    R"((\d+))"          // Anzahl Nächte
    R"(\s+)"
    R"(night)"
    R"(s?)"             // optional: Plural
    R"(\s+)"
    R"(at)"
    R"(\s+)"
    R"((.*))"           // Hotelname
    R"()"};

Okt 23, 2024

lst-0921-book.cpp

// https://godbolt.org/z/xz64qK3e5 
#include <random>
#include <iostream>
int main() {
    std::default_random_engine e{};
    using Dstr = std::uniform_int_distribution<int>;       // gleichverteilte int
    Dstr karte{};                                          // Verteilung erzeugen
    for(int n=32; n>=1; --n)
      std::cout <<" "<< karte(e, Dstr::param_type{1,n} );  // Parameter erst hier
    std::cout << '\n';
    // Ausgabe zum Beispiel:
    // 1 5 23 14 15 6 2 17 17 22 9 11 17 1 1 10 11 1 6 1 6 8 6 9 7 4 1 4 2 3 2 1
}

Okt 23, 2024

lst-0934-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hPPrPT69h 
#include <chrono>
#include <iostream>
void sleep(std::chrono::seconds dur) {
    std::cout << dur.count() << "s\n";
    /* ... */
}
int main() {
    using namespace std::chrono;
    sleep(3);          //                     (ERR)  Fehler: keine implizite Konvertierung von int
    sleep(seconds{4}); // okay
    sleep(5s);         // okay
    seconds x{6};
    sleep(x);          // okay
    auto y = 10s;
    y += 20s;          // Inkrementieren mit Sekunden
    sleep(y);          // nun also 30s
    y = y - 6s;        // Subtraktion von Sekunden
    sleep(y);          // und nun nur noch 24s
    y /= 2;            // Division durch einen Skalar
    sleep(y);          // 12s
    sleep(y + 7);      //                     (ERR)  Fehler: seconds+int geht nicht
}

Okt 23, 2024

lst-0942-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4s69W7qd3 
auto a_date = 2024y/11/14d;
auto b_date = 2024y/11/14;
auto c_date = 14d/11/2024;
auto d_date = November/14/2024;

Okt 23, 2024

lst-0935-book.cpp

// https://godbolt.org/z/8c1r5xrs5 
#include <chrono>
#include <iostream>
using std::chrono::operator""s;  // nur Literalsuffix verfügbar machen
constexpr auto limit = 10s;
void action(std::chrono::seconds dur) {
    if(dur <= limit) {          // vergleichen
       std::cout << dur.count() << "s\n";
    } else {
       std::cout << "zu lang!\n";
    }
}
int main() {
    action(4s);   // Ausgabe: 4s
    action(20s);  // Ausgabe: zu lang!
}

Okt 23, 2024

lst-0937-book.cpp

// https://godbolt.org/z/vTx4cdqzq 
#include <chrono>
#include <iostream>
void showDuration(std::chrono::milliseconds dur) {
    std::cout << dur.count() << "ms\n";
}
int main() {
    using namespace std::chrono;
    auto x = 2s;
    auto y = 3ms;
    showDuration(x + y); // Ausgabe: 2003ms
    showDuration(x - y); // Ausgabe: 1997ms
}

Okt 23, 2024

lst-0927-book.cpp

// https://godbolt.org/z/5snr1hq9b 
#include <chrono>
void sleep(std::chrono::seconds s) { // nimmt Sekunden als Dauer
    /* ... */
}
/* ... */
int main() {
    using namespace std::chrono; // Literale verfügbar machen
    sleep(10min);   // 10 Minuten warten, also 600 Sekunden
    sleep(10ms);    //                     (ERR)  10 Millisekunden? Mit Sekunden nicht abzubilden.
}

Okt 23, 2024

lst-0908-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rErP43G89 
#include <regex>
#include <string>
#include <iostream>
using std::string;
int main() {
    string text = "Titel;Album;Interpret";
    std::regex muster{";"};
    string neu = std::regex_replace(text, muster, string{","});
    std::cout << neu << "\n"; // Ausgabe: Titel,Album,Interpret
}

Okt 23, 2024

lst-0906-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/E9hcWGMW4 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_match; using std::regex_search;
int main() {
    std::cout << std::boolalpha;
    regex muster {"ello"};
    std::string text = "Hello world";
    auto b1 = regex_match (text.cbegin(), text.cend(), muster); // passt nicht
    std::cout << b1 << "\n"; // Ausgabe: false
    auto b2 = regex_search(text.cbegin(), text.cend(), muster); // gefunden
    std::cout << b2 << "\n"; // Ausgabe: true
}

Okt 23, 2024

lst-0936-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qrs63vdz1 
#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;             // Suffixe erlauben
    seconds mySecs = 121s;                   // seconds{121}
    std::cout << mySecs.count() << "s\n";    // Ausgabe: 121s
    milliseconds myMillis = mySecs;          // automatisch umgewandelt
    std::cout << myMillis.count() << "ms\n"; // Ausgabe: 121000ms
    nanoseconds myNanos = mySecs;
    std::cout << myNanos.count() << "ns\n"; // Ausgabe: 121000000000ns
    minutes myMinutesErr = mySecs;          //                     (ERR)  Fehler: Konvertierung mit Verlust
    minutes myMinutes = duration_cast<minutes>(mySecs); // explizit geht's
    std::cout<<myMinutes.count()<<"min\n";  // Ausgabe: 2min
}

Okt 23, 2024

lst-0949-book.cpp

// https://godbolt.org/z/YsjvxTKGj 
#include <iostream>
#include <ratio>
using std::cout; using std::endl;
int main() {
  using einDrittel = std::ratio<1,3>;
  using zweiViertel = std::ratio<2,4>;
  cout << einDrittel::num << "/" << einDrittel::den << endl;   // Ausgabe: 1/3
  cout << zweiViertel::num << "/" << zweiViertel::den << endl; // Ausgabe: 1/2
  using sum = std::ratio_add<einDrittel,zweiViertel>;          // addieren
  cout << sum::num << "/" << sum::den;                         // Ausgabe: 5/6
}

Okt 23, 2024

lst-0944-book.cpp

// https://godbolt.org/z/Md38b9zvf 
#include <chrono>
#include <iostream>
#include <format>
using namespace std::chrono;
int main() {
  auto ymd = last/February/2024;   // letzter Tag im Februar 2024: 29.2.2024
  std::cout << ymd << "\n";        // die Ausgabe mit << ist einfach
  std::cout << std::format("{:%Y-%m-%d}\n", ymd);  // format ist flexibler
  std::cout << std::format("{:%e. %B %y}\n", ymd); // viel flexibler!
}

Okt 23, 2024

lst-0939-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gvz4crW75 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    year y{2021};
    std::cout << y << "\n";
    month m{October};
    auto result = m + months{3};   // 'months', nicht 'month': 3 Monate später
    std::cout << result << "\n";   // übergelaufen zu Januar
    weekday wd{Thursday};
    auto result = wd + days{4};    // 'days', nicht 'day': 4 Tage später
    std::cout << result << "\n";   // übergelaufen zu Montag
    weekday sun1{0};               // 0 ist Sonntag
    weekday sun2{7};               // 7 ist auch Sonntag
    std::cout << sun1 << "\t" << sun2 << "\n";
    weekday_indexed wdi{wd, 4};    // unbestimmter 4. Donnerstag
    std::cout << wdi << "\n";      // Ausgabe: Thu[4]  so gibt chrono 
                                   // unbestimmte Werte aus
}

Okt 23, 2024

lst-0948-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YTKK3vT7s 
#include <chrono>
#include <iostream>
#include <ranges> // views::transform, views::filter
#include <algorithm> // ranges::for_each
using namespace std; namespace c = std::chrono;
namespace v = std::views; namespace r = std::ranges;
int main() {
  auto show_name = [](const string_view name) { cout << name << ' '; };
  const auto& db = c::get_tzdb();
  auto names = db.zones
   | v::transform([](const c::time_zone& z) {return z.name();})
   | v::filter([](const string_view name) {
       return name.starts_with("Europe/Be");});
  r::for_each(names, show_name);
  cout << " <- Europe/Be*\n"; // Ausgabe: Europe/Belgrade Europe/Berlin
  r::for_each(
   db.links
   | v::filter([](const c::time_zone_link& l){
       return l.target()=="Europe/Berlin";})
   | v::transform([](const c::time_zone_link& l)->string_view {
       return l.name();})
   , show_name);
  cout << " <- Links nach Europe/Berlin\n"; // Ausgabe: Arctic/Longyearbyen 
}

Okt 23, 2024

lst-0912-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TK6n4dG37 
const string scoreKeyword = R"(^score\s+)";
const string numberOfPoints = R"((\d+))";
const string forKeyword = R"(\s+for\s+)";
const string numberOfNights = R"((\d+))";
const string nightsAtKeyword = R"(\s+nights?\s+at\s+)";
const string hotelName = R"((.*))";
const regex muster{ scoreKeyword + numberOfPoints +
    forKeyword + numberOfNights + nightsAtKeyword + hotelName };
}

Okt 23, 2024

lst-0908-book.cpp

// https://godbolt.org/z/rErP43G89 
#include <regex>
#include <string>
#include <iostream>
using std::string;
int main() {
    string text = "Titel;Album;Interpret";
    std::regex muster{";"};
    string neu = std::regex_replace(text, muster, string{","});
    std::cout << neu << "\n"; // Ausgabe: Titel,Album,Interpret
}

Okt 23, 2024

lst-0929-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h8vsjxsME 
#include <cinttypes> // int64_t
namespace std { namespace chrono {
class seconds {
    int64_t sec_;
public:
    seconds() = default;
    //  etc 
};
} }

Okt 23, 2024

lst-0913-book.cpp

// https://godbolt.org/z/MszTjE3dv 
const regex muster{R"(^score)"
    R"(\s+)"
    R"((\d+))"          // Punkte
    R"(\s+)"
    R"(for)"
    R"(\s+)"
    R"((\d+))"          // Anzahl Nächte
    R"(\s+)"
    R"(night)"
    R"(s?)"             // optional: Plural
    R"(\s+)"
    R"(at)"
    R"(\s+)"
    R"((.*))"           // Hotelname
    R"()"};

Okt 23, 2024

lst-0926-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/173nr4xxd 
sleep(10min);
sleep(std::chrono::minutes{10});
sleep(std::chrono::duration<unsigned long,std::ratio<60>>{10});

Okt 23, 2024

lst-0937-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vTx4cdqzq 
#include <chrono>
#include <iostream>
void showDuration(std::chrono::milliseconds dur) {
    std::cout << dur.count() << "ms\n";
}
int main() {
    using namespace std::chrono;
    auto x = 2s;
    auto y = 3ms;
    showDuration(x + y); // Ausgabe: 2003ms
    showDuration(x - y); // Ausgabe: 1997ms
}

Okt 23, 2024

lst-0934-book.cpp

// https://godbolt.org/z/hPPrPT69h 
#include <chrono>
#include <iostream>
void sleep(std::chrono::seconds dur) {
    std::cout << dur.count() << "s\n";
    /* ... */
}
int main() {
    using namespace std::chrono;
    sleep(3);          //                     (ERR)  Fehler: keine implizite Konvertierung von int
    sleep(seconds{4}); // okay
    sleep(5s);         // okay
    seconds x{6};
    sleep(x);          // okay
    auto y = 10s;
    y += 20s;          // Inkrementieren mit Sekunden
    sleep(y);          // nun also 30s
    y = y - 6s;        // Subtraktion von Sekunden
    sleep(y);          // und nun nur noch 24s
    y /= 2;            // Division durch einen Skalar
    sleep(y);          // 12s
    sleep(y + 7);      //                     (ERR)  Fehler: seconds+int geht nicht
}

Okt 23, 2024

lst-0949-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YsjvxTKGj 
#include <iostream>
#include <ratio>
using std::cout; using std::endl;
int main() {
  using einDrittel = std::ratio<1,3>;
  using zweiViertel = std::ratio<2,4>;
  cout << einDrittel::num << "/" << einDrittel::den << endl;   // Ausgabe: 1/3
  cout << zweiViertel::num << "/" << zweiViertel::den << endl; // Ausgabe: 1/2
  using sum = std::ratio_add<einDrittel,zweiViertel>;          // addieren
  cout << sum::num << "/" << sum::den;                         // Ausgabe: 5/6
}

Okt 23, 2024

lst-0920-book.cpp

// https://godbolt.org/z/94McsP7PG 
#include <random>
#include <iostream>
int main() {
    std::default_random_engine e{};
    std::uniform_real_distribution<double> unif{3,7}; // im halboff. Intervall [3,7)
    double u = unif(e);                          // Zufallszahl ermitteln
    std::cout << u << '\n';                      // Beispielausgabe: 3.52615
}

Okt 23, 2024

lst-0919-book.cpp

// https://godbolt.org/z/hvM8K4oY6 
#include <random>
#include <vector>
#include <iostream>
using namespace std;
int main() {
    static const size_t size = 10;
    default_random_engine e{};                // Zufallsgenerator
    vector<size_t> counts(size+1);
    binomial_distribution<int> muenzen{size}; // wirft 10 Münzen, 0- bis 10-mal Kopf
    for(auto i=120*1000; i>0; --i)
        ++counts[muenzen(e)];                 // Münzen werfen
    for(auto c : counts) cout<<" "<<c;
    cout << '\n';
    // Beispielausgabe:
    // 109 1159 5344 14043 24806 29505 24544 13973 5252 1150 115
}

Okt 23, 2024

lst-0948-book.cpp

// https://godbolt.org/z/YTKK3vT7s 
#include <chrono>
#include <iostream>
#include <ranges> // views::transform, views::filter
#include <algorithm> // ranges::for_each
using namespace std; namespace c = std::chrono;
namespace v = std::views; namespace r = std::ranges;
int main() {
  auto show_name = [](const string_view name) { cout << name << ' '; };
  const auto& db = c::get_tzdb();
  auto names = db.zones
   | v::transform([](const c::time_zone& z) {return z.name();})
   | v::filter([](const string_view name) {
       return name.starts_with("Europe/Be");});
  r::for_each(names, show_name);
  cout << " <- Europe/Be*\n"; // Ausgabe: Europe/Belgrade Europe/Berlin
  r::for_each(
   db.links
   | v::filter([](const c::time_zone_link& l){
       return l.target()=="Europe/Berlin";})
   | v::transform([](const c::time_zone_link& l)->string_view {
       return l.name();})
   , show_name);
  cout << " <- Links nach Europe/Berlin\n"; // Ausgabe: Arctic/Longyearbyen …
}

Okt 23, 2024

lst-0940-book.cpp

// https://godbolt.org/z/oaKbd9bd4 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
  year this_year{2021};
  year last_year{2020};
  year_month_day ymd{this_year, October, day{28}};
  std::cout << ymd << "\n";
  month_weekday mwd{November, Thursday[4]};  // in einem unbestimmten Jahr
  std::cout << mwd << "\n";                  // Ausgabe: Nov/Thu[4]
  month_day_last mdlast{February};      // letzter Tag eines unbestimmten Februars
  year_month_day_last leap{last_year, mdlast};         // Jahr hinzufügen
  year_month_day_last noleap{this_year, mdlast};       // Jahr hinzufügen
  std::cout << leap << "\t" << leap.day() << "\n";     // Ausgabe: 2020-02-29 29
  std::cout << noleap << "\t" << noleap.day() << "\n"; // Ausgabe: 2021-02-28 28
}

Okt 23, 2024

lst-0918-book.cpp

// https://godbolt.org/z/W8WbbxY78 
#include <random>
#include <chrono>  // system_clock
#include <format>
#include <iostream>

using namespace std;
using namespace chrono;
const size_t LOOPS = 10*1000*1000;

template<typename ENGINE>
void messen(const string &title, ENGINE &engine) {
  const auto start = steady_clock::now();

  /* hart arbeiten */
  unsigned long long checksum = 0;
  size_t loops = LOOPS;
  while(loops-- > 0)
    checksum += engine();

  const auto now = steady_clock::now();
  nanoseconds dur_ns = now - start;
  cout << std::format("  {}: {:5} ns/loop  {:12} ns\n",
      title, dur_ns.count() / LOOPS, dur_ns.count());
}

int main() {
  { default_random_engine e{}; messen("      default", e ); }
  { random_device e{};         messen("       device", e ); }
  { minstd_rand0 e{};          messen(" minstd_rand0", e ); }
  { minstd_rand e{};           messen(" minstd_rand ", e ); }
  { mt19937 e{};               messen("   mt19937   ", e ); }
  { mt19937_64 e{};            messen("   mt19937_64", e ); }
  { ranlux24_base e{};         messen("ranlux24_base", e ); }
  { ranlux48_base e{};         messen("ranlux48_base", e ); }
  { ranlux24 e{};              messen("ranlux24     ", e ); }
  { ranlux48 e{};              messen("ranlux48     ", e ); }
  { knuth_b e{};               messen("      knuth_b", e ); }
  {
    using wide_t = unsigned long long ;
    independent_bits_engine<ranlux48, sizeof(wide_t)*8, wide_t> e{};
    messen("indep<ranlux>", e );
  }
  {
    using wide_t = unsigned long long;
    independent_bits_engine<
          default_random_engine,
          sizeof(wide_t)*8, wide_t>
      e {};
    messen("indep<default>", e );
  }
}

Okt 23, 2024

lst-0919-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hvM8K4oY6 
#include <random>
#include <vector>
#include <iostream>
using namespace std;
int main() {
    static const size_t size = 10;
    default_random_engine e{};                // Zufallsgenerator
    vector<size_t> counts(size+1);
    binomial_distribution<int> muenzen{size}; // wirft 10 Münzen, 0- bis 10-mal Kopf
    for(auto i=120*1000; i>0; --i)
        ++counts[muenzen(e)];                 // Münzen werfen
    for(auto c : counts) cout<<" "<<c;
    cout << '\n';
    // Beispielausgabe:
    // 109 1159 5344 14043 24806 29505 24544 13973 5252 1150 115
}

Okt 23, 2024

lst-0920-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/94McsP7PG 
#include <random>
#include <iostream>
int main() {
    std::default_random_engine e{};
    std::uniform_real_distribution<double> unif{3,7}; // im halboff. Intervall [3,7)
    double u = unif(e);                          // Zufallszahl ermitteln
    std::cout << u << '\n';                      // Beispielausgabe: 3.52615
}

Okt 23, 2024

lst-0947-book.cpp

// https://godbolt.org/z/hP7nhEW69 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
  auto fruehl = local_days{31d/March/2024} + 2h + 1min;
  try {
      auto zt = zoned_time{"Europe/Berlin", fruehl};
  } catch (const nonexistent_local_time& e) {
      std::cout << e.what() << '\n'; // Ausnahme geworfen: existiert nicht
  }
  auto herbst = local_days{27d/October/2024} + 2h + 1min;
  try {
      auto zt = zoned_time{"Europe/Berlin", herbst};
  } catch (const ambiguous_local_time& e) {
     std::cout << e.what() << '\n'; // Ausnahme geworfen: existiert doppelt
  }
  std::cout << zoned_time{"Europe/Berlin", herbst, choose::earliest} << '\n';
  // Ausgabe: 2024-10-27 02:01:00 CEST
  std::cout << zoned_time{"Europe/Berlin", herbst, choose::latest} << '\n';
  // Ausgabe: 2024-10-27 02:01:00 CET
}

Okt 23, 2024

lst-0942-book.cpp

// https://godbolt.org/z/4s69W7qd3 
auto a_date = 2024y/11/14d;
auto b_date = 2024y/11/14;
auto c_date = 14d/11/2024;
auto d_date = November/14/2024;

Okt 23, 2024

lst-0907-book.cpp

// https://godbolt.org/z/Ed8ca4Keq 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
int main() {
    cmatch res;                              // für Detailergebnisse
    std::string text = "<h2>Ergebnis und Teile davon</h2>";
    regex muster{"<h(.)>([^<]+)"};           // Suchmuster mit Gruppen
    regex_search(text.c_str(), res, muster); // Details nach res
    std::cout << res[1] << ". "              // ()-Gruppe 1: H-Ebene
         << res[2] << std::endl;             // ()-Gruppe 2: H-Text
}

Okt 23, 2024

lst-0921-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xz64qK3e5 
#include <random>
#include <iostream>
int main() {
    std::default_random_engine e{};
    using Dstr = std::uniform_int_distribution<int>;       // gleichverteilte int
    Dstr karte{};                                          // Verteilung erzeugen
    for(int n=32; n>=1; --n)
      std::cout <<" "<< karte(e, Dstr::param_type{1,n} );  // Parameter erst hier
    std::cout << '\n';
    // Ausgabe zum Beispiel:
    // 1 5 23 14 15 6 2 17 17 22 9 11 17 1 1 10 11 1 6 1 6 8 6 9 7 4 1 4 2 3 2 1
}

Okt 23, 2024

lst-0935-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8c1r5xrs5 
#include <chrono>
#include <iostream>
using std::chrono::operator""s;  // nur Literalsuffix verfügbar machen
constexpr auto limit = 10s;
void action(std::chrono::seconds dur) {
    if(dur <= limit) {          // vergleichen
       std::cout << dur.count() << "s\n";
    } else {
       std::cout << "zu lang!\n";
    }
}
int main() {
    action(4s);   // Ausgabe: 4s
    action(20s);  // Ausgabe: zu lang!
}

Okt 23, 2024

lst-0907-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ed8ca4Keq 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
int main() {
    cmatch res;                              // für Detailergebnisse
    std::string text = "<h2>Ergebnis und Teile davon</h2>";
    regex muster{"<h(.)>([^<]+)"};           // Suchmuster mit Gruppen
    regex_search(text.c_str(), res, muster); // Details nach res
    std::cout << res[1] << ". "              // ()-Gruppe 1: H-Ebene
         << res[2] << std::endl;             // ()-Gruppe 2: H-Text
}

Okt 23, 2024

lst-0927-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5snr1hq9b 
#include <chrono>
void sleep(std::chrono::seconds s) { // nimmt Sekunden als Dauer
    /* ... */
}
/* ... */
int main() {
    using namespace std::chrono; // Literale verfügbar machen
    sleep(10min);   // 10 Minuten warten, also 600 Sekunden
    sleep(10ms);    //                     (ERR)  10 Millisekunden? Mit Sekunden nicht abzubilden.
}

Okt 23, 2024

lst-0936-book.cpp

// https://godbolt.org/z/qrs63vdz1 
#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;             // Suffixe erlauben
    seconds mySecs = 121s;                   // seconds{121}
    std::cout << mySecs.count() << "s\n";    // Ausgabe: 121s
    milliseconds myMillis = mySecs;          // automatisch umgewandelt
    std::cout << myMillis.count() << "ms\n"; // Ausgabe: 121000ms
    nanoseconds myNanos = mySecs;
    std::cout << myNanos.count() << "ns\n"; // Ausgabe: 121000000000ns
    minutes myMinutesErr = mySecs;          //                     (ERR)  Fehler: Konvertierung mit Verlust
    minutes myMinutes = duration_cast<minutes>(mySecs); // explizit geht's
    std::cout<<myMinutes.count()<<"min\n";  // Ausgabe: 2min
}

Okt 23, 2024

lst-0926-book.cpp

// https://godbolt.org/z/173nr4xxd 
sleep(10min);
sleep(std::chrono::minutes{10});
sleep(std::chrono::duration<unsigned long,std::ratio<60>>{10});

Okt 23, 2024

lst-0911-book.cpp

// https://godbolt.org/z/v91WoqjPj 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
const regex muster{R"(^score\s+(\d+)\s+for\s+(\d+)\s+nights?\s+at\s+(.*))"};
void extract(const std::string &text) {
    cmatch res;
    regex_search(text.c_str(), res, muster);
    std::cout << res[1] << "," << res[2] << "," << res[3] << "\n";
}
int main() {
    extract("score 400 for 2 nights at Minas Tirith Airport");
    extract("score 84 for 1 night at Prancing Pony");
}

Okt 23, 2024

lst-0929-book.cpp

// https://godbolt.org/z/h8vsjxsME 
#include <cinttypes> // int64_t
namespace std { namespace chrono {
class seconds {
    int64_t sec_;
public:
    seconds() = default;
    // … etc …
};
} }

Okt 23, 2024

lst-0945-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/19vf9jfTM 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    for (int mo = 1; mo <= 12; ++mo) {
        year_month_weekday patch_tues{mo/Tuesday[2]/2024y};
        year_month_day ymd{sys_days{patch_tues}};
        std::cout << ymd.month() << " " << ymd.day() << "\n";
    }
}

Okt 23, 2024

lst-0939-book.cpp

// https://godbolt.org/z/Gvz4crW75 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    year y{2021};
    std::cout << y << "\n";
    month m{October};
    auto result = m + months{3};   // 'months', nicht 'month': 3 Monate später
    std::cout << result << "\n";   // übergelaufen zu Januar
    weekday wd{Thursday};
    auto result = wd + days{4};    // 'days', nicht 'day': 4 Tage später
    std::cout << result << "\n";   // übergelaufen zu Montag
    weekday sun1{0};               // 0 ist Sonntag
    weekday sun2{7};               // 7 ist auch Sonntag
    std::cout << sun1 << "\t" << sun2 << "\n";
    weekday_indexed wdi{wd, 4};    // unbestimmter 4. Donnerstag
    std::cout << wdi << "\n";      // Ausgabe: Thu[4] — so gibt chrono 
                                   // unbestimmte Werte aus
}

Okt 23, 2024

lst-0914-book.cpp

// https://godbolt.org/z/6ecxTsYzj 
#include <random>
#include <vector>
#include <iostream>
void wuerfel() {
  std::default_random_engine engine{};         // Zufall normaler Qualität
  std::vector<size_t> counts{0,0,0,0,0,0};
  std::uniform_int_distribution<int> w6{0, 5}; // gleichverteilte Ganzzahlen
  for(auto i=1200*1000; i>0; --i)
    ++counts[w6(engine)];
  for(auto c : counts) std::cout<<" "<<c;
  std::cout << '\n';
}
int main() {
    wuerfel();
}

Okt 23, 2024

lst-0940-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oaKbd9bd4 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
  year this_year{2021};
  year last_year{2020};
  year_month_day ymd{this_year, October, day{28}};
  std::cout << ymd << "\n";
  month_weekday mwd{November, Thursday[4]};  // in einem unbestimmten Jahr
  std::cout << mwd << "\n";                  // Ausgabe: Nov/Thu[4]
  month_day_last mdlast{February};      // letzter Tag eines unbestimmten Februars
  year_month_day_last leap{last_year, mdlast};         // Jahr hinzufügen
  year_month_day_last noleap{this_year, mdlast};       // Jahr hinzufügen
  std::cout << leap << "\t" << leap.day() << "\n";     // Ausgabe: 2020-02-29 29
  std::cout << noleap << "\t" << noleap.day() << "\n"; // Ausgabe: 2021-02-28 28
}

Okt 23, 2024

lst-0898-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cx8b9seaW 
//  wie zuvor 
int main() {
  tuple ps = praeser(2015);
  cout << get<int>(ps) << '\n';    // Ausgabe: 1940
  cout << get<string>(ps) << '\n'; //                 (ERR)  nicht eindeutig
}

Okt 23, 2024

lst-0892-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1YPT3asMz 
#include <filesystem>   // std::filesystem
#include <iostream>
namespace fs = std::filesystem; using std::cout; using std::endl;
int main() {
    // Pfadkomponenten
    fs::path root {"/"};
    fs::path dir {"var/www/"};
    fs::path index {"index.html"};
    // zusammenfügen
    fs::path p = root / dir / index;     // operator/
    // ausgeben
    cout << "Name: " << p << endl;       // "/var/www/index.html"
    // zerlegen
    cout << "Vater: " << p.parent_path() << endl; // "/var/www"
    cout << "Name: " << p.filename() << endl;     // "index.html"
    cout << "Endung: " << p.extension() << endl;  // ".html"
    // Information
    cout << std::boolalpha;
    cout << "Existiert? " << fs::exists(p) << endl;
    cout << "Echte Datei? " << fs::is_regular_file(p) << endl;
}

Okt 23, 2024

lst-0877-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/43E38b6Eq 
#include <fstream>
#include <iomanip> // setw
#include <iostream>
int main() {
    std::ifstream file("data.dat");
    if( !file ) {
        std::cout << "Fehler beim Öffnen\n";
        return 1;
    }
    char ch;
    while(file.get(ch) ) {
        std::cout.put(ch);
    }
    if( file.eof() ) {
        file.clear();
    }
    file.close();
}

Okt 23, 2024

lst-0880-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qP8cT5n7c 
#include <fstream>
#include <iostream>
#include <vector>
using std::cout;
int main() {
    std::ifstream file("testfile.txt", std::ios::binary);
    if( !file ) { /* Fehler */ cout <<"ERR1\n"; return 1; }
    std::ofstream filecopy("backup.dat", std::ios::binary);
    if( !filecopy ) { /* Fehler */ return 1; }
    file.seekg(0, std::ios::end);
    auto size = file.tellg();
    cout << "Dateigroesse : " << size << " Byte\n";
    file.seekg(0, std::ios::beg); // Wichtig!
    std::vector<char> puffer(size);
    file.read(puffer.data(), size);
    if( !file ) { cout << "Fehler bei read...\n"; return 1;}
    cout << "Gelesen: " << file.gcount() << " Byte\n";
    filecopy.write( puffer.data(), size );
    if( !filecopy ) { cout << "Fehler bei write...\n"; return 1;}
}

Okt 23, 2024

lst-0904-book.cpp

// https://godbolt.org/z/Psdz9s9Gc 
#include <iostream>
#include <string>
#include <tuple>
using namespace std;
template<typename Tuple>
auto back(Tuple &&tuple) {
    using Noref = typename remove_reference<Tuple>::type; // falls Tuple&
    constexpr auto sz = tuple_size<Noref>::value;
    return get<sz-1>(forward<Tuple>(tuple));
}
int main() {
    tuple<string,int,string> enterprise = make_tuple("NCC", 1701, "D");
    cout << back(enterprise) << "\n"; // Ausgabe: D
}

Okt 23, 2024

lst-0903-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eq1dqWbe9 
#include <iostream>
#include <string>
#include <tuple>
using std::tuple; using std::cout; using std::string;
int main() {
    tuple<int,string> a { 12, "gnorf" };
    tuple b { 666 };
    tuple<double,double,string> c { 77.77, 33.33, "frong" };
    tuple<int,string,int,double,double,string> r = std::tuple_cat( a, b, c );
    cout << std::get<2>(r) << "\n"; // Ausgabe: 666
}

Okt 23, 2024

lst-0887-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/z6sYqM48e 
#include <iostream>
#include <string>
void show(double f) {
    std::cout << "os: " << f
       << "\t to_string: " << std::to_string(f) << "\n";
}
int main() {
    show(23.43);     // Ausgabe: os: 23.43    to_string: 23.430000
    show(1e-9);      // Ausgabe: os: 1e-09    to_string: 0.000000
    show(1e40);      // Ausgabe: os: 1e+40    to_string: 1000752.000000
    show(1e-40);     // Ausgabe: os: 1e-40    to_string: 0.000000
    show(123456789); // Ausgabe: os: 1.23457e+08  to_string: 123456789.000000
}

Okt 23, 2024

lst-0880-book.cpp

// https://godbolt.org/z/qP8cT5n7c 
#include <fstream>
#include <iostream>
#include <vector>
using std::cout;
int main() {
    std::ifstream file("testfile.txt", std::ios::binary);
    if( !file ) { /* Fehler */ cout <<"ERR1\n"; return 1; }
    std::ofstream filecopy("backup.dat", std::ios::binary);
    if( !filecopy ) { /* Fehler */ return 1; }
    file.seekg(0, std::ios::end);
    auto size = file.tellg();
    cout << "Dateigroesse : " << size << " Byte\n";
    file.seekg(0, std::ios::beg); // Wichtig!
    std::vector<char> puffer(size);
    file.read(puffer.data(), size);
    if( !file ) { cout << "Fehler bei read...\n"; return 1;}
    cout << "Gelesen: " << file.gcount() << " Byte\n";
    filecopy.write( puffer.data(), size );
    if( !filecopy ) { cout << "Fehler bei write...\n"; return 1;}
}

Okt 23, 2024

lst-0884-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cbGbcT178 
#include <sstream>  // ostringstream
#include <iostream>
int main() {
    std::ostringstream ostr;
    double dval = 3.1415;
    int ival = 4321;
    ostr << dval << " : " << ival;
    const std::string sval = ostr.str();
    std::cout << sval << std::endl;    // Ausgabe: 3.1415 : 4321
}

Okt 23, 2024

lst-0886-book.cpp

// https://godbolt.org/z/vs5henTrz 
#include <sstream> // stringstream
#include <iostream>
#include <stdexcept> // invalid_argument
template <class T1, class T2>
void myConvert(const T1& in, T2& out) {
    std::stringstream ss;
    ss << in;
    ss >> out;
    if( ! ss.eof() ) {
        throw std::invalid_argument("Fehler beim Konvertieren");
    }
}
int main() {
    std::string sval;
    float fval=3.1415f;
    std::string sdval("5.321");
    double dsval=0;
    std::string gehtnicht("geht nicht");
    try {
        myConvert(fval, sval);
        std::cout << sval << std::endl;  // Ausgabe: 3.1415
        myConvert(sdval, dsval);
        std::cout << dsval << std::endl; // Ausgabe: 5.321
        myConvert(gehtnicht, dsval);     // löst "Fehler beim Konvertieren" aus
    }
    catch(const std::invalid_argument& e) {
        std::cout << e.what() << std::endl;
    }
}

Okt 23, 2024

lst-0885-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1EMox3hW5 
#include <sstream>  // istringstream
#include <iostream>
int main() {
    std::istringstream istr;
    std::string sval("3.1415 : 4321");
    std::string none;
    double dval=0.0;
    int ival=0;
    istr.str(sval);                // initialisieren
    istr >> dval >> none >> ival;  // auslesen
    if( ! istr.eof() ) {
        std::cout << "Fehler beim Konvertieren\n"; return 1;
    }
    std::cout << dval << " == " << none << " == " << ival << "\n";
    // Ausgabe: 3.1415 == : == 4321
}

Okt 23, 2024

lst-0899-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YzTvoE3x6 
//  wie zuvor 
int main() {
  using std::tie; using std::ignore;
  string nachname {};
  int gebj {};
  tie(ignore, nachname, ignore, gebj) = praeser(2015);
  cout << nachname << ' ' << gebj << '\n'; // Ausgabe: Gauck 1940
}

Okt 23, 2024

lst-0899-book.cpp

// https://godbolt.org/z/YzTvoE3x6 
// … wie zuvor …
int main() {
  using std::tie; using std::ignore;
  string nachname {};
  int gebj {};
  tie(ignore, nachname, ignore, gebj) = praeser(2015);
  cout << nachname << ' ' << gebj << '\n'; // Ausgabe: Gauck 1940
}

Okt 23, 2024

lst-0893-book.cpp

// https://godbolt.org/z/M8xjcnKxq 
#include <format>
#include <chrono>
#include <string>
#include <string_view>
#include <iostream>
using namespace std; using namespace std::literals;
void pr(string_view s) { cout << s << endl; }
double pi = 3.14159265359;

int main() {
  pr(format("Hallo, {}!", "Leser"));             // einfacher C-String
  pr(format("Hallo, {}!", "Autor"s));            // einfacher String
  pr(format("Du bist {} Jahre alt.", 30));       // Ganzzahlen
  pr(format("Das macht {:.2f} Euro.", 19.9933)); // Fließkommazahl, 2 Stellen
  pr(format("Wissenschaftlich: {:e}", -44.876)); // ergibt "-4.487600e+01"
  pr(format("Binär von {} ist {:b}.", 42, 42));  // binär ohne Basis
  pr(format("Hex von {} ist {:#x}.", 73, 73));   // hexadezimal mit Basis
  pr(format("Mit Nullen aufgefüllt: {:03}", 7)); // ergibt "007"
  pr(format("|{0:<10}|{1:^10}|{2:>10}|", "li", "mi", "re"));
  // Ausrichtung und Index
  pr(format("{} {:.9}!", "Boa", "Constrictor")); // ohne Index, String abschneiden
  using namespace std::chrono;                   // schicke Zeitangaben:
  pr(format("{}, {}", 2023y/11/5, minutes{20})); // Ausgabe: 2023-11-05, 20min
}

Okt 23, 2024

lst-0886-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vs5henTrz 
#include <sstream> // stringstream
#include <iostream>
#include <stdexcept> // invalid_argument
template <class T1, class T2>
void myConvert(const T1& in, T2& out) {
    std::stringstream ss;
    ss << in;
    ss >> out;
    if( ! ss.eof() ) {
        throw std::invalid_argument("Fehler beim Konvertieren");
    }
}
int main() {
    std::string sval;
    float fval=3.1415f;
    std::string sdval("5.321");
    double dsval=0;
    std::string gehtnicht("geht nicht");
    try {
        myConvert(fval, sval);
        std::cout << sval << std::endl;  // Ausgabe: 3.1415
        myConvert(sdval, dsval);
        std::cout << dsval << std::endl; // Ausgabe: 5.321
        myConvert(gehtnicht, dsval);     // löst "Fehler beim Konvertieren" aus
    }
    catch(const std::invalid_argument& e) {
        std::cout << e.what() << std::endl;
    }
}

Okt 23, 2024

lst-0895-book.cpp

// https://godbolt.org/z/WqjK31Gn6 
// 'Elb' wie zuvor
template<> struct std::formatter<Elb> {
  std::string attribs;                 // Folge von '%n', '%g', '%e', '%v' und anderem
  constexpr auto parse(std::format_parse_context& pctx) {
    auto it = std::ranges::find(pctx.begin(), pctx.end(), '}');// suche '}'
    attribs = std::string(pctx.begin(), it);                   // alles speichern
    return it;                                                 // zeigt auf '}'
  }
  auto format(const Elb& elb, std::format_context& fctx) const {
    auto out = fctx.out();                                      // hier hinein
    for(auto n=0u; n<attribs.size()-1; ++n) {
      if(attribs[n] == '%') {             // Instruktion, ein Mitglied auszugeben
        switch(attribs[++n]) {
          case 'n': out = std::format_to(out, "{}", elb.name); break;
          case 'g': out = std::format_to(out, "{}", elb.geb); break;
          case 'e': out = std::format_to(out, "{}", elb.epoche); break;
          case 'v': out = std::format_to(out, "{}", elb.volk); break;
          case '%': out = std::format_to(out, "%"); break;      // %% wird zu %
        }
      } else {
        out = std::format_to(out, "{}", attribs[n]);           // alles andere
      }
    }
    return out;                                                // zeigt ans Ende
  }
};
int main() {
  Elb e{"Feanor", 1169, "EZ", "Nordor"};
  std::cout << std::format("{:Elb %n}", e) << std::endl;
  // Ausgabe: Elb Feanor
  std::cout << std::format("Elb {:%n, %v, geboren %g im Zeitalter %e}\n", e);
  // Ausgabe: Elb Feanor, Nordor, geboren 1169 im Zeitalter EZ
}

Okt 23, 2024

lst-0892-book.cpp

// https://godbolt.org/z/1YPT3asMz 
#include <filesystem>   // std::filesystem
#include <iostream>
namespace fs = std::filesystem; using std::cout; using std::endl;
int main() {
    // Pfadkomponenten
    fs::path root {"/"};
    fs::path dir {"var/www/"};
    fs::path index {"index.html"};
    // zusammenfügen
    fs::path p = root / dir / index;     // operator/
    // ausgeben
    cout << "Name: " << p << endl;       // "/var/www/index.html"
    // zerlegen
    cout << "Vater: " << p.parent_path() << endl; // "/var/www"
    cout << "Name: " << p.filename() << endl;     // "index.html"
    cout << "Endung: " << p.extension() << endl;  // ".html"
    // Information
    cout << std::boolalpha;
    cout << "Existiert? " << fs::exists(p) << endl;
    cout << "Echte Datei? " << fs::is_regular_file(p) << endl;
}

Okt 23, 2024

lst-0905-book.cpp

// https://godbolt.org/z/zjboebEhc 
#include <string>
#include <iostream>
#include <regex>
using std::regex; using std::sregex_iterator; using std::string;
const regex rgxMobile(R"(01[567]\d{6,10})");        // Handy 0151-0179
bool isMobilephone(const string& text) {
  return std::regex_match(text, rgxMobile);         // Passt text ganz?
}
bool containsMobilephone(const string &text) {
  return std::regex_search(text, rgxMobile);        // irgendwo in text?
}
void listMobilephones(const string &text) {
  sregex_iterator begin{ text.cbegin(), text.cend(), rgxMobile };
  sregex_iterator end;
  for(auto it = begin; it != end; ++it)
    std::cout << it->str() << " ";                  // Treffertext
} // "xyz01709999 abc 0161887766 uvw" -> "01709999 161887766"

Okt 23, 2024

lst-0896-book.cpp

// https://godbolt.org/z/4YM9d99xG 
#include <iostream>
#include <string>
#include <vector>
#include <utility> // pair
using std::pair; using std::cout; using std::cin; using std::string;
std::vector<string> monate { "Jan", "Feb", "Mar" };
std::vector temps { 8, 12, 11 };
std::pair<string, int> monatMitTemp(size_t m) {
    auto monat = monate.at(m);
    auto temperatur = temps.at(m);
    return std::make_pair(monat, temperatur);
}
int main() {
    std::pair daten = monatMitTemp(1);
    cout << "Monat : " << daten.first << std::endl; // Ausgabe: Monat : Feb
    cout << "Temperatur : " << daten.second << std::endl; 
    // Ausgabe: Temperatur : 12
}

Okt 23, 2024

lst-0902-book.cpp

// https://godbolt.org/z/vdT7TTjWK 
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>
using std::tuple; using std::tie; using std::cout; using std::string;
struct Point {
    int x,y,z;
    bool operator<(const Point &b) {
        return tie(x,y,z) < tie(b.x, b.y, b.z);
    }
};
int main() {
    Point a{ 11, 22, 33 };
    Point b{ 11, 33, 0 };
    cout << std::boolalpha << (a < b) << "\n"; // Ausgabe: true
}

Okt 23, 2024

lst-0883-book.cpp

// https://godbolt.org/z/dz75jr1rM 
#include <iostream>
#include <thread>
#include <syncstream>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long von, long schritt, long bis) {
    for (auto n=von; n<=bis; n+=schritt) {
        std::osyncstream osync{ std::cout }; // Sync auf cout, solange osync existiert
        osync << "fib("<<n<<")=" << fib(n) << '\n';
    }
}
int main() {
    std::jthread f40{ runFib, 1, 3, 40 };
    std::jthread f41{ runFib, 2, 3, 41 };
    std::jthread f42{ runFib, 3, 3, 42 };
}

Okt 23, 2024

lst-0884-book.cpp

// https://godbolt.org/z/cbGbcT178 
#include <sstream>  // ostringstream
#include <iostream>
int main() {
    std::ostringstream ostr;
    double dval = 3.1415;
    int ival = 4321;
    ostr << dval << " : " << ival;
    const std::string sval = ostr.str();
    std::cout << sval << std::endl;    // Ausgabe: 3.1415 : 4321
}

Okt 23, 2024

lst-0905-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zjboebEhc 
#include <string>
#include <iostream>
#include <regex>
using std::regex; using std::sregex_iterator; using std::string;
const regex rgxMobile(R"(01[567]\d{6,10})");        // Handy 0151-0179
bool isMobilephone(const string& text) {
  return std::regex_match(text, rgxMobile);         // Passt text ganz?
}
bool containsMobilephone(const string &text) {
  return std::regex_search(text, rgxMobile);        // irgendwo in text?
}
void listMobilephones(const string &text) {
  sregex_iterator begin{ text.cbegin(), text.cend(), rgxMobile };
  sregex_iterator end;
  for(auto it = begin; it != end; ++it)
    std::cout << it->str() << " ";                  // Treffertext
} // "xyz01709999 abc 0161887766 uvw" -> "01709999 161887766"

Okt 23, 2024

lst-0903-book.cpp

// https://godbolt.org/z/eq1dqWbe9 
#include <iostream>
#include <string>
#include <tuple>
using std::tuple; using std::cout; using std::string;
int main() {
    tuple<int,string> a { 12, "gnorf" };
    tuple b { 666 };
    tuple<double,double,string> c { 77.77, 33.33, "frong" };
    tuple<int,string,int,double,double,string> r = std::tuple_cat( a, b, c );
    cout << std::get<2>(r) << "\n"; // Ausgabe: 666
}

Okt 23, 2024

lst-0890-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/on6W73nz1 
#include <fstream>
#include <iostream>
#include <memory> // unique_ptr
int main() {
    std::fstream file("27Streams.tex");          // Datei zum Lesen öffnen
    auto bufptr = file.rdbuf();                  // std::streambuf*
    auto size = bufptr->pubseekoff(0, file.end); // std::streamsize
    bufptr->pubseekoff(0, file.beg);             // wieder an den Anfang
    auto buffer = std::unique_ptr<char[]>(new char[size]); // Speicher holen
    auto n = bufptr->sgetn(buffer.get(), size);  // übertrage Anzahl Zeichen
    std::cout << "Zeichen gelesen: " << n << "\n";
    std::cout.write(buffer.get(), size);         // char[] ausgeben
}

Okt 23, 2024

lst-0879-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7r8r31K3e 
#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ifstream file("44fstream07.cpp");
    if( !file ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::ofstream filecopy("backup.cpp");
    if( !filecopy ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::string puffer;
    while( getline(file, puffer) ) {
        filecopy << puffer << std::endl;
        cout << puffer << std::endl;
    }
    if( file.eof() ) {
        file.clear();
    }
}

Okt 23, 2024

lst-0879-book.cpp

// https://godbolt.org/z/7r8r31K3e 
#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ifstream file("44fstream07.cpp");
    if( !file ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::ofstream filecopy("backup.cpp");
    if( !filecopy ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::string puffer;
    while( getline(file, puffer) ) {
        filecopy << puffer << std::endl;
        cout << puffer << std::endl;
    }
    if( file.eof() ) {
        file.clear();
    }
}

Okt 23, 2024

lst-0898-book.cpp

// https://godbolt.org/z/cx8b9seaW 
// … wie zuvor …
int main() {
  tuple ps = praeser(2015);
  cout << get<int>(ps) << '\n';    // Ausgabe: 1940
  cout << get<string>(ps) << '\n'; //                 (ERR)  nicht eindeutig
}

Okt 23, 2024

lst-0894-book.cpp

// https://godbolt.org/z/jYsbxqzYW 
#include <format>
#include <string>
#include <vector>
#include <iostream>
struct Elb {
  std::string name;
  int geb;
  std::string epoche;
  std::string volk;
};
template<> struct std::formatter<Elb> {
  std::formatter<std::string> sub_fmt;
  constexpr auto parse(std::format_parse_context& pctx) {
    return sub_fmt.parse(pctx); // liefert iterator auf '}'
  }
  auto format(const Elb& elb, std::format_context& fctx) const {
    std::string s = std::format("{}/{} ({} {})",
        elb.name, elb.volk, elb.geb, elb.epoche);
    return sub_fmt.format(s, fctx); // formatieren delegieren
  }
};
int main() {
  std::vector<Elb> elben{
    {"Feanor", 1169, "EZ", "Nordor"},
    {"Galadriel", 1362, "EZ", "Noldor"},
    {"Legolas", 87, "DZ", "Sindar"},
    {"Elrond", 532, "EZ", "Halbelb"},
    {"Elwe", 1050, "EZ", "Sindar"},
  };
  for (const auto& e : elben) {
    std::cout << std::format("Elb: {:>20}", e) << std::endl;
  }
}

Okt 23, 2024

lst-0890-book.cpp

// https://godbolt.org/z/on6W73nz1 
#include <fstream>
#include <iostream>
#include <memory> // unique_ptr
int main() {
    std::fstream file("27Streams.tex");          // Datei zum Lesen öffnen
    auto bufptr = file.rdbuf();                  // std::streambuf*
    auto size = bufptr->pubseekoff(0, file.end); // std::streamsize
    bufptr->pubseekoff(0, file.beg);             // wieder an den Anfang
    auto buffer = std::unique_ptr<char[]>(new char[size]); // Speicher holen
    auto n = bufptr->sgetn(buffer.get(), size);  // übertrage Anzahl Zeichen
    std::cout << "Zeichen gelesen: " << n << "\n";
    std::cout.write(buffer.get(), size);         // char[] ausgeben
}

Okt 23, 2024

lst-0876-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KzsPfMbnq 
#include <fstream>
#include <iomanip> // setw
#include <iostream>
int main() {
    std::ofstream file("data.dat");
    if( !file ) {
        std::cout << "Konnte data.dat nicht öffnen\n";
        return 1;
    }
    file << std::setw(10) << std::setfill( '*' )
         << 1234 << std::endl;
}

Okt 23, 2024

lst-0900-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jrP4v76aj 
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <algorithm> // ranges::sort
using std::tuple; using std::get; using std::cout; using std::string;
int main() {
    std::vector<tuple<string,string,int>> armstrongs =
      { {"Armstrong", "Louis", 1901}  // Initialisieren per Initialisierungsliste
      , {"Armstrong", "Lance", 1971}
      , {"Armstrong", "Neil", 1930} };
    std::ranges::sort(armstrongs);  // Lance < Louis < Neil
    for(const auto& a : armstrongs) {
      cout << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "\n";
    }
}

Okt 23, 2024

lst-0895-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WqjK31Gn6 
// 'Elb' wie zuvor…
template<> struct std::formatter<Elb> {
  std::string attribs;                 // Folge von '%n', '%g', '%e', '%v' und anderem
  constexpr auto parse(std::format_parse_context& pctx) {
    auto it = std::ranges::find(pctx.begin(), pctx.end(), '}');// suche '}'
    attribs = std::string(pctx.begin(), it);                   // alles speichern
    return it;                                                 // zeigt auf '}'
  }
  auto format(const Elb& elb, std::format_context& fctx) const {
    auto out = fctx.out();                                      // hier hinein
    for(auto n=0u; n<attribs.size()-1; ++n) {
      if(attribs[n] == '%') {             // Instruktion, ein Mitglied auszugeben
        switch(attribs[++n]) {
          case 'n': out = std::format_to(out, "{}", elb.name); break;
          case 'g': out = std::format_to(out, "{}", elb.geb); break;
          case 'e': out = std::format_to(out, "{}", elb.epoche); break;
          case 'v': out = std::format_to(out, "{}", elb.volk); break;
          case '%': out = std::format_to(out, "%"); break;      // %% wird zu %
        }
      } else {
        out = std::format_to(out, "{}", attribs[n]);           // alles andere
      }
    }
    return out;                                                // zeigt ans Ende
  }
};
int main() {
  Elb e{"Feanor", 1169, "EZ", "Nordor"};
  std::cout << std::format("{:Elb %n}", e) << std::endl;
  // Ausgabe: Elb Feanor
  std::cout << std::format("Elb {:%n, %v, geboren %g im Zeitalter %e}\n", e);
  // Ausgabe: Elb Feanor, Nordor, geboren 1169 im Zeitalter EZ
}

Okt 23, 2024

lst-0901-book.cpp

// https://godbolt.org/z/9qhMo6zbb 
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>

using std::tuple; using std::get; using std::cout; using std::string;

int main() {
    std::map<tuple<int,string>,double> m { {{12,"x"},3.14} };
    cout << m[{12,"x"}] << "\n"; // Ausgabe: 3.14
    std::unordered_set<tuple<int,string>> s { {12,"x"} }; //                 (ERR)  kein std::hash
}

Okt 23, 2024

lst-0887-book.cpp

// https://godbolt.org/z/z6sYqM48e 
#include <iostream>
#include <string>
void show(double f) {
    std::cout << "os: " << f
       << "\t to_string: " << std::to_string(f) << "\n";
}
int main() {
    show(23.43);     // Ausgabe: os: 23.43    to_string: 23.430000
    show(1e-9);      // Ausgabe: os: 1e-09    to_string: 0.000000
    show(1e40);      // Ausgabe: os: 1e+40    to_string: 100…0752.000000
    show(1e-40);     // Ausgabe: os: 1e-40    to_string: 0.000000
    show(123456789); // Ausgabe: os: 1.23457e+08  to_string: 123456789.000000
}

Okt 23, 2024

lst-0894-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jYsbxqzYW 
#include <format>
#include <string>
#include <vector>
#include <iostream>
struct Elb {
  std::string name;
  int geb;
  std::string epoche;
  std::string volk;
};
template<> struct std::formatter<Elb> {
  std::formatter<std::string> sub_fmt;
  constexpr auto parse(std::format_parse_context& pctx) {
    return sub_fmt.parse(pctx); // liefert iterator auf '}'
  }
  auto format(const Elb& elb, std::format_context& fctx) const {
    std::string s = std::format("{}/{} ({} {})",
        elb.name, elb.volk, elb.geb, elb.epoche);
    return sub_fmt.format(s, fctx); // formatieren delegieren
  }
};
int main() {
  std::vector<Elb> elben{
    {"Feanor", 1169, "EZ", "Nordor"},
    {"Galadriel", 1362, "EZ", "Noldor"},
    {"Legolas", 87, "DZ", "Sindar"},
    {"Elrond", 532, "EZ", "Halbelb"},
    {"Elwe", 1050, "EZ", "Sindar"},
  };
  for (const auto& e : elben) {
    std::cout << std::format("Elb: {:>20}", e) << std::endl;
  }
}

Okt 23, 2024

lst-0877-book.cpp

// https://godbolt.org/z/43E38b6Eq 
#include <fstream>
#include <iomanip> // setw
#include <iostream>
int main() {
    std::ifstream file("data.dat");
    if( !file ) {
        std::cout << "Fehler beim Öffnen\n";
        return 1;
    }
    char ch;
    while(file.get(ch) ) {
        std::cout.put(ch);
    }
    if( file.eof() ) {
        file.clear();
    }
    file.close();
}

Okt 23, 2024

lst-0900-book.cpp

// https://godbolt.org/z/jrP4v76aj 
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <algorithm> // ranges::sort
using std::tuple; using std::get; using std::cout; using std::string;
int main() {
    std::vector<tuple<string,string,int>> armstrongs =
      { {"Armstrong", "Louis", 1901}  // Initialisieren per Initialisierungsliste
      , {"Armstrong", "Lance", 1971}
      , {"Armstrong", "Neil", 1930} };
    std::ranges::sort(armstrongs);  // Lance < Louis < Neil
    for(const auto& a : armstrongs) {
      cout << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "\n";
    }
}

Okt 23, 2024

lst-0901-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9qhMo6zbb 
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>

using std::tuple; using std::get; using std::cout; using std::string;

int main() {
    std::map<tuple<int,string>,double> m { {{12,"x"},3.14} };
    cout << m[{12,"x"}] << "\n"; // Ausgabe: 3.14
    std::unordered_set<tuple<int,string>> s { {12,"x"} }; //                 (ERR)  kein std::hash
}

Okt 23, 2024

lst-0883-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dz75jr1rM 
#include <iostream>
#include <thread>
#include <syncstream>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long von, long schritt, long bis) {
    for (auto n=von; n<=bis; n+=schritt) {
        std::osyncstream osync{ std::cout }; // Sync auf cout, solange osync existiert
        osync << "fib("<<n<<")=" << fib(n) << '\n';
    }
}
int main() {
    std::jthread f40{ runFib, 1, 3, 40 };
    std::jthread f41{ runFib, 2, 3, 41 };
    std::jthread f42{ runFib, 3, 3, 42 };
}

Okt 23, 2024

lst-0893-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M8xjcnKxq 
#include <format>
#include <chrono>
#include <string>
#include <string_view>
#include <iostream>
using namespace std; using namespace std::literals;
void pr(string_view s) { cout << s << endl; }
double pi = 3.14159265359;

int main() {
  pr(format("Hallo, {}!", "Leser"));             // einfacher C-String
  pr(format("Hallo, {}!", "Autor"s));            // einfacher String
  pr(format("Du bist {} Jahre alt.", 30));       // Ganzzahlen
  pr(format("Das macht {:.2f} Euro.", 19.9933)); // Fließkommazahl, 2 Stellen
  pr(format("Wissenschaftlich: {:e}", -44.876)); // ergibt "-4.487600e+01"
  pr(format("Binär von {} ist {:b}.", 42, 42));  // binär ohne Basis
  pr(format("Hex von {} ist {:#x}.", 73, 73));   // hexadezimal mit Basis
  pr(format("Mit Nullen aufgefüllt: {:03}", 7)); // ergibt "007"
  pr(format("|{0:<10}|{1:^10}|{2:>10}|", "li", "mi", "re"));
  // Ausrichtung und Index
  pr(format("{} {:.9}!", "Boa", "Constrictor")); // ohne Index, String abschneiden
  using namespace std::chrono;                   // schicke Zeitangaben:
  pr(format("{}, {}", 2023y/11/5, minutes{20})); // Ausgabe: 2023-11-05, 20min
}

Okt 23, 2024

lst-0885-book.cpp

// https://godbolt.org/z/1EMox3hW5 
#include <sstream>  // istringstream
#include <iostream>
int main() {
    std::istringstream istr;
    std::string sval("3.1415 : 4321");
    std::string none;
    double dval=0.0;
    int ival=0;
    istr.str(sval);                // initialisieren
    istr >> dval >> none >> ival;  // auslesen
    if( ! istr.eof() ) {
        std::cout << "Fehler beim Konvertieren\n"; return 1;
    }
    std::cout << dval << " == " << none << " == " << ival << "\n";
    // Ausgabe: 3.1415 == : == 4321
}

Okt 23, 2024

lst-0896-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4YM9d99xG 
#include <iostream>
#include <string>
#include <vector>
#include <utility> // pair
using std::pair; using std::cout; using std::cin; using std::string;
std::vector<string> monate { "Jan", "Feb", "Mar" };
std::vector temps { 8, 12, 11 };
std::pair<string, int> monatMitTemp(size_t m) {
    auto monat = monate.at(m);
    auto temperatur = temps.at(m);
    return std::make_pair(monat, temperatur);
}
int main() {
    std::pair daten = monatMitTemp(1);
    cout << "Monat : " << daten.first << std::endl; // Ausgabe: Monat : Feb
    cout << "Temperatur : " << daten.second << std::endl; 
    // Ausgabe: Temperatur : 12
}

Okt 23, 2024

lst-0902-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vdT7TTjWK 
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>
using std::tuple; using std::tie; using std::cout; using std::string;
struct Point {
    int x,y,z;
    bool operator<(const Point &b) {
        return tie(x,y,z) < tie(b.x, b.y, b.z);
    }
};
int main() {
    Point a{ 11, 22, 33 };
    Point b{ 11, 33, 0 };
    cout << std::boolalpha << (a < b) << "\n"; // Ausgabe: true
}

Okt 23, 2024

lst-0881-book.cpp

// https://godbolt.org/z/b3W48s86z 
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using std::cout; using std::string;
class DataClass {
    std::string text_;
    int data_;
public:
    DataClass(string t="", int i=0)
      : text_{t}, data_{i} {}
    std::ostream& write(std::ostream& os) const {
        os << text_ << std::ends;
        os.write(reinterpret_cast<const char*>(&data_), sizeof(data_));
        return os;
    }
    std::istream& read(std::istream& is) {
        std::getline(is, text_, '\0');
        is.read(reinterpret_cast<char*>(&data_), sizeof(data_));
        return is;
    }
    std::ostream& print(std::ostream& os) {
        return os << text_ << " : " << data_ << std::endl;
    }
};
int main() {
    std::ofstream file_w("data.dat", std::ios::binary);
    if( !file_w) { cout << "Fehler bei Öffnen\n"; return 1; }
    std::vector<DataClass> vec_dat;
    vec_dat.push_back(DataClass("Ein Text", 123));
    vec_dat.push_back(DataClass("Mehr Text", 321));
    vec_dat.emplace_back("Viel mehr Text", 333);
    for(const auto &elem : vec_dat){
        elem.write(file_w);
    }
    file_w.close();
    std::ifstream file_r("data.dat", std::ios::binary);
    if( !file_r) { cout << "Fehler bei Öffnen\n"; return 1; }
    DataClass dat_r;
    while( file_r ) {
        dat_r.read(file_r);
        if( file_r.eof()) break;
        dat_r.print(cout);
    }
}

Okt 23, 2024

lst-0904-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Psdz9s9Gc 
#include <iostream>
#include <string>
#include <tuple>
using namespace std;
template<typename Tuple>
auto back(Tuple &&tuple) {
    using Noref = typename remove_reference<Tuple>::type; // falls Tuple&
    constexpr auto sz = tuple_size<Noref>::value;
    return get<sz-1>(forward<Tuple>(tuple));
}
int main() {
    tuple<string,int,string> enterprise = make_tuple("NCC", 1701, "D");
    cout << back(enterprise) << "\n"; // Ausgabe: D
}

Okt 23, 2024

lst-0875-book.cpp

// https://godbolt.org/z/arKsG6vqc 
#include <fstream>
#include <iostream>
int main() {
    std::ofstream file01("data.db");
    if( file01.fail() ) {
        std::cout << "Konnte data.db nicht öffnen\n";
    } else {
        std::cout << "ok.\n";
    }
    file01 << "Text für die Datei\n";
    if( file01.is_open()) {
        file01.close();
    }
    file01.open("data001.db");
    // Automatisch:
    {
        std::ofstream file02("data002.db");
    } // ab hier wird file02 geschlossen
} // ab hier ist auch file01 geschlossen

Okt 23, 2024

lst-0881-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/b3W48s86z 
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using std::cout; using std::string;
class DataClass {
    std::string text_;
    int data_;
public:
    DataClass(string t="", int i=0)
      : text_{t}, data_{i} {}
    std::ostream& write(std::ostream& os) const {
        os << text_ << std::ends;
        os.write(reinterpret_cast<const char*>(&data_), sizeof(data_));
        return os;
    }
    std::istream& read(std::istream& is) {
        std::getline(is, text_, '\0');
        is.read(reinterpret_cast<char*>(&data_), sizeof(data_));
        return is;
    }
    std::ostream& print(std::ostream& os) {
        return os << text_ << " : " << data_ << std::endl;
    }
};
int main() {
    std::ofstream file_w("data.dat", std::ios::binary);
    if( !file_w) { cout << "Fehler bei Öffnen\n"; return 1; }
    std::vector<DataClass> vec_dat;
    vec_dat.push_back(DataClass("Ein Text", 123));
    vec_dat.push_back(DataClass("Mehr Text", 321));
    vec_dat.emplace_back("Viel mehr Text", 333);
    for(const auto &elem : vec_dat){
        elem.write(file_w);
    }
    file_w.close();
    std::ifstream file_r("data.dat", std::ios::binary);
    if( !file_r) { cout << "Fehler bei Öffnen\n"; return 1; }
    DataClass dat_r;
    while( file_r ) {
        dat_r.read(file_r);
        if( file_r.eof()) break;
        dat_r.print(cout);
    }
}

Okt 23, 2024

lst-0875-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/arKsG6vqc 
#include <fstream>
#include <iostream>
int main() {
    std::ofstream file01("data.db");
    if( file01.fail() ) {
        std::cout << "Konnte data.db nicht öffnen\n";
    } else {
        std::cout << "ok.\n";
    }
    file01 << "Text für die Datei\n";
    if( file01.is_open()) {
        file01.close();
    }
    file01.open("data001.db");
    // Automatisch:
    {
        std::ofstream file02("data002.db");
    } // ab hier wird file02 geschlossen
} // ab hier ist auch file01 geschlossen

Okt 23, 2024

lst-0897-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/47jb7nEG4 
#include <iostream>
#include <string>
#include <algorithm> // min, max
#include <tuple>
using std::tuple; using std::make_tuple; using std::get; using std::cout;
using std::string;
tuple<int,int,int> ordne(int a, int b, int c) {
  using std::min; using std::max;
  auto x = min(a,min(b,c));
  auto y = max(min(a,b), min(max(a,b),c));
  auto z = max(a,max(b,c));
  return make_tuple(x, y, z);
}
auto praeser(int jahr) {
  using namespace std::literals;
  if(jahr>=2017)
    return make_tuple("Frank-Walter"s, "Steinmeier"s, "SPD"s, 1956);
  if(jahr>=2012)
    return make_tuple("Joachim"s, "Gauck"s, "-"s, 1940);
  // 
}
int main() {
  tuple<int,int,int> zs = ordne(23, 42, 7);
  cout << get<0>(zs) <<' '<< get<1>(zs) <<' '<< get<2>(zs) <<'\n'; 
  // Ausgabe: 7 23 42
  auto ps = praeser(2015);
  cout << get<1>(ps) << '\n'; // Ausgabe: Gauck
}

Okt 23, 2024

lst-0897-book.cpp

// https://godbolt.org/z/47jb7nEG4 
#include <iostream>
#include <string>
#include <algorithm> // min, max
#include <tuple>
using std::tuple; using std::make_tuple; using std::get; using std::cout;
using std::string;
tuple<int,int,int> ordne(int a, int b, int c) {
  using std::min; using std::max;
  auto x = min(a,min(b,c));
  auto y = max(min(a,b), min(max(a,b),c));
  auto z = max(a,max(b,c));
  return make_tuple(x, y, z);
}
auto praeser(int jahr) {
  using namespace std::literals;
  if(jahr>=2017)
    return make_tuple("Frank-Walter"s, "Steinmeier"s, "SPD"s, 1956);
  if(jahr>=2012)
    return make_tuple("Joachim"s, "Gauck"s, "-"s, 1940);
  // …
}
int main() {
  tuple<int,int,int> zs = ordne(23, 42, 7);
  cout << get<0>(zs) <<' '<< get<1>(zs) <<' '<< get<2>(zs) <<'\n'; 
  // Ausgabe: 7 23 42
  auto ps = praeser(2015);
  cout << get<1>(ps) << '\n'; // Ausgabe: Gauck
}

Okt 23, 2024

lst-0876-book.cpp

// https://godbolt.org/z/KzsPfMbnq 
#include <fstream>
#include <iomanip> // setw
#include <iostream>
int main() {
    std::ofstream file("data.dat");
    if( !file ) {
        std::cout << "Konnte data.dat nicht öffnen\n";
        return 1;
    }
    file << std::setw(10) << std::setfill( '*' )
         << 1234 << std::endl;
}

Okt 23, 2024

lst-0850-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MMP16Mj3W 
#include <iostream>
#include <array>
#include <string>
using std::array;
template<typename T, size_t S>
auto append(const array<T, S>& data, T elem) {
    array<T, S+1> result {};
    for(auto i=0u; i < data.size(); ++i)
        result[i] = data[i];
    result[S] =elem;
    return result;
}
int main() {
    // vorher
    array pics { 3, 4, 5 };
    std::cout << pics[0] << '\n'; // Ausgabe: 3
    // vergrößern
    auto mehr = append(pics, 77);
    // nachher
    std::cout << mehr[3] << '\n'; // Ausgabe: 77
}

Okt 23, 2024

lst-0844-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8d8qPWPcG 
#include <vector>
#include <iostream>
#include <algorithm>
using std::vector; using std::ostream; using std::cout;
int main() {
    vector<int> data{};
    data.reserve(400);                    // Platz für 400 Elemente
    // Phase 1: befüllen
    for(int idx = 1; idx <= 20; ++idx) {
        for(int val = 0; val < 20; ++val) {
            data.push_back(val % idx);    // irgendwas zwischen 0 und 19
        }
    }
    cout << data.size() << '\n';          // 400 Elemente zwischen 0 und 19
    // Nachbereitung Phase 1: set-Äquivalent erstellen
    std::sort(data.begin(), data.end());  // Vorbereitung für unique
    auto wo = std::unique(data.begin(), data.end()); // doppelte ans Ende
    data.erase(wo, data.end());           // doppelte wegräumen
    data.shrink_to_fit();
    cout << data.size() << '\n';          // nur noch 20 Elemente
    // Phase 2: benutzen
    for(auto &e:data)
        cout << e << ' ';                 // Ausgabe: 0 1 2 .. 18 19
    cout << '\n';
    auto it = std::lower_bound(data.begin(), data.end(), 16); // suche Wert
    if(it!=data.end() && *it == 16)
        cout << "gefunden!\n";
    if(std::binary_search(data.begin(), data.end(), 7))       // ja oder nein
        cout << "auch gefunden!\n";
}

Okt 23, 2024

lst-0865-book.cpp

// https://godbolt.org/z/TY9df9sb6 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw
using std::cout; using std::cin; using std::endl;
std::ostream& tabl(std::ostream& os) {
    os << '\t';
    return os;
}
std::istream& firstNum(std::istream& is) {
    char ch;
    is.get(ch);
    if( (ch >= '0') && (ch <= '9') ) {
        std::cin.putback(ch);
    }
    return is;
}
int main() {
    int val=0;
    cout << "Text1" << tabl << "Text2" << endl; // Ausgabe: Text1 (tab) Text2
    cout << "Eingabe machen: ";
    cin >> firstNum >> val;
    cout << val << std::endl; // Ausgabe: 12345
}

Okt 23, 2024

lst-0868-book.cpp

// https://godbolt.org/z/KKE6nWT49 
#include <iostream>
using std::cout; using std::endl;
class dendl { // Punkte gefolgt von Newline
    int dendl_;
public:
    dendl(int n=1)
      : dendl_{n} {}
    std::ostream& operator()(std::ostream& os) const { // Funktor
        for(int i=0; i<dendl_; ++i) os << '.';
        return os << '\n';
    }
};
std::ostream& operator<<( std::ostream& os, const dendl& elem) {
    return elem(os);
}
int main() {
    cout << "Text1" << dendl(4); // Ausgabe: Text1....
    cout << "Text2" << dendl(2); // Ausgabe: Text2..
    cout << "Text3" << dendl();  // Ausgabe: Text3.
}

Okt 23, 2024

lst-0863-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TMdzrjvhd 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw
using std::cout; using std::endl;
int main() {
    int val = -1000;
    cout << std::setw(10) << std::internal
         << val << endl;
    cout << std::setw(10) << std::left << val << endl;
    cout << std::setw(10) << std::right
         << val << endl;
}

Okt 23, 2024

lst-0856-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rP6vMM1Gr 
#include <iostream>
using std::cout; using std::cin; using std::endl;
int main() {
    const unsigned int MAX = 10;
    char buffer[MAX] = {0};
    cout << "Eingabe getline : ";
    cin.getline(buffer, MAX);
    cout << std::cin.gcount()
        << " Zeichen wurden eingelesen\n";
    for(auto c : buffer) {
        if(c && c!='\0') cout.put(c);
    }
    cin.ignore(MAX, '\n');
    cout << "\nEingabe machen (mit . beenden) : ";
    char ch=0;
    while(cin.get(ch)) {
        if(ch == '.') break;
        cout.put(ch);
    }
    cout << "Eingabe beendet" << endl;
}

Okt 23, 2024

lst-0874-book.cpp

// https://godbolt.org/z/3ocr4v745 
#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ofstream file01("testfile.txt", std::ios::out|std::ios::app);
    if(file01.fail()) {
        cout << "Konnte testfile.txt nicht öffnen\n";
    } else {
        cout << "ok.\n";
    }
    std::fstream file02;
    file02.open("database.db", std::ios::out|std::ios::trunc);
    if( !file02 ) {
        cout << "Konnte database.db nicht öffnen\n";
    } else {
        cout << "ok.\n";
    }
}

Okt 23, 2024

lst-0839-book.cpp

// https://godbolt.org/z/dKPbjj1f8 
#include <iostream>
#include <memory>    // uninitialized_copy
#include <alloca.h>  // alloca (Linux)
#include <list>
int main () {
  const std::list input{1,9,2,6,6,6,8};
  const auto SZ = input.size();
  // uninitialisierter Speicherbereich:
  int* ziel = (int*)alloca(sizeof(int) * SZ); // Platz für 7 ints
  std::uninitialized_copy(input.begin(), input.end(), ziel);
  // Testausgabe
  for(int idx=0; idx<SZ; ++idx) {
    std::cout << ziel[idx] << ' ';
  }
  std::cout << '\n'; // Ausgabe: 1 9 2 6 6 6 8
}

Okt 23, 2024

lst-0872-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4MY1Yznv9 
#include <iostream>
using std::cout; using std::endl;
int main() {
    int val = 255;
    std::ios::fmtflags ff = std::cout.flags();
    cout.flags(std::ios::hex | std::ios::showbase);
    cout << val << endl;  // Ausgabe: 0xff
    cout.flags(ff);
    cout << val << endl;  // Ausgabe: 255
}

Okt 23, 2024

lst-0841-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n8ErWj7j6 
template<typename It, typename Func>
void adjacent_pair(It begin, It end, Func func) {
    if(begin != end) {
        It prev = begin;    // erstes Argument
        ++begin;            // zweites Argument
        for(; begin != end; ++begin, ++prev) {
            func(*prev, *begin);
        }
    }
}

Okt 23, 2024

lst-0859-book.cpp

// https://godbolt.org/z/Mr6E3Ez48 
#include <iostream>
int main() {
    unsigned int val;
    std::cout << "Wert eingeben: ";
    std::cin >> val;
    if( std::cin ) { // operator bool()
        /* ... */                                   // Eingabe korrekt
    } else {
        std::cout << "Fehler bei std::cin\n";   // Fehler bei der Eingabe
    }
}

Okt 23, 2024

lst-0872-book.cpp

// https://godbolt.org/z/4MY1Yznv9 
#include <iostream>
using std::cout; using std::endl;
int main() {
    int val = 255;
    std::ios::fmtflags ff = std::cout.flags();
    cout.flags(std::ios::hex | std::ios::showbase);
    cout << val << endl;  // Ausgabe: 0xff
    cout.flags(ff);
    cout << val << endl;  // Ausgabe: 255
}

Okt 23, 2024

lst-0843-book.cpp

// https://godbolt.org/z/dfoorEdYT 
#include <ranges>
#include <iostream>
#include <string_view>
#include <vector>
using namespace std::literals;
using namespace std; namespace vs = std::views; namespace rs = std::ranges;

// Beispiel 1
class Add_1: public rs::range_adaptor_closure<Add_1> { 
  // von Hilfsklasse ableiten
public:
  template<rs::input_range R>
  constexpr auto operator()(R&& r) const {         // universelle Referenz
    return forward<R>(r)                           // universelle Referenz erhalten
      | vs::transform([](auto i) {return i+1;});   // Ihre Implementierung
  }
};
Add_1 add_1{};                                     // Range-Adapter erzeugen

// Beispiel 2
class Dna_to_rna: public rs::range_adaptor_closure<Dna_to_rna> { // ableiten
public:
  template<rs::input_range R>
  constexpr auto operator()(R&& r) const {         // universelle Referenz
    return forward<R>(r)                           // universelle Referenz erhalten
      | vs::transform([](char c)                   // Ihre Implementierung
      {
        switch(c) {
          case 'T': return 'U';
          case 't': return 'u';
          default: return c;
        }
    });
  }
};
Dna_to_rna dna_to_rna{};                           // Range-Adapter erzeugen
// Beispiele benutzen
int main() {
  vector vec{1, 2, 3, 4, 5};
  for(auto i: vec | add_1)                         // benutzen
    cout << i << ' ';
  cout << '\n';         // Ausgabe: 2 3 4 5 6
  auto telo_rep = "TTAGGGTTAGGGTTAGGGTTAGGGT"sv;
  for(auto c: telo_rep | dna_to_rna)  // benutzen
        cout << c;
  cout << '\n';         // Ausgabe: UUAGGGUUAGGGUUAGGGUUAGGGU
}

Okt 23, 2024

lst-0843-godb.cpp

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/dfoorEdYT 
#include <ranges>
#include <iostream>
#include <string_view>
#include <vector>
using namespace std::literals;
using namespace std; namespace vs = std::views; namespace rs = std::ranges;

// Beispiel 1
class Add_1: public rs::range_adaptor_closure<Add_1> { 
  // von Hilfsklasse ableiten
public:
  template<rs::input_range R>
  constexpr auto operator()(R&& r) const {         // universelle Referenz
    return forward<R>(r)                           // universelle Referenz erhalten
      | vs::transform([](auto i) {return i+1;});   // Ihre Implementierung
  }
};
Add_1 add_1{};                                     // Range-Adapter erzeugen

// Beispiel 2
class Dna_to_rna: public rs::range_adaptor_closure<Dna_to_rna> { // ableiten
public:
  template<rs::input_range R>
  constexpr auto operator()(R&& r) const {         // universelle Referenz
    return forward<R>(r)                           // universelle Referenz erhalten
      | vs::transform([](char c)                   // Ihre Implementierung
      {
        switch(c) {
          case 'T': return 'U';
          case 't': return 'u';
          default: return c;
        }
    });
  }
};
Dna_to_rna dna_to_rna{};                           // Range-Adapter erzeugen
// Beispiele benutzen
int main() {
  vector vec{1, 2, 3, 4, 5};
  for(auto i: vec | add_1)                         // benutzen
    cout << i << ' ';
  cout << '\n';         // Ausgabe: 2 3 4 5 6
  auto telo_rep = "TTAGGGTTAGGGTTAGGGTTAGGGT"sv;
  for(auto c: telo_rep | dna_to_rna)  // benutzen
        cout << c;
  cout << '\n';         // Ausgabe: UUAGGGUUAGGGUUAGGGUUAGGGU
}

Okt 23, 2024

lst-0859-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mr6E3Ez48 
#include <iostream>
int main() {
    unsigned int val;
    std::cout << "Wert eingeben: ";
    std::cin >> val;
    if( std::cin ) { // operator bool()
        /* ... */                                   // Eingabe korrekt
    } else {
        std::cout << "Fehler bei std::cin\n";   // Fehler bei der Eingabe
    }
}

Okt 23, 2024

lst-0863-book.cpp

// https://godbolt.org/z/TMdzrjvhd 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw
using std::cout; using std::endl;
int main() {
    int val = -1000;
    cout << std::setw(10) << std::internal
         << val << endl;
    cout << std::setw(10) << std::left << val << endl;
    cout << std::setw(10) << std::right
         << val << endl;
}

Okt 23, 2024

lst-0850-book.cpp

// https://godbolt.org/z/MMP16Mj3W 
#include <iostream>
#include <array>
#include <string>
using std::array;
template<typename T, size_t S>
auto append(const array<T, S>& data, T elem) {
    array<T, S+1> result {};
    for(auto i=0u; i < data.size(); ++i)
        result[i] = data[i];
    result[S] =elem;
    return result;
}
int main() {
    // vorher
    array pics { 3, 4, 5 };
    std::cout << pics[0] << '\n'; // Ausgabe: 3
    // vergrößern
    auto mehr = append(pics, 77);
    // nachher
    std::cout << mehr[3] << '\n'; // Ausgabe: 77
}

Okt 23, 2024

lst-0874-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3ocr4v745 
#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ofstream file01("testfile.txt", std::ios::out|std::ios::app);
    if(file01.fail()) {
        cout << "Konnte testfile.txt nicht öffnen\n";
    } else {
        cout << "ok.\n";
    }
    std::fstream file02;
    file02.open("database.db", std::ios::out|std::ios::trunc);
    if( !file02 ) {
        cout << "Konnte database.db nicht öffnen\n";
    } else {
        cout << "ok.\n";
    }
}

Okt 23, 2024

lst-0851-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/scE81KfEa 
#include <iostream>
#include <vector>
#include <list>
#include <ranges>
namespace rs = std::ranges;

template<rs::range R>
void alg(R&& range) {
  if constexpr(rs::random_access_range<R>)
    std::cout << "wahlfrei.\n";
  else if constexpr(rs::bidirectional_range<R>)
    std::cout << "bidirektional, aber nicht wahlfrei\n";
  else static_assert(false, "nicht unterstützter Range-Typ");
}
int main() {
    std::vector<int> vec {};       // vector ist wahlfrei
    alg(vec);
    std::list<int> lst;            // list ist nur bidirektional
    alg(lst);
    std::istreambuf_iterator<char> i1{std::cin}, i2{}; // nicht einmal bidirektional
    auto fwd = rs::subrange{i1, i2};
    alg(fwd); //             (ERR)  Fehler: keine passende Implementierung
}

Okt 23, 2024

lst-0862-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bEKaYdssE 
#include <iostream>
#include <ios>
using std::cout; using std::endl;
void f() {
    int val = 100;
    cout << val << endl;               // Ausgabe: 0x64
}
int main() {
    int val = 255;
    cout << std::showbase;
    cout << std::dec << val << endl;   // Ausgabe: 255
    cout << std::hex << val << endl;   // Ausgabe: 0xff
    f();
    cout << std::oct << val << endl;   // Ausgabe: 0377
    cout << val << std::endl;          // Ausgabe: 0377
}

Okt 23, 2024

lst-0856-book.cpp

// https://godbolt.org/z/rP6vMM1Gr 
#include <iostream>
using std::cout; using std::cin; using std::endl;
int main() {
    const unsigned int MAX = 10;
    char buffer[MAX] = {0};
    cout << "Eingabe getline : ";
    cin.getline(buffer, MAX);
    cout << std::cin.gcount()
        << " Zeichen wurden eingelesen\n";
    for(auto c : buffer) {
        if(c && c!='\0') cout.put(c);
    }
    cin.ignore(MAX, '\n');
    cout << "\nEingabe machen (mit . beenden) : ";
    char ch=0;
    while(cin.get(ch)) {
        if(ch == '.') break;
        cout.put(ch);
    }
    cout << "Eingabe beendet" << endl;
}

Okt 23, 2024

lst-0854-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Th66Y9WvE 
#include <iostream> // cin, cout
int main() {
    int val1, val2;
    std::cout << "Bitte 2 int-Werte: ";
    std::cin >> val1 >> val2;
    std::cout << val1 << " : " << val2 << std::endl;
}

Okt 23, 2024

lst-0836-book.cpp

// https://godbolt.org/z/z4ajz5E5P 
#include <numeric>    // adjacent_difference
#include <functional> // plus
#include <algorithm>  // copy
#include <iostream>
#include <iterator>   // ostream_iterator
#include <vector>
#include <ranges>     // pairwise_transform
using std::cout; using std::vector; namespace vs = std::views;
int main() {
    // Streamausgabeiterator für int;
    std::ostream_iterator<int> os{std::cout, " "};
    vector data{ 1, -1, 2, -2, -4, 4, -6, 6 };
    std::copy(data.begin(), data.end (), os);
    cout << '\n'; // Ausgabe: 1 –1 2 –2 –4 4 –6 6
    vector<int> res( data.size()-1 ); // Platz für Ergebnis
    // Ergebnisse nach res schreiben:
    adjacent_difference(data.begin(), data.end(), res.begin());
    std::copy (res.begin(), res.end (), os);
    cout << '\n'; // Ausgabe: 1 –2 3 –4 –2 8 –10
    // gleich nach os schreiben:
    adjacent_difference(data.begin(), data.end(), os, std::plus<int>{});
    cout << '\n'; // Ausgabe: 1 0 1 0 –6 0 –2 0
    // oder via Range-Adapter:
    for(auto e: vs::pairwise_transform(data, std::plus<int>{}))
        cout << e << ' ';
    cout << '\n'; // Ausgabe: 0 1 0 –6 0 –2 0
}

Okt 23, 2024

lst-0838-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qcWsdedMz 
#include <numeric> // *_scan
#include <iostream>
#include <vector>
using std::inclusive_scan; using std::exclusive_scan;
std::ostream& operator<<=(std::ostream&os, const std::vector<int>&data) {
    for(auto &e : data) os << e << ' '; return os << '\n';
}
int main() {
  std::vector data{ 1, 3, 10, 18, 30, 50 };
  std::vector<int> result(6);    // 6 Elemente
  auto plus = [](auto a, auto b) { return a+b; };
  inclusive_scan(data.begin(),data.end(), result.begin(), plus, 100);
  std::cout <<= result;
  // Ausgabe: 101 104 114 132 162 212
  exclusive_scan(data.begin(),data.end(), result.begin(), 100);
  std::cout <<= result;
  // Ausgabe: 100 101 104 114 132 162
}

Okt 23, 2024

lst-0870-book.cpp

// https://godbolt.org/z/csbPMYM19 
#include <iostream>
#include <ios> // hex, dec
using std::cout; using std::endl;
int main() {
    int val = 255;
    cout << std::showbase << std::hex << val << endl;   // Ausgabe: 0xff
    cout << std::noshowbase << std::dec << val << endl; // Ausgabe: 255
}

Okt 23, 2024

lst-0854-book.cpp

// https://godbolt.org/z/Th66Y9WvE 
#include <iostream> // cin, cout
int main() {
    int val1, val2;
    std::cout << "Bitte 2 int-Werte: ";
    std::cin >> val1 >> val2;
    std::cout << val1 << " : " << val2 << std::endl;
}

Okt 23, 2024

lst-0846-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jT7raEfKa 
#include <iostream>
#include <array>
#include <vector>
#include <string>
using std::array; using std::move; using std::forward;

// == array vergrößern ==
template<typename T, size_t S, std::size_t... Idx>
constexpr array<T, S+1>
help_append(array<T, S>&& data, T&& elem, std::index_sequence<Idx...>) {
  return { std::get<Idx>(forward<array<T, S>>(data))..., forward<T>(elem) };
}
template<typename T, size_t S>
constexpr auto
append(array<T, S> data, T elem) {
  return help_append(move(data), move(elem),
                  std::make_index_sequence<S>{});
}

// == Beispiel ==
class Picture {            // Nullerregel; verschiebbar
  std::vector<char> data_; // viele Daten
  std::string name_;
public:
  explicit Picture(const std::string& name) : data_(1000,0), name_{name}
    { /* ... hier Bild laden ... */ }
  auto name() const { return name_; }
};
int main() {
  // vorher
  array pics{Picture{"Mona"}, Picture{"Schrei"}, Picture{"Vincent"}};
  std::cout << pics[0].name() << '\n'; // Ausgabe: Mona
  // vergrößern
  Picture neu { "Uhren" };
  auto mehr = append(move(pics), move(neu));
  // nachher
  std::cout << pics[0].name() << '\n'; // Ausgabe:
  std::cout << mehr[0].name() << '\n'; // Ausgabe: Mona
  std::cout << mehr[3].name() << '\n'; // Ausgabe: Uhren
}

Okt 23, 2024

lst-0835-book.cpp

// https://godbolt.org/z/8sEdxd5jP 
#include <numeric>    // accumulate
#include <functional> // multiplies
#include <algorithm>  // transform, fold_left
#include <iostream>
#include <vector>
using std::accumulate; using std::cout; using std::vector; using std::multiplies;
namespace rs = std::ranges;
int main() {
  vector data{ 2, 3, 5, 10, 20 };
  cout << accumulate(data.begin(),data.end(),0)<<'\n';     // +, Ausgabe: 40
  cout << rs::fold_left(data, 1, multiplies<int>{})<<'\n'; // *, 6000
  vector<bool> gerade( data.size() );
  std::transform( data.begin(), data.end(), gerade.begin(),
      [](auto n) { return n%2==0; });
  for(auto b : gerade) {
      cout << ( b ? "gerade " : "ungerade ");
  }
  cout << "\n";       // Ausgabe: gerade ungerade ungerade gerade gerade
  auto sindAlleGerade = accumulate(gerade.begin(), gerade.end(), true,
          [](auto b, auto c) { return b&&c; });
  if(sindAlleGerade) {
      cout << "alles gerade Zahlen\n";
  } else {
      cout << "ungerade Zahlen dabei\n"; // das ist die Ausgabe
  }
}

Okt 23, 2024

lst-0870-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/csbPMYM19 
#include <iostream>
#include <ios> // hex, dec
using std::cout; using std::endl;
int main() {
    int val = 255;
    cout << std::showbase << std::hex << val << endl;   // Ausgabe: 0xff
    cout << std::noshowbase << std::dec << val << endl; // Ausgabe: 255
}

Okt 23, 2024

lst-0845-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fv3963reh 
#include <iostream>  // cout
#include <algorithm> // copy
#include <iterator>  // ostream_iterator
#include <vector>
int main() {
  std::vector<char> pfad{};
  for (char ch = 'a'; ch <= 'z'; ++ch) {
    pfad.push_back(ch);
  }
  std::ranges::copy(pfad, // hier alles, geht aber auch mit anderen Ranges
    std::ostream_iterator<char>(std::cout, " ") // kopiere nach cout, Separator " "
  );
}

Okt 23, 2024

lst-0858-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rq3eGP3cv 
#include <fstream>
#include <iostream>
using std::cout; using std::cin; using std::ofstream;
void checkIOstate(std::ios& stream) {
    if( stream.good() ) {
        cout << "Alles in Ordnung\n";
    } else if( stream.bad() ) {
        cout << "Fataler Fehler\n";
    } else if( stream.fail()) {
        cout << "Fehler bei der Ein-/Ausgabe\n";
        if( stream.eof()) {
            cout << "Ende des Datenstroms erreicht\n";
        }
    }
    stream.clear();
}
int main() {
    int val=0;
    cout << "Wert eingeben: ";
    cin >> val;
    checkIOstate( cin );
    std::ifstream file;
    file.open("nichtvorhanden.text");
    checkIOstate(file);
    std::fstream fstr;
    fstr.open("neueDatei.txt",
        ofstream::out | ofstream::in
        | ofstream::binary | ofstream::trunc);
    fstr << "Text in der Datei\n";
    fstr.seekp(std::ios_base::beg);
    char ch;
    while( fstr.good()) {
        fstr.get(ch);
        if(fstr.good()) cout.put(ch);
    }
    checkIOstate(fstr);
}

Okt 23, 2024

lst-0841-book.cpp

// https://godbolt.org/z/n8ErWj7j6 
template<typename It, typename Func>
void adjacent_pair(It begin, It end, Func func) {
    if(begin != end) {
        It prev = begin;    // erstes Argument
        ++begin;            // zweites Argument
        for(; begin != end; ++begin, ++prev) {
            func(*prev, *begin);
        }
    }
}

Okt 23, 2024

lst-0837-book.cpp

// https://godbolt.org/z/aPoe3d873 
#include <numeric>   // accumulate, iota
#include <algorithm> // copy
#include <iostream>
#include <iterator>  // ostream_iterator
#include <vector>
#include <ranges>    // iota, take, stride
using std::accumulate; using std::cout; using std::vector; 
namespace vs = std::views;
struct Generator {
    int state_;
    void operator++() { state_ += state_; }
    operator int() { return state_; }
};
int main() {
    std::ostream_iterator<int> os{std::cout, " "}; // Streamausgabeiterator für int
    vector<int> data(7);
    std::iota(data.begin(), data.end(), 10);
    std::copy(data.begin(), data.end (), os);
    cout << '\n';          // Ausgabe: 10 11 12 13 14 15 16
    vector<int> seq(7);
    std::iota(seq.begin(), seq.end(), Generator{2});
    std::copy(seq.begin(), seq.end(), os);
    cout << '\n';          // Ausgabe: 2 4 8 16 32 64 128
    for(auto i: vs::iota(0) | vs::stride(3) | vs::take(6))
        cout << i << ' ';
    cout << '\n';          // Ausgabe: 0 3 6 9 12 15
}

Okt 23, 2024

lst-0860-book.cpp

// https://godbolt.org/z/s1csa51z9 
#include <iostream>
#include <iomanip>
using std::cin; using std::cout; using std::endl;

void f(bool b) {
     cout << b << endl;                    // Ausgabe:  true
}

int main () {
    bool b=true;
    cout << std::boolalpha << b << endl;   // Ausgabe: true
    b=false;
    cout << b << endl;                     // Ausgabe: false
    f(true);
    cout << std::noboolalpha << b << endl; // Ausgabe: 0
    b=true;
    cout << b << endl;                     // Ausgabe: 1
}

Okt 23, 2024

lst-0862-book.cpp

// https://godbolt.org/z/bEKaYdssE 
#include <iostream>
#include <ios>
using std::cout; using std::endl;
void f() {
    int val = 100;
    cout << val << endl;               // Ausgabe: 0x64
}
int main() {
    int val = 255;
    cout << std::showbase;
    cout << std::dec << val << endl;   // Ausgabe: 255
    cout << std::hex << val << endl;   // Ausgabe: 0xff
    f();
    cout << std::oct << val << endl;   // Ausgabe: 0377
    cout << val << std::endl;          // Ausgabe: 0377
}

Okt 23, 2024

lst-0844-book.cpp

// https://godbolt.org/z/8d8qPWPcG 
#include <vector>
#include <iostream>
#include <algorithm>
using std::vector; using std::ostream; using std::cout;
int main() {
    vector<int> data{};
    data.reserve(400);                    // Platz für 400 Elemente
    // Phase 1: befüllen
    for(int idx = 1; idx <= 20; ++idx) {
        for(int val = 0; val < 20; ++val) {
            data.push_back(val % idx);    // irgendwas zwischen 0 und 19
        }
    }
    cout << data.size() << '\n';          // 400 Elemente zwischen 0 und 19
    // Nachbereitung Phase 1: set-Äquivalent erstellen
    std::sort(data.begin(), data.end());  // Vorbereitung für unique
    auto wo = std::unique(data.begin(), data.end()); // doppelte ans Ende
    data.erase(wo, data.end());           // doppelte wegräumen
    data.shrink_to_fit();
    cout << data.size() << '\n';          // nur noch 20 Elemente
    // Phase 2: benutzen
    for(auto &e:data)
        cout << e << ' ';                 // Ausgabe: 0 1 2 .. 18 19
    cout << '\n';
    auto it = std::lower_bound(data.begin(), data.end(), 16); // suche Wert
    if(it!=data.end() && *it == 16)
        cout << "gefunden!\n";
    if(std::binary_search(data.begin(), data.end(), 7))       // ja oder nein
        cout << "auch gefunden!\n";
}

Okt 23, 2024

lst-0838-book.cpp

// https://godbolt.org/z/qcWsdedMz 
#include <numeric> // *_scan
#include <iostream>
#include <vector>
using std::inclusive_scan; using std::exclusive_scan;
std::ostream& operator<<=(std::ostream&os, const std::vector<int>&data) {
    for(auto &e : data) os << e << ' '; return os << '\n';
}
int main() {
  std::vector data{ 1, 3, 10, 18, 30, 50 };
  std::vector<int> result(6);    // 6 Elemente
  auto plus = [](auto a, auto b) { return a+b; };
  inclusive_scan(data.begin(),data.end(), result.begin(), plus, 100);
  std::cout <<= result;
  // Ausgabe: 101 104 114 132 162 212
  exclusive_scan(data.begin(),data.end(), result.begin(), 100);
  std::cout <<= result;
  // Ausgabe: 100 101 104 114 132 162
}

Okt 23, 2024

lst-0837-godb.cpp

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/aPoe3d873 
#include <numeric>   // accumulate, iota
#include <algorithm> // copy
#include <iostream>
#include <iterator>  // ostream_iterator
#include <vector>
#include <ranges>    // iota, take, stride
using std::accumulate; using std::cout; using std::vector; 
namespace vs = std::views;
struct Generator {
    int state_;
    void operator++() { state_ += state_; }
    operator int() { return state_; }
};
int main() {
    std::ostream_iterator<int> os{std::cout, " "}; // Streamausgabeiterator für int
    vector<int> data(7);
    std::iota(data.begin(), data.end(), 10);
    std::copy(data.begin(), data.end (), os);
    cout << '\n';          // Ausgabe: 10 11 12 13 14 15 16
    vector<int> seq(7);
    std::iota(seq.begin(), seq.end(), Generator{2});
    std::copy(seq.begin(), seq.end(), os);
    cout << '\n';          // Ausgabe: 2 4 8 16 32 64 128
    for(auto i: vs::iota(0) | vs::stride(3) | vs::take(6))
        cout << i << ' ';
    cout << '\n';          // Ausgabe: 0 3 6 9 12 15
}

Okt 23, 2024

lst-0868-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KKE6nWT49 
#include <iostream>
using std::cout; using std::endl;
class dendl { // Punkte gefolgt von Newline
    int dendl_;
public:
    dendl(int n=1)
      : dendl_{n} {}
    std::ostream& operator()(std::ostream& os) const { // Funktor
        for(int i=0; i<dendl_; ++i) os << '.';
        return os << '\n';
    }
};
std::ostream& operator<<( std::ostream& os, const dendl& elem) {
    return elem(os);
}
int main() {
    cout << "Text1" << dendl(4); // Ausgabe: Text1....
    cout << "Text2" << dendl(2); // Ausgabe: Text2..
    cout << "Text3" << dendl();  // Ausgabe: Text3.
}

Okt 23, 2024

lst-0865-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TY9df9sb6 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw
using std::cout; using std::cin; using std::endl;
std::ostream& tabl(std::ostream& os) {
    os << '\t';
    return os;
}
std::istream& firstNum(std::istream& is) {
    char ch;
    is.get(ch);
    if( (ch >= '0') && (ch <= '9') ) {
        std::cin.putback(ch);
    }
    return is;
}
int main() {
    int val=0;
    cout << "Text1" << tabl << "Text2" << endl; // Ausgabe: Text1 (tab) Text2
    cout << "Eingabe machen: ";
    cin >> firstNum >> val;
    cout << val << std::endl; // Ausgabe: 12345
}

Okt 23, 2024

lst-0846-book.cpp

// https://godbolt.org/z/jT7raEfKa 
#include <iostream>
#include <array>
#include <vector>
#include <string>
using std::array; using std::move; using std::forward;

// == array vergrößern ==
template<typename T, size_t S, std::size_t... Idx>
constexpr array<T, S+1>
help_append(array<T, S>&& data, T&& elem, std::index_sequence<Idx...>) {
  return { std::get<Idx>(forward<array<T, S>>(data))..., forward<T>(elem) };
}
template<typename T, size_t S>
constexpr auto
append(array<T, S> data, T elem) {
  return help_append(move(data), move(elem),
                  std::make_index_sequence<S>{});
}

// == Beispiel ==
class Picture {            // Nullerregel; verschiebbar
  std::vector<char> data_; // viele Daten
  std::string name_;
public:
  explicit Picture(const std::string& name) : data_(1000,0), name_{name}
    { /* ... hier Bild laden ... */ }
  auto name() const { return name_; }
};
int main() {
  // vorher
  array pics{Picture{"Mona"}, Picture{"Schrei"}, Picture{"Vincent"}};
  std::cout << pics[0].name() << '\n'; // Ausgabe: Mona
  // vergrößern
  Picture neu { "Uhren" };
  auto mehr = append(move(pics), move(neu));
  // nachher
  std::cout << pics[0].name() << '\n'; // Ausgabe:
  std::cout << mehr[0].name() << '\n'; // Ausgabe: Mona
  std::cout << mehr[3].name() << '\n'; // Ausgabe: Uhren
}

Okt 23, 2024

lst-0864-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sYK8oT33x 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw

using std::cout; using std::endl;
int main() {
    double dval = 3.14159;
    std::ios_base::fmtflags ff(std::ios::scientific|std::ios::uppercase);
    cout << std::setiosflags(ff);
    cout << dval << endl;                           // Ausgabe: 3.141590E+00
    cout << std::resetiosflags(ff) << dval << endl; // Ausgabe: 3.14159
    cout << std::setprecision(3) << dval << endl;   // Ausgabe: 3.14
    cout << std::setw(10);
    cout << std::setfill( '*' ) << 1246 << endl;    // Ausgabe: ******1246
}

Okt 23, 2024

lst-0845-book.cpp

// https://godbolt.org/z/fv3963reh 
#include <iostream>  // cout
#include <algorithm> // copy
#include <iterator>  // ostream_iterator
#include <vector>
int main() {
  std::vector<char> pfad{};
  for (char ch = 'a'; ch <= 'z'; ++ch) {
    pfad.push_back(ch);
  }
  std::ranges::copy(pfad, // hier alles, geht aber auch mit anderen Ranges
    std::ostream_iterator<char>(std::cout, " ") // kopiere nach cout, Separator " "
  );
}

Okt 23, 2024

lst-0835-godb.cpp

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/8sEdxd5jP 
#include <numeric>    // accumulate
#include <functional> // multiplies
#include <algorithm>  // transform, fold_left
#include <iostream>
#include <vector>
using std::accumulate; using std::cout; using std::vector; using std::multiplies;
namespace rs = std::ranges;
int main() {
  vector data{ 2, 3, 5, 10, 20 };
  cout << accumulate(data.begin(),data.end(),0)<<'\n';     // +, Ausgabe: 40
  cout << rs::fold_left(data, 1, multiplies<int>{})<<'\n'; // *, 6000
  vector<bool> gerade( data.size() );
  std::transform( data.begin(), data.end(), gerade.begin(),
      [](auto n) { return n%2==0; });
  for(auto b : gerade) {
      cout << ( b ? "gerade " : "ungerade ");
  }
  cout << "\n";       // Ausgabe: gerade ungerade ungerade gerade gerade
  auto sindAlleGerade = accumulate(gerade.begin(), gerade.end(), true,
          [](auto b, auto c) { return b&&c; });
  if(sindAlleGerade) {
      cout << "alles gerade Zahlen\n";
  } else {
      cout << "ungerade Zahlen dabei\n"; // das ist die Ausgabe
  }
}

Okt 23, 2024

lst-0842-book.cpp

// https://godbolt.org/z/91jj8Toqs 
#include <vector>
#include <iostream>
// … adjacent_pair von oben hier …
int main() {
    std::vector v{1,2,3,4};
    auto f = [](auto a, auto b) { std::cout << (a+b) << ' '; };
    adjacent_pair(v.begin(), v.end(), f); // 3 5 7
    std::cout << '\n';

    std::vector x{4,8};
    adjacent_pair(x.begin(), x.end(), f); // 12
    std::cout << '\n';

    std::vector w{4};
    adjacent_pair(w.begin(), w.end(), f); // nichts
    std::cout << '\n';

    std::vector<int> y{};
    adjacent_pair(y.begin(), y.end(), f); // nichts
    std::cout << '\n';
}

Okt 23, 2024

lst-0839-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dKPbjj1f8 
#include <iostream>
#include <memory>    // uninitialized_copy
#include <alloca.h>  // alloca (Linux)
#include <list>
int main () {
  const std::list input{1,9,2,6,6,6,8};
  const auto SZ = input.size();
  // uninitialisierter Speicherbereich:
  int* ziel = (int*)alloca(sizeof(int) * SZ); // Platz für 7 ints
  std::uninitialized_copy(input.begin(), input.end(), ziel);
  // Testausgabe
  for(int idx=0; idx<SZ; ++idx) {
    std::cout << ziel[idx] << ' ';
  }
  std::cout << '\n'; // Ausgabe: 1 9 2 6 6 6 8
}

Okt 23, 2024

lst-0860-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s1csa51z9 
#include <iostream>
#include <iomanip>
using std::cin; using std::cout; using std::endl;

void f(bool b) {
     cout << b << endl;                    // Ausgabe:  true
}

int main () {
    bool b=true;
    cout << std::boolalpha << b << endl;   // Ausgabe: true
    b=false;
    cout << b << endl;                     // Ausgabe: false
    f(true);
    cout << std::noboolalpha << b << endl; // Ausgabe: 0
    b=true;
    cout << b << endl;                     // Ausgabe: 1
}

Okt 23, 2024

lst-0851-book.cpp

// https://godbolt.org/z/scE81KfEa 
#include <iostream>
#include <vector>
#include <list>
#include <ranges>
namespace rs = std::ranges;

template<rs::range R>
void alg(R&& range) {
  if constexpr(rs::random_access_range<R>)
    std::cout << "wahlfrei.\n";
  else if constexpr(rs::bidirectional_range<R>)
    std::cout << "bidirektional, aber nicht wahlfrei\n";
  else static_assert(false, "nicht unterstützter Range-Typ");
}
int main() {
    std::vector<int> vec {};       // vector ist wahlfrei
    alg(vec);
    std::list<int> lst;            // list ist nur bidirektional
    alg(lst);
    std::istreambuf_iterator<char> i1{std::cin}, i2{}; // nicht einmal bidirektional
    auto fwd = rs::subrange{i1, i2};
    alg(fwd); //             (ERR)  Fehler: keine passende Implementierung
}

Okt 23, 2024

lst-0871-book.cpp

// https://godbolt.org/z/1xzzMdjdM 
#include <iostream>
using std::cout; using std::endl;
int main() {
    int val = 255;
    cout.setf(std::ios_base::hex, std::ios_base::basefield);
    cout.setf(std::ios_base::showbase);
    cout << val << std::endl; // Ausgabe: 0xff
    cout.unsetf(std::ios_base::showbase);
    cout.setf(std::ios_base::dec, std::ios_base::basefield);
    cout << val << std::endl; // Ausgabe: 255
}

Okt 23, 2024

lst-0864-book.cpp

// https://godbolt.org/z/sYK8oT33x 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw

using std::cout; using std::endl;
int main() {
    double dval = 3.14159;
    std::ios_base::fmtflags ff(std::ios::scientific|std::ios::uppercase);
    cout << std::setiosflags(ff);
    cout << dval << endl;                           // Ausgabe: 3.141590E+00
    cout << std::resetiosflags(ff) << dval << endl; // Ausgabe: 3.14159
    cout << std::setprecision(3) << dval << endl;   // Ausgabe: 3.14
    cout << std::setw(10);
    cout << std::setfill( '*' ) << 1246 << endl;    // Ausgabe: ******1246
}

Okt 23, 2024

lst-0871-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xzzMdjdM 
#include <iostream>
using std::cout; using std::endl;
int main() {
    int val = 255;
    cout.setf(std::ios_base::hex, std::ios_base::basefield);
    cout.setf(std::ios_base::showbase);
    cout << val << std::endl; // Ausgabe: 0xff
    cout.unsetf(std::ios_base::showbase);
    cout.setf(std::ios_base::dec, std::ios_base::basefield);
    cout << val << std::endl; // Ausgabe: 255
}

Okt 23, 2024

lst-0873-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EfEx8fdGo 
#include <fstream>
#include <iostream>
#include <string>
int main() {
    std::string name = "textfile.txt";
    std::ifstream file01;
    file01.open(name);
    if( file01.fail() ) {
        std::cout << "Konnte " << name << " nicht oeffnen\n";
    }
    std::ofstream file02("data.dat");
    if( file02.good() ) {
        std::cout << "data.dat geoeffnet bzw. erzeugt\n";
    }
    std::fstream file03;
    file03.open("database.db");
    if( !file03 ) {
        std::cout << "Konnte database.db nicht oeffnen\n";
    }
}

Okt 23, 2024

lst-0836-godb.cpp

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/z4ajz5E5P 
#include <numeric>    // adjacent_difference
#include <functional> // plus
#include <algorithm>  // copy
#include <iostream>
#include <iterator>   // ostream_iterator
#include <vector>
#include <ranges>     // pairwise_transform
using std::cout; using std::vector; namespace vs = std::views;
int main() {
    // Streamausgabeiterator für int;
    std::ostream_iterator<int> os{std::cout, " "};
    vector data{ 1, -1, 2, -2, -4, 4, -6, 6 };
    std::copy(data.begin(), data.end (), os);
    cout << '\n'; // Ausgabe: 1 1 2 2 4 4 6 6
    vector<int> res( data.size()-1 ); // Platz für Ergebnis
    // Ergebnisse nach res schreiben:
    adjacent_difference(data.begin(), data.end(), res.begin());
    std::copy (res.begin(), res.end (), os);
    cout << '\n'; // Ausgabe: 1 2 3 4 2 8 10
    // gleich nach os schreiben:
    adjacent_difference(data.begin(), data.end(), os, std::plus<int>{});
    cout << '\n'; // Ausgabe: 1 0 1 0 6 0 2 0
    // oder via Range-Adapter:
    for(auto e: vs::pairwise_transform(data, std::plus<int>{}))
        cout << e << ' ';
    cout << '\n'; // Ausgabe: 0 1 0 6 0 2 0
}

Okt 23, 2024

lst-0873-book.cpp

// https://godbolt.org/z/EfEx8fdGo 
#include <fstream>
#include <iostream>
#include <string>
int main() {
    std::string name = "textfile.txt";
    std::ifstream file01;
    file01.open(name);
    if( file01.fail() ) {
        std::cout << "Konnte " << name << " nicht oeffnen\n";
    }
    std::ofstream file02("data.dat");
    if( file02.good() ) {
        std::cout << "data.dat geoeffnet bzw. erzeugt\n";
    }
    std::fstream file03;
    file03.open("database.db");
    if( !file03 ) {
        std::cout << "Konnte database.db nicht oeffnen\n";
    }
}

Okt 23, 2024

lst-0858-book.cpp

// https://godbolt.org/z/rq3eGP3cv 
#include <fstream>
#include <iostream>
using std::cout; using std::cin; using std::ofstream;
void checkIOstate(std::ios& stream) {
    if( stream.good() ) {
        cout << "Alles in Ordnung\n";
    } else if( stream.bad() ) {
        cout << "Fataler Fehler\n";
    } else if( stream.fail()) {
        cout << "Fehler bei der Ein-/Ausgabe\n";
        if( stream.eof()) {
            cout << "Ende des Datenstroms erreicht\n";
        }
    }
    stream.clear();
}
int main() {
    int val=0;
    cout << "Wert eingeben: ";
    cin >> val;
    checkIOstate( cin );
    std::ifstream file;
    file.open("nichtvorhanden.text");
    checkIOstate(file);
    std::fstream fstr;
    fstr.open("neueDatei.txt",
        ofstream::out | ofstream::in
        | ofstream::binary | ofstream::trunc);
    fstr << "Text in der Datei\n";
    fstr.seekp(std::ios_base::beg);
    char ch;
    while( fstr.good()) {
        fstr.get(ch);
        if(fstr.good()) cout.put(ch);
    }
    checkIOstate(fstr);
}

Okt 23, 2024

lst-0842-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/91jj8Toqs 
#include <vector>
#include <iostream>
//  adjacent_pair von oben hier 
int main() {
    std::vector v{1,2,3,4};
    auto f = [](auto a, auto b) { std::cout << (a+b) << ' '; };
    adjacent_pair(v.begin(), v.end(), f); // 3 5 7
    std::cout << '\n';

    std::vector x{4,8};
    adjacent_pair(x.begin(), x.end(), f); // 12
    std::cout << '\n';

    std::vector w{4};
    adjacent_pair(w.begin(), w.end(), f); // nichts
    std::cout << '\n';

    std::vector<int> y{};
    adjacent_pair(y.begin(), y.end(), f); // nichts
    std::cout << '\n';
}

Okt 23, 2024

lst-0810-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KPP16bdK9 
#include <iostream>
#include <valarray>
using std::ostream; using std::valarray;
ostream& operator<<(ostream&os, const valarray<double>&vs) {
    os << "[";
    for(auto&v : vs) os << v << " ";
    return os << "]";
}
int main() {
    valarray a{ 1.0, 2.0, 3.0, 4.0 }; // valarray<double>
    valarray b{ 2.0, 4.0, 6.0, 8.0 };
    valarray c{ 2.5, 1.75, 0.5, 0.125 };
    valarray<double> x = ( a + b ) * c;
    std::cout << "x: " << x << "\n";  // Ausgabe: [7.5 10.5 4.5 1.5 ]
    auto y = ( a + b ) / 2;           // y ist nicht unbedingt ein valarray!
    std::cout << "y: " << y << "\n";  // Ausgabe: [1.5 3 4.5 6 ]
}

Okt 23, 2024

lst-0827-book.cpp

// https://godbolt.org/z/WqvM6KEEM 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
using std::string_view; using namespace std::literals; using std::cout;
auto istPalindrom(string_view sv) {
  return std::ranges::equal(sv.begin(), sv.end(), sv.rbegin(), sv.rend()); };
int main() {
  for(auto s : {"regallager"sv, "rentner"sv, "blutwurst"sv }) {
    cout << s << " ist " << (istPalindrom(s)?"ein":"kein") << " Palindrom\n";
  }
}

Okt 23, 2024

lst-0807-book.cpp

// https://godbolt.org/z/qaKv6Tebf 
#include <stack>
void run(auto data) { /* ... */ }  // C++20, abgekürztes Funktionstemplate
run(stack<int>{});              // Default: nutzt vector<int>
run(stack<int,vector<int>>{});  // wie der Default
run(stack<int,list<int>>{});    // nutzt list<int>

Okt 23, 2024

lst-0809-book.cpp

// https://godbolt.org/z/jrGdT6665 
#include <bitset>
#include <iostream>
using std::cout;
int main() {
    std::bitset<8> bits{};         // 8 Bit dicht gepackt
    bits.set(4);                   // 5. Bit auf 1
    cout << bits << '\n';          // 00010000
    bits.flip();                   // alle Bits invertieren
    cout << bits << '\n';          // 11101111
    bits.set();                    // alle Bits auf 1
    bits.flip(1);                  // 2. Bit invertieren
    std::cout << bits << '\n';     // 11111101
    bits.reset();                  // alle Bits auf 0
    bits.set(4);                   // 5. Bit auf 1
    cout << bits << '\n';          // 00010000
    bits.flip();                   // alle Bits invertieren
    cout << bits << '\n';          // 11101111
    bits.set();                    // alle Bits auf 1
    bits.flip(1);                  // 2. Bit invertieren
    bits.flip(6);                  // 7. Bit invertieren
    cout << bits << '\n';          // 10111101
    // Verknüpfungen
    std::bitset<8> zack("....####", 8, '.', '#');
    cout << zack << '\n';          // 00001111
    cout << (bits & zack) << '\n'; // 00001101
    cout << (bits | zack) << '\n'; // 10111111
    cout << (bits ^ zack) << '\n'; // 10110010
    // andere Integertypen
    std::bitset<64> b(0x123456789abcdef0LL);
    cout << b << '\n';
    // 0001001000110100010101100111100010011010101111001101111011110000
    cout << std::hex << b.to_ullong() << '\n'; // umwandeln
    // 123456789abcdef0
}

Okt 23, 2024

lst-0806-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a8cGxr9s9 
#include <unordered_set> // unordered_multiset
#include <iostream>
#include <string>
using std::unordered_multiset; using std::cout; using std::string;
int main() {
    const string in = "Keines meiner beiden Beine zeigt einen Schein.";
    unordered_multiset<int> cs(in.begin(), in.end()); // string als Container
    cout << cs.count( 'e' ) << " Mal e\n"; // Ausgabe: 10 Mal e
}

Okt 23, 2024

lst-0830-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7r4b8jdGr 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using std::to_string; using std::string; using std::vector;
struct Squares {
    mutable int n = 1;
    int operator()() const { return n*n++; }
};
int main() {
    vector<int> sq(10);
    std::ranges::generate(sq, Squares{});
    std::ranges::for_each(sq, [](auto n) {
        std::cout << n << " "; });
    std::cout << '\n';        // Ausgabe: 1 4 9 16 25 36 49 64 81 100
    string a = "NCC-";
    vector<int> b {1,7,0,1};
    vector<string> c(4);
    auto f = [](char c, int i) -> string { return c+to_string(i); };
    std::ranges::transform(
        a,           // Eingabe 1
        b,           // Eingabe 2
        c.begin(),   // Ausgabe
        f);          // string f(char,int)
    std::ranges::for_each(c, [](auto s) {
        std::cout << s << " "; });
    std::cout << '\n';        // Ausgabe: N1 C7 C0 -1
}

Okt 23, 2024

lst-0816-book.cpp

// https://godbolt.org/z/5czT3xoxc 
std::vector v{0,1,3,5,7,9,2,4,6,8};
bool flag = true;
for(size_t i=1; (i <= v.size()) && flag; ++i) {
    flag = false;
    for(size_t j=0; (j < v.size()-1); ++j) {
        if(v[j+1] < v[j]) {
            std::swap(v[j+1], v[j]);
            flag = true;
        }
    }
}
for(int i:v) std::cout << i << ' ';

Okt 23, 2024

lst-0811-book.cpp

// https://godbolt.org/z/r11584Wef 
#include <valarray>
#include <iostream>
using namespace std;
template<typename T>
ostream& operator<<=(ostream &os, const valarray<T>& a) { // '<<=' mit Newline
    for(const auto &v : a) os << v << ' ';
    return os << '\n';
}
int main() {
    // … Beispielcode hier …
}

Okt 23, 2024

lst-0811-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r11584Wef 
#include <valarray>
#include <iostream>
using namespace std;
template<typename T>
ostream& operator<<=(ostream &os, const valarray<T>& a) { // '<<=' mit Newline
    for(const auto &v : a) os << v << ' ';
    return os << '\n';
}
int main() {
    //  Beispielcode hier 
}

Okt 23, 2024

lst-0808-book.cpp

// https://godbolt.org/z/6sYGnqnTj 
#include <vector>
#include <string>
#include <iostream>
#include <string_view>
using std::string; using std::string_view; using std::vector; using std::cout;
int get_len(string_view str) { return str.size(); } // string_view als Parameter
int main() {
    string s1 = "Hallo";                  // einfach mit Stringliteral
    string s2{'H','a','l','l','o'};       // oder mit Liste von char
    using namespace std::literals;        // für ""s-Suffix und ""sv-Suffix
    auto s3 = "Hallo"s;  // noch einfacher mit echtem Stringliteral
    vector<char> v1{"Hallo"};             //                          (ERR)  kein vector mit Stringliteral
    vector<char> v2{'H','a','l','l','o'}; // Liste von char ist okay
    cout << s1 << s2 << s3 << '\n';       // Ausgabe von string geht
    cout << v1 << v2 << '\n';             //                          (ERR)  vector hat keine Ausgabe
    const auto str = "String"s;           // Stringliteral
    const auto strv = "String-View"sv;    // String-View-Literal
    cout << "Laenge von 'str' ist " << get_len(str) << '\n';   // Ausgabe: … 6
    cout << "Laenge von 'strv' ist " << get_len(strv) << '\n'; // Ausgabe: … 11
}

Okt 23, 2024

lst-0810-book.cpp

// https://godbolt.org/z/KPP16bdK9 
#include <iostream>
#include <valarray>
using std::ostream; using std::valarray;
ostream& operator<<(ostream&os, const valarray<double>&vs) {
    os << "[";
    for(auto&v : vs) os << v << " ";
    return os << "]";
}
int main() {
    valarray a{ 1.0, 2.0, 3.0, 4.0 }; // valarray<double>
    valarray b{ 2.0, 4.0, 6.0, 8.0 };
    valarray c{ 2.5, 1.75, 0.5, 0.125 };
    valarray<double> x = ( a + b ) * c;
    std::cout << "x: " << x << "\n";  // Ausgabe: [7.5 10.5 4.5 1.5 ]
    auto y = ( a + b ) / 2;           // y ist nicht unbedingt ein valarray!
    std::cout << "y: " << y << "\n";  // Ausgabe: [1.5 3 4.5 6 ]
}

Okt 23, 2024

lst-0830-book.cpp

// https://godbolt.org/z/7r4b8jdGr 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using std::to_string; using std::string; using std::vector;
struct Squares {
    mutable int n = 1;
    int operator()() const { return n*n++; }
};
int main() {
    vector<int> sq(10);
    std::ranges::generate(sq, Squares{});
    std::ranges::for_each(sq, [](auto n) {
        std::cout << n << " "; });
    std::cout << '\n';        // Ausgabe: 1 4 9 16 25 36 49 64 81 100
    string a = "NCC-";
    vector<int> b {1,7,0,1};
    vector<string> c(4);
    auto f = [](char c, int i) -> string { return c+to_string(i); };
    std::ranges::transform(
        a,           // Eingabe 1
        b,           // Eingabe 2
        c.begin(),   // Ausgabe
        f);          // string f(char,int)
    std::ranges::for_each(c, [](auto s) {
        std::cout << s << " "; });
    std::cout << '\n';        // Ausgabe: N1 C7 C0 -1
}

Okt 23, 2024

lst-0819-godb.cpp

//#(compile) c++; compiler:g112; options:-O3 -std=c++23 -ltbb; libs:tbb@trunk
// https://godbolt.org/z/qcT9o7YfG 
#include <algorithm>  // find
#include <numeric>    // reduce, accumulate
#include <execution>  // std::execution
#include <iostream>
#include <chrono>     // Zeitmessung
using namespace std::chrono;
long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start).count();
}
template <typename FUNC> void timeit(const char* title, FUNC func) {
    auto start = steady_clock::now();
    auto ret = func(); // ausführen
    std::cout << title << ": " << millisSeit(start) << " ms" << std::endl;
}
int main() {
    using namespace std::execution;          // seq, par, par_unseq
    using std::reduce; using std::accumulate; using std::find;
    std::vector<double> v(600'000'000, 0.0); // 600 Millionen Elemente
    for(auto&x:v) x = ::rand();              // mit Zufallswerten füllen
    timeit("warmlaufen       ", [&v] {
        return reduce(seq, v.begin(), v.end(), 0.0);
    });
    timeit("accumulate       ", [&v] {
        return accumulate(v.begin(), v.end(), 0.0);
    });
    timeit("reduce, seq      ", [&v] {
        return reduce(seq, v.begin(), v.end(), 0.0);
    });
    timeit("reduce, par      ", [&v] {
        return reduce(par, v.begin(), v.end(), 0.0);
    });

    timeit("reduce, par_unseq", [&v] {
        return reduce(par_unseq, v.begin(), v.end(), 0.0);
    });
    timeit("find, seq        ", [&v] {
        return find(seq, v.begin(), v.end(), 1.1) == v.end() ? 0.0 : 1.0;
    });
    timeit("find, par        ", [&v] {
        return find(par, v.begin(), v.end(), 1.1) == v.end() ? 0.0 : 1.0;
    });
    return 0;
}

Okt 23, 2024

lst-0808-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6sYGnqnTj 
#include <vector>
#include <string>
#include <iostream>
#include <string_view>
using std::string; using std::string_view; using std::vector; using std::cout;
int get_len(string_view str) { return str.size(); } // string_view als Parameter
int main() {
    string s1 = "Hallo";                  // einfach mit Stringliteral
    string s2{'H','a','l','l','o'};       // oder mit Liste von char
    using namespace std::literals;        // für ""s-Suffix und ""sv-Suffix
    auto s3 = "Hallo"s;  // noch einfacher mit echtem Stringliteral
    vector<char> v1{"Hallo"};             //                          (ERR)  kein vector mit Stringliteral
    vector<char> v2{'H','a','l','l','o'}; // Liste von char ist okay
    cout << s1 << s2 << s3 << '\n';       // Ausgabe von string geht
    cout << v1 << v2 << '\n';             //                          (ERR)  vector hat keine Ausgabe
    const auto str = "String"s;           // Stringliteral
    const auto strv = "String-View"sv;    // String-View-Literal
    cout << "Laenge von 'str' ist " << get_len(str) << '\n';   // Ausgabe:  6
    cout << "Laenge von 'strv' ist " << get_len(strv) << '\n'; // Ausgabe:  11
}

Okt 23, 2024

lst-0817-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EjT7nPPv7 
std::vector v{0,1,3,5,7,9,2,4,6,8};
std::sort(v.begin(), v.end());
for(int i:v) std::cout << i << ' ';
std::cout << '\n';
// oder mit einer Range:
std::ranges::sort(v);
for(int i:v) std::cout << i << ' ';
std::cout << '\n';

Okt 23, 2024

lst-0828-book.cpp

// https://godbolt.org/z/jz1Gqo7d9 
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
    std::vector<int> c{ 1,2,3,4 };
    std::ranges::for_each(c, [](auto &n) { n*=n; }); //             (ERR)  modifizierend
    std::cout << c[3] << '\n'; // Ausgabe: 16
}

Okt 23, 2024

lst-0814-book.cpp

// https://godbolt.org/z/6z6d71Ka4 
valarray<int> v {
  1,  2,  3,
  4,  5,  6,
  7,  8,  9,
 10, 11, 12 };
v[slice(0, 4, 3)] *= valarray<int>(v[slice(0, 4, 3)]); // erste Spalte quadrieren
cout <<= v;  // Ausgabe: 1 2 3 16 5 6 49 8 9 100 11 12
v[slice(0, 4, 3)] = valarray<int>{1, 4, 7, 10}; // wiederherstellen
valarray<int> r3(v[gslice(0, {2, 3}, {6,2})]);  // 2-D-Schnitt vom 3-D-Würfel
cout <<= r3;                                    // Ausgabe: 1 3 5 7 9 11
valarray<char> text("jetzt gehts erst los", 20);
valarray<char> caps("JGEL", 4);
valarray<size_t> idx{ 0, 6, 12, 17 };           // Indexe in text
text[idx] = caps;                               // indirekt zuweisen
cout <<= text;                                  // Ausgabe: Jetzt Gehts Erst Los

Okt 23, 2024

lst-0833-book.cpp

// https://godbolt.org/z/qW4hvE9s3 
#include <algorithm>
#include <iostream>
#include <list>
#include <string>
#include <iterator> // ostream_iterator
#include <cctype>   // toupper
using std::toupper;
int main() {
    std::list a{ 1,2,4,4,4,7,7,9 };
    std::list b{ 2,2,3,4,4,8 };
    using Os = std::ostream_iterator<int>; // Typ des Ausgabeiterators
    Os os{std::cout, " "};                 // Streamausgabeiterator für int
    auto run = [&a,&b,&os](auto algo) {    // nutze a, b und os
        algo(a.begin(), a.end(), b.begin(), b.end(), os); // Algorithmus aufrufen
        std::cout << '\n';
    };

    // Ergebnisse der Algorithmen
    using It = decltype(a.begin());       // Typ der Eingabeiteratoren

    run(std::merge<It,It,Os>);            // Ausgabe: 1 2 2 2 3 4 4 4 4 4 7 7 8 9
    run(std::set_union<It,It,Os>);        // Ausgabe: 1 2 2 3 4 4 4 7 7 8 9
    run(std::set_intersection<It,It,Os>); // Ausgabe: 2 4 4
    run(std::set_difference<It,It,Os>);   // Ausgabe: 1 4 7 7 9
    run(std::set_symmetric_difference<It,It,Os>); // Ausgabe: 1 2 3 4 7 7 8 9

    // Mit Buchstaben wird es noch klarer
    std::string x = "abdddggi";
    std::string y = "BBCDDH";
    using Us = std::ostream_iterator<char>;   // Typ des Ausgabeiterators
    Us us{std::cout, ""};                     // Streamausgabeiterator für char
    auto compare = [](auto c, auto d) { return toupper(c) < toupper(d); };
    auto run2 = [&x,&y,&us,&compare](auto algo) {    // nutze x, y und us
        algo(x.begin(), x.end(), y.begin(), y.end(), us, compare);
        std::cout << '\n';
    };
    // Ergebnisse der Algorithmen
    using Jt = decltype(x.begin());           // Typ der Eingabeiteratoren
    using Cm = decltype(compare);             // Typ der Vergleichsfunktion

    run2(std::merge<Jt,Jt,Us,Cm>);            // Ausgabe: abBBCdddDDggHi
    run2(std::set_union<Jt,Jt,Us,Cm>);        // Ausgabe: abBCdddggHi
    run2(std::set_intersection<Jt,Jt,Us,Cm>); // Ausgabe: bdd
    run2(std::set_difference<Jt,Jt,Us,Cm>);   // Ausgabe: adggi
    run2(std::set_symmetric_difference<Jt,Jt,Us,Cm>); // Ausgabe: aBCdggHi
}

Okt 23, 2024

lst-0816-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5czT3xoxc 
std::vector v{0,1,3,5,7,9,2,4,6,8};
bool flag = true;
for(size_t i=1; (i <= v.size()) && flag; ++i) {
    flag = false;
    for(size_t j=0; (j < v.size()-1); ++j) {
        if(v[j+1] < v[j]) {
            std::swap(v[j+1], v[j]);
            flag = true;
        }
    }
}
for(int i:v) std::cout << i << ' ';

Okt 23, 2024

lst-0806-book.cpp

// https://godbolt.org/z/a8cGxr9s9 
#include <unordered_set> // unordered_multiset
#include <iostream>
#include <string>
using std::unordered_multiset; using std::cout; using std::string;
int main() {
    const string in = "Keines meiner beiden Beine zeigt einen Schein.";
    unordered_multiset<int> cs(in.begin(), in.end()); // string als Container
    cout << cs.count( 'e' ) << " Mal e\n"; // Ausgabe: 10 Mal e
}

Okt 23, 2024

lst-0807-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qaKv6Tebf 
#include <stack>
void run(auto data) { /* ... */ }  // C++20, abgekürztes Funktionstemplate
run(stack<int>{});              // Default: nutzt vector<int>
run(stack<int,vector<int>>{});  // wie der Default
run(stack<int,list<int>>{});    // nutzt list<int>

Okt 23, 2024

lst-0813-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dd1q6GdYq 
valarray v { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
valarray<int> r1(v[slice(0, 4, 3)]); // Start bei 0, 4 Elemente, Schrittweite 3
cout <<= r1;                         // Ausgabe: 1 4 7 10
valarray<int> r2(v[v > 6]);          // adressiert per valarray<bool>
cout <<= r2;                         // Ausgabe: 7 8 9 10 11 12
const valarray<size_t> indirekt{ 2, 2, 3, 6 };  // doppelte erlaubt
valarray<int> r5(v[indirekt]);       // adressiert per valarray<size_t>
cout <<= r5;                         // Ausgabe: 3 3 4 7

Okt 23, 2024

lst-0817-book.cpp

// https://godbolt.org/z/EjT7nPPv7 
std::vector v{0,1,3,5,7,9,2,4,6,8};
std::sort(v.begin(), v.end());
for(int i:v) std::cout << i << ' ';
std::cout << '\n';
// oder mit einer Range:
std::ranges::sort(v);
for(int i:v) std::cout << i << ' ';
std::cout << '\n';

Okt 23, 2024

lst-0818-book.cpp

// https://godbolt.org/z/9xrP8Ehvd 
#include <algorithm>
#include <vector>
#include <iostream>
void sort_uniq(std::vector<int> &data) {
    std::ranges::sort(data);                        // sortieren
    auto to_delete = std::ranges::unique(data);     // nach hinten verschieben
    data.erase(to_delete.begin(), to_delete.end()); // tatsächlich löschen
}
int main() {
    std::vector ns{1,5,2,3,9,2,2,2,2,1,5,2,2,3,1,1,2,2,1};
    sort_uniq(ns);
    std::ranges::for_each(ns, [](auto x) {
        std::cout << x << ' '; });
    std::cout << '\n'; // Ausgabe: 1 2 3 5 9
}

Okt 23, 2024

lst-0825-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s1GjfWxv6 
void print(ranges::view auto range) { // Wertparameter, eingeschränkt auf Views
  for (auto const& e : range) { cout << e; } cout << '\n';
}
vector vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
list   lst{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(vec);                      //             (ERR)  Verboten für Container, sehr gut!
print(vs::all(vec));             // Container in View umwandeln
print(vs::all(lst));             // Container in View umwandeln
print(vec | vs::take(3));        // take mit vector klappt
print(lst | vs::take(3));        // take mit list klappt
print(vec | vs::drop(5));        // drop mit vector klappt
print(lst | vs::drop(5));        // als Wertparameter klappt drop mit list

Okt 23, 2024

lst-0814-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6z6d71Ka4 
valarray<int> v {
  1,  2,  3,
  4,  5,  6,
  7,  8,  9,
 10, 11, 12 };
v[slice(0, 4, 3)] *= valarray<int>(v[slice(0, 4, 3)]); // erste Spalte quadrieren
cout <<= v;  // Ausgabe: 1 2 3 16 5 6 49 8 9 100 11 12
v[slice(0, 4, 3)] = valarray<int>{1, 4, 7, 10}; // wiederherstellen
valarray<int> r3(v[gslice(0, {2, 3}, {6,2})]);  // 2-D-Schnitt vom 3-D-Würfel
cout <<= r3;                                    // Ausgabe: 1 3 5 7 9 11
valarray<char> text("jetzt gehts erst los", 20);
valarray<char> caps("JGEL", 4);
valarray<size_t> idx{ 0, 6, 12, 17 };           // Indexe in text
text[idx] = caps;                               // indirekt zuweisen
cout <<= text;                                  // Ausgabe: Jetzt Gehts Erst Los

Okt 23, 2024

lst-0831-book.cpp

// https://godbolt.org/z/j9ozax8qE 
#include <ranges> // zip_transform
// …
auto res = std::views::zip_transform(f, a, b);  // Range-Adapter
for(auto s: res) { std::cout << s << " "; };
std::cout << '\n';        // Ausgabe: N1 C7 C0 -1

Okt 23, 2024

lst-0815-book.cpp

// https://godbolt.org/z/jr1chqbze 
#include <iostream>
#include <iomanip> // setw
#include <valarray>
using namespace std;

/* Matrix drucken */
template<class T>
void printMatrix(ostream&os, const valarray<T>& a, size_t n) {
    for(size_t i = 0; i < (n*n); ++i) {
        os << setw(3) << a[i];        // Wert drucken
        os << ((i+1)%n ? ' ' : '\n'); // nächste Zeile?
    }
}

/* Matrix-Kreuzprodukt */
template<class T>

valarray<T> matmult(
        const valarray<T>& a, size_t arows, size_t acols,
        const valarray<T>& b, size_t brows, size_t bcols)
{
    /* Bedingung: acols==brows */
    valarray<T> result(arows * bcols);
    for(size_t i = 0; i < arows; ++i) {
      for(size_t j = 0; j < bcols; ++j) {
        auto row = a[slice(acols*i, acols, 1)]; // Zeile
        auto col = b[slice(j, brows, bcols)];   // Spalte
        result[i*bcols+j] = (row*col).sum();    // Kreuzprodukt Zeile a[i] und 
                                                // Spalte b[j]
      }
    }
    return result;
}

int main() {
    constexpr int n = 3;
    valarray ma{1,0,-1,  2,2,-3,  3,4,0};         // 3 x 3-Matrix
    valarray mb{3,4,-1,  1,-3,0,  -1,1,2};        // 3 x 3-Matrix
    printMatrix(cout, ma, n);
    cout << "  -mal-\n ";
    printMatrix(cout, mb, n);
    cout << "  -ergibt-:\n ";
    valarray<int> mc = matmult(ma, n,n, mb, n,n);
    printMatrix(cout, mc, n);
}

Okt 23, 2024

lst-0815-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jr1chqbze 
#include <iostream>
#include <iomanip> // setw
#include <valarray>
using namespace std;

/* Matrix drucken */
template<class T>
void printMatrix(ostream&os, const valarray<T>& a, size_t n) {
    for(size_t i = 0; i < (n*n); ++i) {
        os << setw(3) << a[i];        // Wert drucken
        os << ((i+1)%n ? ' ' : '\n'); // nächste Zeile?
    }
}

/* Matrix-Kreuzprodukt */
template<class T>

valarray<T> matmult(
        const valarray<T>& a, size_t arows, size_t acols,
        const valarray<T>& b, size_t brows, size_t bcols)
{
    /* Bedingung: acols==brows */
    valarray<T> result(arows * bcols);
    for(size_t i = 0; i < arows; ++i) {
      for(size_t j = 0; j < bcols; ++j) {
        auto row = a[slice(acols*i, acols, 1)]; // Zeile
        auto col = b[slice(j, brows, bcols)];   // Spalte
        result[i*bcols+j] = (row*col).sum();    // Kreuzprodukt Zeile a[i] und 
                                                // Spalte b[j]
      }
    }
    return result;
}

int main() {
    constexpr int n = 3;
    valarray ma{1,0,-1,  2,2,-3,  3,4,0};         // 3 x 3-Matrix
    valarray mb{3,4,-1,  1,-3,0,  -1,1,2};        // 3 x 3-Matrix
    printMatrix(cout, ma, n);
    cout << "  -mal-\n ";
    printMatrix(cout, mb, n);
    cout << "  -ergibt-:\n ";
    valarray<int> mc = matmult(ma, n,n, mb, n,n);
    printMatrix(cout, mc, n);
}

Okt 23, 2024

lst-0812-book.cpp

// https://godbolt.org/z/WGazqoGc1 
valarray<int> data;              // zunächst Größe 0
cout << data.size() << "\n";     // Ausgabe: 0
data.resize(100);                // vergrößert
cout << data.size() << "\n";     // Ausgabe: 100
valarray<int> data2(200);        // Platz für 200 Werte
cout << data2.size() << "\n";    // Ausgabe: 200
valarray<int> dataC(5, 20);      // zwanzig 5en, andersherum als bei vector
cout << dataC.size() <<": dataC[6]="<< dataC[6]<< "\n"; // Ausgabe: 20: dataC[6]=5
valarray dataD{ 2, 3, 5, 7, 11 };      // valarray<int>, Initialisierungsliste
cout << dataD.size() <<": dataD[3]=" <<dataD[3]<< "\n"; // Ausgabe: 5: dataD[3]=7

Okt 23, 2024

lst-0832-book.cpp

// https://godbolt.org/z/s53qx664K 
#include <iostream>
#include <random>       // default_random_engine
#include <string>
#include <iterator>     // back_inserter
#include <algorithm>    // sample

int main() {
   std::default_random_engine zufall{};
   const std::string in = "abcdefgh";
   for(auto idx : {0,1,2,3}) {
     std::string out;
     std::ranges::sample(in, std::back_inserter(out), 5, zufall);
     std::cout << out << '\n';
   }
}

Okt 23, 2024

lst-0833-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qW4hvE9s3 
#include <algorithm>
#include <iostream>
#include <list>
#include <string>
#include <iterator> // ostream_iterator
#include <cctype>   // toupper
using std::toupper;
int main() {
    std::list a{ 1,2,4,4,4,7,7,9 };
    std::list b{ 2,2,3,4,4,8 };
    using Os = std::ostream_iterator<int>; // Typ des Ausgabeiterators
    Os os{std::cout, " "};                 // Streamausgabeiterator für int
    auto run = [&a,&b,&os](auto algo) {    // nutze a, b und os
        algo(a.begin(), a.end(), b.begin(), b.end(), os); // Algorithmus aufrufen
        std::cout << '\n';
    };

    // Ergebnisse der Algorithmen
    using It = decltype(a.begin());       // Typ der Eingabeiteratoren

    run(std::merge<It,It,Os>);            // Ausgabe: 1 2 2 2 3 4 4 4 4 4 7 7 8 9
    run(std::set_union<It,It,Os>);        // Ausgabe: 1 2 2 3 4 4 4 7 7 8 9
    run(std::set_intersection<It,It,Os>); // Ausgabe: 2 4 4
    run(std::set_difference<It,It,Os>);   // Ausgabe: 1 4 7 7 9
    run(std::set_symmetric_difference<It,It,Os>); // Ausgabe: 1 2 3 4 7 7 8 9

    // Mit Buchstaben wird es noch klarer
    std::string x = "abdddggi";
    std::string y = "BBCDDH";
    using Us = std::ostream_iterator<char>;   // Typ des Ausgabeiterators
    Us us{std::cout, ""};                     // Streamausgabeiterator für char
    auto compare = [](auto c, auto d) { return toupper(c) < toupper(d); };
    auto run2 = [&x,&y,&us,&compare](auto algo) {    // nutze x, y und us
        algo(x.begin(), x.end(), y.begin(), y.end(), us, compare);
        std::cout << '\n';
    };
    // Ergebnisse der Algorithmen
    using Jt = decltype(x.begin());           // Typ der Eingabeiteratoren
    using Cm = decltype(compare);             // Typ der Vergleichsfunktion

    run2(std::merge<Jt,Jt,Us,Cm>);            // Ausgabe: abBBCdddDDggHi
    run2(std::set_union<Jt,Jt,Us,Cm>);        // Ausgabe: abBCdddggHi
    run2(std::set_intersection<Jt,Jt,Us,Cm>); // Ausgabe: bdd
    run2(std::set_difference<Jt,Jt,Us,Cm>);   // Ausgabe: adggi
    run2(std::set_symmetric_difference<Jt,Jt,Us,Cm>); // Ausgabe: aBCdggHi
}

Okt 23, 2024

lst-0809-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jrGdT6665 
#include <bitset>
#include <iostream>
using std::cout;
int main() {
    std::bitset<8> bits{};         // 8 Bit dicht gepackt
    bits.set(4);                   // 5. Bit auf 1
    cout << bits << '\n';          // 00010000
    bits.flip();                   // alle Bits invertieren
    cout << bits << '\n';          // 11101111
    bits.set();                    // alle Bits auf 1
    bits.flip(1);                  // 2. Bit invertieren
    std::cout << bits << '\n';     // 11111101
    bits.reset();                  // alle Bits auf 0
    bits.set(4);                   // 5. Bit auf 1
    cout << bits << '\n';          // 00010000
    bits.flip();                   // alle Bits invertieren
    cout << bits << '\n';          // 11101111
    bits.set();                    // alle Bits auf 1
    bits.flip(1);                  // 2. Bit invertieren
    bits.flip(6);                  // 7. Bit invertieren
    cout << bits << '\n';          // 10111101
    // Verknüpfungen
    std::bitset<8> zack("....####", 8, '.', '#');
    cout << zack << '\n';          // 00001111
    cout << (bits & zack) << '\n'; // 00001101
    cout << (bits | zack) << '\n'; // 10111111
    cout << (bits ^ zack) << '\n'; // 10110010
    // andere Integertypen
    std::bitset<64> b(0x123456789abcdef0LL);
    cout << b << '\n';
    // 0001001000110100010101100111100010011010101111001101111011110000
    cout << std::hex << b.to_ullong() << '\n'; // umwandeln
    // 123456789abcdef0
}

Okt 23, 2024

lst-0825-book.cpp

// https://godbolt.org/z/s1GjfWxv6 
void print(ranges::view auto range) { // Wertparameter, eingeschränkt auf Views
  for (auto const& e : range) { cout << e; } cout << '\n';
}
vector vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
list   lst{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(vec);                      //             (ERR)  Verboten für Container, sehr gut!
print(vs::all(vec));             // Container in View umwandeln
print(vs::all(lst));             // Container in View umwandeln
print(vec | vs::take(3));        // take mit vector klappt
print(lst | vs::take(3));        // take mit list klappt
print(vec | vs::drop(5));        // drop mit vector klappt
print(lst | vs::drop(5));        // als Wertparameter klappt drop mit list

Okt 23, 2024

lst-0834-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/73hTTM7s6 
#include <iostream>
#include <algorithm>
#include <string>
void one(std::string &seq) {
    std::ranges::next_permutation(seq);
    std::cout << seq << '\n';
}
int main() {
    std::string seq = "BDK";
    std::cout << seq << '\n'; // Ausgabe: BDK
    auto limit = 3*2*1;       // n!
    for(int i=0; i<limit; ++i)
        one(seq);
    // Hier ist die Sequenz wieder in ihrem Ursprungszustand.
}

Okt 23, 2024

lst-0821-book.cpp

// https://godbolt.org/z/hYTv6f9eo 
#include <ranges>
#include <array>
#include <string>
#include <iostream>
#include <string_view>
using namespace std::literals; using namespace std;

// Funktion für die Ausgabe von allem Möglichen
template <typename OBJ>
void print(OBJ&& obj, int level = 0) {
  if constexpr(std::ranges::input_range<OBJ>) {                 // range
    cout << '[';
    for (const auto& elem : obj) print(elem, level+1);
    cout << ']';
  } else if constexpr(requires (OBJ tpl){ std::get<0>(tpl);}) { // tuple/pair
    cout << "(";
    print(get<0>(obj), level+1); print(get<1>(obj), level+1);
    cout << ")";
  } else cout << obj;                                           // element
  if (level == 0) cout << '\n';
}
int main() {
  using namespace std::views; // ausnahmsweise für die Kürze
  auto const nums = array{0, 0, 1, 1, 2, 2};
  auto const animals = array{"cat"s, "dog"s};
  print(iota(0, 5) | chunk(2));                      // Ausgabe: [[01][23][4]]
  print(nums | chunk_by(equal_to{}));                // Ausgabe: [[00][11][22]]
  print(iota(0, 5) | slide(3));                      // Ausgabe: [[012][123][234]]
  print(iota(0, 10) | stride(3));                    // Ausgabe: [0369]
  print(repeat(8) |take(5));                         // Ausgabe: [88888]
  print(zip_transform(plus{}, nums, nums));          // Ausgabe: [002244]
  print(zip(iota(0, 3), iota(1, 4)));                // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | adjacent<2>);                   // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | pairwise);                      // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | adjacent_transform<2>(plus{})); // Ausgabe: [135]
  print(iota(0, 4) | pairwise_transform(plus{}));    // Ausgabe: [135]
  print(animals | join_with( '+' ));                 // Ausgabe: [cat+dog]
  print(cartesian_product(iota(0, 2), "AZ"s));       // Ausgabe: [(0A)(0Z)(1A)(1Z)]
  print(enumerate("APL"s));                          // Ausgabe: [(0A)(1P)(2L)]
  return 0;
}

Okt 23, 2024

lst-0834-book.cpp

// https://godbolt.org/z/73hTTM7s6 
#include <iostream>
#include <algorithm>
#include <string>
void one(std::string &seq) {
    std::ranges::next_permutation(seq);
    std::cout << seq << '\n';
}
int main() {
    std::string seq = "BDK";
    std::cout << seq << '\n'; // Ausgabe: BDK
    auto limit = 3*2*1;       // n!
    for(int i=0; i<limit; ++i)
        one(seq);
    // Hier ist die Sequenz wieder in ihrem Ursprungszustand.
}

Okt 23, 2024

lst-0824-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/64zdMEe4r 
void print(const auto& range) { //             (ERR)  kritisch: konstante Referenz
  for (auto const& e : range) { cout << e; } cout << '\n';
}
vector vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
list   lst{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(vec);                  // funktioniert auf direkten Containern
print(lst);                  // funktioniert auf direkten Containern
print(vec | vs::take(3));    // take mit vector klappt
print(lst | vs::take(3));    // take mit list klappt
print(vec | vs::drop(5));    // drop mit vector klappt
print(lst | vs::drop(5));    //             (ERR)  drop mit list klappt nicht!

Okt 23, 2024

lst-0828-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jz1Gqo7d9 
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
    std::vector<int> c{ 1,2,3,4 };
    std::ranges::for_each(c, [](auto &n) { n*=n; }); //             (ERR)  modifizierend
    std::cout << c[3] << '\n'; // Ausgabe: 16
}

Okt 23, 2024

lst-0824-book.cpp

// https://godbolt.org/z/64zdMEe4r 
void print(const auto& range) { //             (ERR)  kritisch: konstante Referenz
  for (auto const& e : range) { cout << e; } cout << '\n';
}
vector vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
list   lst{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(vec);                  // funktioniert auf direkten Containern
print(lst);                  // funktioniert auf direkten Containern
print(vec | vs::take(3));    // take mit vector klappt
print(lst | vs::take(3));    // take mit list klappt
print(vec | vs::drop(5));    // drop mit vector klappt
print(lst | vs::drop(5));    //             (ERR)  drop mit list klappt nicht!

Okt 23, 2024

lst-0827-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WqvM6KEEM 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
using std::string_view; using namespace std::literals; using std::cout;
auto istPalindrom(string_view sv) {
  return std::ranges::equal(sv.begin(), sv.end(), sv.rbegin(), sv.rend()); };
int main() {
  for(auto s : {"regallager"sv, "rentner"sv, "blutwurst"sv }) {
    cout << s << " ist " << (istPalindrom(s)?"ein":"kein") << " Palindrom\n";
  }
}

Okt 23, 2024

lst-0826-book.cpp

// https://godbolt.org/z/3r5E1f9YP 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
#include <ranges>
using std::vector; using std::string; using std::string_view;
using namespace std::literals; using std::find_if;
vector<string> demo_split(string_view s) {
  vector<string> result{};
  auto it = s.begin();
  while(it != s.end()) {
    // bis normales Zeichen:
    it = find_if(it, s.end(), [](char c) { return c!=' '; });
     // bis Leerzeichen:
     auto jt = find_if(it, s.end(), [](char c) { return c==' '; });
    if(it!=s.end())
      result.push_back(string(it, jt)); // Kopie ins Ergebnis
    it = jt;
  }
  return result;
}
int main() {
  auto text = "Der Text ist kurz"sv;
  auto res = demo_split(text);
  std::ranges::for_each(res, [](const string &e) {
      std::cout << "[" << e << "] "; });
  std::cout << '\n'; // Ausgabe: [Der] [Text] [ist] [kurz]
  // oder gleich mit views::split:
  for(auto word : text | std::views::split(" "sv)) {
    std::cout << "[";
    for(auto c : word) std::cout << c;
    std::cout << "] ";
  } // Ausgabe: [Der] [Text] [ist] [kurz]
}

Okt 23, 2024

lst-0821-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hYTv6f9eo 
#include <ranges>
#include <array>
#include <string>
#include <iostream>
#include <string_view>
using namespace std::literals; using namespace std;

// Funktion für die Ausgabe von allem Möglichen
template <typename OBJ>
void print(OBJ&& obj, int level = 0) {
  if constexpr(std::ranges::input_range<OBJ>) {                 // range
    cout << '[';
    for (const auto& elem : obj) print(elem, level+1);
    cout << ']';
  } else if constexpr(requires (OBJ tpl){ std::get<0>(tpl);}) { // tuple/pair
    cout << "(";
    print(get<0>(obj), level+1); print(get<1>(obj), level+1);
    cout << ")";
  } else cout << obj;                                           // element
  if (level == 0) cout << '\n';
}
int main() {
  using namespace std::views; // ausnahmsweise für die Kürze
  auto const nums = array{0, 0, 1, 1, 2, 2};
  auto const animals = array{"cat"s, "dog"s};
  print(iota(0, 5) | chunk(2));                      // Ausgabe: [[01][23][4]]
  print(nums | chunk_by(equal_to{}));                // Ausgabe: [[00][11][22]]
  print(iota(0, 5) | slide(3));                      // Ausgabe: [[012][123][234]]
  print(iota(0, 10) | stride(3));                    // Ausgabe: [0369]
  print(repeat(8) |take(5));                         // Ausgabe: [88888]
  print(zip_transform(plus{}, nums, nums));          // Ausgabe: [002244]
  print(zip(iota(0, 3), iota(1, 4)));                // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | adjacent<2>);                   // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | pairwise);                      // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | adjacent_transform<2>(plus{})); // Ausgabe: [135]
  print(iota(0, 4) | pairwise_transform(plus{}));    // Ausgabe: [135]
  print(animals | join_with( '+' ));                 // Ausgabe: [cat+dog]
  print(cartesian_product(iota(0, 2), "AZ"s));       // Ausgabe: [(0A)(0Z)(1A)(1Z)]
  print(enumerate("APL"s));                          // Ausgabe: [(0A)(1P)(2L)]
  return 0;
}

Okt 23, 2024

lst-0820-book.cpp

// https://godbolt.org/z/rrq1v5qPs 
std::list lst{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto take5 = rs::take_view{lst, 5};     // View via Typ
auto take6 = lst | vs::take(6);         // View via Adapter

Okt 23, 2024

lst-0812-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WGazqoGc1 
valarray<int> data;              // zunächst Größe 0
cout << data.size() << "\n";     // Ausgabe: 0
data.resize(100);                // vergrößert
cout << data.size() << "\n";     // Ausgabe: 100
valarray<int> data2(200);        // Platz für 200 Werte
cout << data2.size() << "\n";    // Ausgabe: 200
valarray<int> dataC(5, 20);      // zwanzig 5en, andersherum als bei vector
cout << dataC.size() <<": dataC[6]="<< dataC[6]<< "\n"; // Ausgabe: 20: dataC[6]=5
valarray dataD{ 2, 3, 5, 7, 11 };      // valarray<int>, Initialisierungsliste
cout << dataD.size() <<": dataD[3]=" <<dataD[3]<< "\n"; // Ausgabe: 5: dataD[3]=7

Okt 23, 2024

lst-0832-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s53qx664K 
#include <iostream>
#include <random>       // default_random_engine
#include <string>
#include <iterator>     // back_inserter
#include <algorithm>    // sample

int main() {
   std::default_random_engine zufall{};
   const std::string in = "abcdefgh";
   for(auto idx : {0,1,2,3}) {
     std::string out;
     std::ranges::sample(in, std::back_inserter(out), 5, zufall);
     std::cout << out << '\n';
   }
}

Okt 23, 2024

lst-0818-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9xrP8Ehvd 
#include <algorithm>
#include <vector>
#include <iostream>
void sort_uniq(std::vector<int> &data) {
    std::ranges::sort(data);                        // sortieren
    auto to_delete = std::ranges::unique(data);     // nach hinten verschieben
    data.erase(to_delete.begin(), to_delete.end()); // tatsächlich löschen
}
int main() {
    std::vector ns{1,5,2,3,9,2,2,2,2,1,5,2,2,3,1,1,2,2,1};
    sort_uniq(ns);
    std::ranges::for_each(ns, [](auto x) {
        std::cout << x << ' '; });
    std::cout << '\n'; // Ausgabe: 1 2 3 5 9
}

Okt 23, 2024

lst-0826-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3r5E1f9YP 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
#include <ranges>
using std::vector; using std::string; using std::string_view;
using namespace std::literals; using std::find_if;
vector<string> demo_split(string_view s) {
  vector<string> result{};
  auto it = s.begin();
  while(it != s.end()) {
    // bis normales Zeichen:
    it = find_if(it, s.end(), [](char c) { return c!=' '; });
     // bis Leerzeichen:
     auto jt = find_if(it, s.end(), [](char c) { return c==' '; });
    if(it!=s.end())
      result.push_back(string(it, jt)); // Kopie ins Ergebnis
    it = jt;
  }
  return result;
}
int main() {
  auto text = "Der Text ist kurz"sv;
  auto res = demo_split(text);
  std::ranges::for_each(res, [](const string &e) {
      std::cout << "[" << e << "] "; });
  std::cout << '\n'; // Ausgabe: [Der] [Text] [ist] [kurz]
  // oder gleich mit views::split:
  for(auto word : text | std::views::split(" "sv)) {
    std::cout << "[";
    for(auto c : word) std::cout << c;
    std::cout << "] ";
  } // Ausgabe: [Der] [Text] [ist] [kurz]
}

Okt 23, 2024

lst-0831-godb.cpp

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/j9ozax8qE 
#include <ranges> // zip_transform
// 
auto res = std::views::zip_transform(f, a, b);  // Range-Adapter
for(auto s: res) { std::cout << s << " "; };
std::cout << '\n';        // Ausgabe: N1 C7 C0 -1

Okt 23, 2024

lst-0819-book.cpp

// https://godbolt.org/z/qcT9o7YfG 
#include <algorithm>  // find
#include <numeric>    // reduce, accumulate
#include <execution>  // std::execution
#include <iostream>
#include <chrono>     // Zeitmessung
using namespace std::chrono;
long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start).count();
}
template <typename FUNC> void timeit(const char* title, FUNC func) {
    auto start = steady_clock::now();
    auto ret = func(); // ausführen
    std::cout << title << ": " << millisSeit(start) << " ms" << std::endl;
}
int main() {
    using namespace std::execution;          // seq, par, par_unseq
    using std::reduce; using std::accumulate; using std::find;
    std::vector<double> v(600'000'000, 0.0); // 600 Millionen Elemente
    for(auto&x:v) x = ::rand();              // mit Zufallswerten füllen
    timeit("warmlaufen       ", [&v] {
        return reduce(seq, v.begin(), v.end(), 0.0);
    });
    timeit("accumulate       ", [&v] {
        return accumulate(v.begin(), v.end(), 0.0);
    });
    timeit("reduce, seq      ", [&v] {
        return reduce(seq, v.begin(), v.end(), 0.0);
    });
    timeit("reduce, par      ", [&v] {
        return reduce(par, v.begin(), v.end(), 0.0);
    });

    timeit("reduce, par_unseq", [&v] {
        return reduce(par_unseq, v.begin(), v.end(), 0.0);
    });
    timeit("find, seq        ", [&v] {
        return find(seq, v.begin(), v.end(), 1.1) == v.end() ? 0.0 : 1.0;
    });
    timeit("find, par        ", [&v] {
        return find(par, v.begin(), v.end(), 1.1) == v.end() ? 0.0 : 1.0;
    });
    return 0;
}

Okt 23, 2024

lst-0813-book.cpp

// https://godbolt.org/z/dd1q6GdYq 
valarray v { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
valarray<int> r1(v[slice(0, 4, 3)]); // Start bei 0, 4 Elemente, Schrittweite 3
cout <<= r1;                         // Ausgabe: 1 4 7 10
valarray<int> r2(v[v > 6]);          // adressiert per valarray<bool>
cout <<= r2;                         // Ausgabe: 7 8 9 10 11 12
const valarray<size_t> indirekt{ 2, 2, 3, 6 };  // doppelte erlaubt
valarray<int> r5(v[indirekt]);       // adressiert per valarray<size_t>
cout <<= r5;                         // Ausgabe: 3 3 4 7

Okt 23, 2024

lst-0805-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qnove9h8o 
#include <unordered_set> // unordered_multiset
#include <vector>
#include <iostream>
using std::unordered_multiset; using std::cout; using std::ostream;
template<typename Elem>
ostream& operator<<=(ostream&os, const unordered_multiset<Elem>&data) {
    for(auto &e : data) { os << e << ' '; } return os << '\n'; }
int main() {
    // ohne Argumente
    unordered_multiset<int> leer(1000); // anfängliche Größe der Hashtabelle
    cout <<= leer;      // Ausgabe:
    // Initialisierungsliste; doppelte werden übernommen:
    unordered_multiset daten{ 1,1,2,2,3,3,4,4,5,5 };
    cout <<= daten;     // Ausgabe in etwa: 5 5 4 4 3 3 2 2 1 1
    // Kopie
    unordered_multiset kopie(daten);
    cout <<= kopie;     // Ausgabe in etwa: 5 5 4 4 3 3 2 2 1 1
    // Bereich
    std::vector in{1,2,3,10,20,30,10,20,30,1,2,3};
    unordered_multiset bereich(in.begin()+3, in.end()-3);
    cout <<= bereich;   // Ausgabe in etwa: 30 30 20 20 10 10
}

Okt 23, 2024

lst-0820-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rrq1v5qPs 
std::list lst{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto take5 = rs::take_view{lst, 5};     // View via Typ
auto take6 = lst | vs::take(6);         // View via Adapter

Okt 23, 2024

lst-0783-book.cpp

// https://godbolt.org/z/54zqqhzh6 
string such7(const map<int,string> &data) {
    return data[7];            //                                                  (ERR)  non-const-Methode auf const-Parameter
}
string such5(const map<int,string> &data) {
    auto it = data.find(5);    // nicht automatisch einfügend
    return it==data.end() ? string{} : it->second;
}
// 
map<int,string> zwerge{ {1,"eins"}, {3,"drei"}, {5,"fuenf"}, {7,"sieben"} };
cout << such7(zwerge) << '\n';
cout << such5(zwerge) << '\n';  // Ausgabe: fuenf

Okt 23, 2024

lst-0786-book.cpp

// https://godbolt.org/z/9hPqa5MfY 
#include <string>
#include <iterator> // distance
#include <ranges>   // subrange
struct Person {
  std::string name;
  friend bool operator<(const Person &a, const Person &b) {  
    // nur erster Buchstabe
    return a.name.size()==0 ? true
      : (b.name.size()==0 ? false : a.name[0] < b.name[0]);
  }
};
// …
multiset data{ 1, 4,4, 2,2,2, 7, 9 };
auto [von1, bis1] = data.equal_range(2);
cout << "Anzahl 2en: "
  << std::distance(von1, bis1) << '\n'; // Ausgabe: Anzahl 2en: 3
auto [von2, bis2] = data.equal_range(5);
cout << "Anzahl 5en: "
  << std::distance(von2, bis2) << '\n'; // Ausgabe: Anzahl 5en: 0
multiset<Person> raum{
  {"Karl"}, {"Kurt"}, {"Peter"}, {"Karl"}, {"Ken"}};
auto [p, q] = raum.equal_range(Person{"K"});
for(auto& p : std::ranges::subrange(p,q)) { // C++20-Range oder einfache Schleife
  cout << p.name << ' ';
}
cout << '\n'; // Ausgabe: Karl Kurt Karl Ken

Okt 23, 2024

lst-0789-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dj68ej97r 
using namespace std::literals; // für ""s

multimap<int,string> numlang{};
numlang.insert( std::make_pair(7, "seven"s) );
numlang.insert( std::pair<int,string>(7, "sieben"s) );
numlang.emplace( 7, "yedi"s );
cout <<= numlang; // Ausgabe: 7:seven 7:sieben 7:yedi

Okt 23, 2024

lst-0784-book.cpp

// https://godbolt.org/z/PYbexWex3 
#include <set>     // multiset
#include <iostream>
using std::multiset; using std::cout;
template<typename Elem, typename Comp>
std::ostream& operator<<=(std::ostream&os, const multiset<Elem,Comp>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0798-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1s41eaWjx 
unordered_set nums{ 1,2,3,4,5,6,7,8,9,10 };
cout <<= nums;               // Ausgabe ähnlich: 9 1 2 3 4 5 6 7 8 10
auto it = nums.begin();
while(it != nums.end()) {
    if(*it % 2 == 0) {       // gerade Zahl?
        it = nums.erase(it); // Restelemente verändern nicht Reihenfolge
    } else {
        ++it;
    }
}
cout <<= nums;               // Ausgabe ähnlich: 9 1 3 5 7

Okt 23, 2024

lst-0793-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xv6vrcsY6 
#include <unordered_set>
#include <iostream>
using std::unordered_set; using std::cout; using std::ostream;
template<typename Elem, typename Cmp>
ostream& operator<<=(ostream&os, const unordered_set<Elem,Cmp>&data){
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0780-book.cpp

// https://godbolt.org/z/7h3vsWvYG 
map<string,int> zwerge;
zwerge.emplace("Fili",  2859);
cout << zwerge["Fili"] << '\n'; // Ausgabe: 2859
cout << zwerge["Dori"] << '\n'; // neu erzeugt. Ausgabe: 0
zwerge["Kili"] = 2846;          // neu erzeugt und gleich überschrieben
cout << zwerge["Kili"] << '\n'; // Ausgabe: 2846
cout <<= zwerge;                // Ausgabe: Dori:0 Fili:2859 Kili:2846

Okt 23, 2024

lst-0791-book.cpp

// https://godbolt.org/z/ejMv4ohse 
#include <set>               // set, multiset
#include <unordered_set>     // unordered_set, unordered_multiset
#include <iostream>
#include <string>
#include <chrono>            // Zeitmessung
using std::cout;
using namespace std::chrono;

long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start).count();
}
constexpr size_t ITERATIONS = 100'000;
template<typename Cont, typename Gen>
    requires std::invocable<Gen, size_t> &&  // C++20-Concept
    requires(Gen gen, size_t n) {{gen(n)} -> std::same_as<int>;} &&
    std::same_as<typename Cont::value_type,int>
void timeStuff(std::string name, Cont data, Gen genNum) {
    cout << name << "...";
    auto start = steady_clock::now();
    for(size_t idx=0; idx<ITERATIONS; ++idx) {
        data.insert( genNum(idx) );
    }
    cout << " " << millisSeit(start) << " ms" << std::endl;
}
int alleGleich(size_t) { return 7; }      // erzeugt immer die gleiche Zahl
int gestreut(size_t n) { return int(n); } // erzeugt unterschiedliche Zahlen
struct BadHash {  // die schlechtestmögliche Hashfunktion als Funktor
       size_t   operator()(int) const { return 1uz; }
};

int main() {
   std::multiset<int> m{};
   timeStuff("multiset           alleGleich        ", m, &alleGleich);
   timeStuff("multiset           gestreut          ", m, &gestreut);
   std::set<int> s{};
   timeStuff("set                alleGleich        ", s, &alleGleich);
   timeStuff("set                gestreut          ", s, &gestreut);
   std::unordered_multiset<int> um{};
   timeStuff("unordered_multiset alleGleich        ", um, &alleGleich);
   timeStuff("unordered_multiset gestreut          ", um, &gestreut);
   std::unordered_multiset<int,BadHash> umb{};
   timeStuff("unordered_multiset alleGleich badHash", umb, &alleGleich);
   timeStuff("unordered_multiset gestreut   badHash", umb, &gestreut);
}

Okt 23, 2024

lst-0799-book.cpp

// https://godbolt.org/z/TTbY8YbG9 
// Befüllen mit 100 Werten
unordered_set<int> d{};
d.rehash(10);             // versuche, 10 Eimer zu haben
d.max_load_factor(100.0); // 100 Elemente pro Eimer sind okay
cout << "Eimer Anzahl: " << d.bucket_count() << '\n';
for(int x : std::ranges::iota_view{0,100}) { // C++20 iota(): 0,1,2,,99
    d.insert(x);
}
// ausgeben
for(int b = d.bucket_count()-1; b>=0; --b) {
    cout << "Eimer "<<b<<":";
    for(auto it=d.begin(b); it!=d.end(b); ++it)
        cout << *it << ' ';
    cout << '\n';
}

Okt 23, 2024

lst-0796-book.cpp

// https://godbolt.org/z/WeMr9ePdh 
#include <set>
template<typename Key>
std::set<Key> sorted(const unordered_set<Key> &data)
  { return std::set<Key>(data.begin(), data.end()); }
// …
// ohne Argumente
unordered_set<int> leer{};
cout <<= leer;      // Ausgabe:
// Initialisierungsliste
unordered_set daten{1,1,2,2,3,3,4,4,5,5};// doppelte werden nicht übernommen
cout <<= daten;     // Ausgabe in etwa: 5 4 3 2 1
// Kopie
unordered_set kopie(daten);
cout <<= kopie;     // Ausgabe in etwa: 5 4 3 2 1
// Bereich
auto so1 = sorted(daten);
unordered_set bereich(std::next(so1.begin()), std::prev(so1.end()));
cout <<= bereich;   // Ausgabe in etwa: 2 3 4

Okt 23, 2024

lst-0796-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WeMr9ePdh 
#include <set>
template<typename Key>
std::set<Key> sorted(const unordered_set<Key> &data)
  { return std::set<Key>(data.begin(), data.end()); }
// 
// ohne Argumente
unordered_set<int> leer{};
cout <<= leer;      // Ausgabe:
// Initialisierungsliste
unordered_set daten{1,1,2,2,3,3,4,4,5,5};// doppelte werden nicht übernommen
cout <<= daten;     // Ausgabe in etwa: 5 4 3 2 1
// Kopie
unordered_set kopie(daten);
cout <<= kopie;     // Ausgabe in etwa: 5 4 3 2 1
// Bereich
auto so1 = sorted(daten);
unordered_set bereich(std::next(so1.begin()), std::prev(so1.end()));
cout <<= bereich;   // Ausgabe in etwa: 2 3 4

Okt 23, 2024

lst-0788-book.cpp

// https://godbolt.org/z/6no9dW64d 
multimap int2int{ std::make_pair(3,4) };  // multimap<int,int>
using namespace std::literals; // für ""s
multimap<int,string> numlang{
    {7,"sieben"s}, {6,"six"s},
    {7,"siete"s}, {6,"sechs"s},
    {7,"seven"s}, {7,"yedi"s},
    {8,"eight"s} };
cout <<= numlang; // Ausgabe: 6:six 6:sechs 7:sieben 7:siete 7:seven 7:yedi 8:eight

Okt 23, 2024

lst-0800-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ffashhsK1 
#include <unordered_map>
#include <iostream>
using std::unordered_map; using std::cout;
template<typename K, typename T>
std::ostream& operator<<=(std::ostream&os, const unordered_map<K,T>&data) {
    for(auto &e : data) {
        os << e.first << ":" << e.second << ' ';
    }
    return os << '\n'; // bei operator<<= mit Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0800-book.cpp

// https://godbolt.org/z/ffashhsK1 
#include <unordered_map>
#include <iostream>
using std::unordered_map; using std::cout;
template<typename K, typename T>
std::ostream& operator<<=(std::ostream&os, const unordered_map<K,T>&data) {
    for(auto &e : data) {
        os << e.first << ":" << e.second << ' ';
    }
    return os << '\n'; // bei operator<<= mit Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0779-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bzvrPefvY 
map<int,string> plz2ort;
plz2ort.insert(std::make_pair(53227, "Bonn"));
plz2ort.emplace(50667, "Koeln");
cout <<= plz2ort;                    // Ausgabe: 50667:Koeln 53227:Bonn
map<string,int> ort2plz;
ort2plz.emplace("Koeln", 50667);
ort2plz.emplace("Koeln", 51063);     // überschreibt nicht
cout <<= ort2plz;                    // Ausgabe: Koeln:50667

Okt 23, 2024

lst-0799-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TTbY8YbG9 
// Befüllen mit 100 Werten
unordered_set<int> d{};
d.rehash(10);             // versuche, 10 Eimer zu haben
d.max_load_factor(100.0); // 100 Elemente pro Eimer sind okay
cout << "Eimer Anzahl: " << d.bucket_count() << '\n';
for(int x : std::ranges::iota_view{0,100}) { // C++20 iota(): 0,1,2,,99
    d.insert(x);
}
// ausgeben
for(int b = d.bucket_count()-1; b>=0; --b) {
    cout << "Eimer "<<b<<":";
    for(auto it=d.begin(b); it!=d.end(b); ++it)
        cout << *it << ' ';
    cout << '\n';
}

Okt 23, 2024

lst-0782-book.cpp

// https://godbolt.org/z/16T5dob75 
map<char,int> data { { 'a',1}, {'b',2}, {'c',3} };
for(auto it=data.rbegin(); it!=data.rend(); ++it) {  // rückwärts
    cout << it->first << ':' << it->second << ' ';   // mit -> dereferenzieren
}
cout << '\n'; // Ausgabe: c:3 b:2 a:1
for(auto &e : data) {                          // vorwärts, nimmt begin() und end()
    cout << e.first << ':' << e.second << ' '; // Paar, Elementzugriff mit .
}
cout << '\n'; // Ausgabe: a:1 b:2 c:3

Okt 23, 2024

lst-0789-book.cpp

// https://godbolt.org/z/dj68ej97r 
using namespace std::literals; // für ""s

multimap<int,string> numlang{};
numlang.insert( std::make_pair(7, "seven"s) );
numlang.insert( std::pair<int,string>(7, "sieben"s) );
numlang.emplace( 7, "yedi"s );
cout <<= numlang; // Ausgabe: 7:seven 7:sieben 7:yedi

Okt 23, 2024

lst-0780-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7h3vsWvYG 
map<string,int> zwerge;
zwerge.emplace("Fili",  2859);
cout << zwerge["Fili"] << '\n'; // Ausgabe: 2859
cout << zwerge["Dori"] << '\n'; // neu erzeugt. Ausgabe: 0
zwerge["Kili"] = 2846;          // neu erzeugt und gleich überschrieben
cout << zwerge["Kili"] << '\n'; // Ausgabe: 2846
cout <<= zwerge;                // Ausgabe: Dori:0 Fili:2859 Kili:2846

Okt 23, 2024

lst-0786-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9hPqa5MfY 
#include <string>
#include <iterator> // distance
#include <ranges>   // subrange
struct Person {
  std::string name;
  friend bool operator<(const Person &a, const Person &b) {  
    // nur erster Buchstabe
    return a.name.size()==0 ? true
      : (b.name.size()==0 ? false : a.name[0] < b.name[0]);
  }
};
// 
multiset data{ 1, 4,4, 2,2,2, 7, 9 };
auto [von1, bis1] = data.equal_range(2);
cout << "Anzahl 2en: "
  << std::distance(von1, bis1) << '\n'; // Ausgabe: Anzahl 2en: 3
auto [von2, bis2] = data.equal_range(5);
cout << "Anzahl 5en: "
  << std::distance(von2, bis2) << '\n'; // Ausgabe: Anzahl 5en: 0
multiset<Person> raum{
  {"Karl"}, {"Kurt"}, {"Peter"}, {"Karl"}, {"Ken"}};
auto [p, q] = raum.equal_range(Person{"K"});
for(auto& p : std::ranges::subrange(p,q)) { // C++20-Range oder einfache Schleife
  cout << p.name << ' ';
}
cout << '\n'; // Ausgabe: Karl Kurt Karl Ken

Okt 23, 2024

lst-0785-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mej9GjT1j 
#include <vector>
// 
multiset msinit{1,2,2,3,1};                   // sortiert bei Initialisierung
cout <<= msinit; // Ausgabe: 1 1 2 2 3
std::vector in{ 7,7,7,7,7,7,7 };
std::set srange( in.begin(), in.end() );      // set entfernt doppelte
cout << srange.size() << ": " << *srange.begin() << '\n'; // Ausgabe: 1: 7
multiset msrange( in.begin(), in.end() );      // multiset erhält doppelte
cout <<= msrange; // Ausgabe: 7 7 7 7 7 7 7

Okt 23, 2024

lst-0790-book.cpp

// https://godbolt.org/z/TbvKTn4Px 
multimap<char,int> vals{ {'c',1}, {'c',8}, {'g',1},
    {'c',1}, {'a',7}, {'a',1}, {'c',2}, };
cout <<= vals;            // Ausgabe: a:7 a:1 c:1 c:8 c:1 c:2 g:1
vals.erase( 'c' );        // löscht alle 'c's
cout <<= vals;            // Ausgabe: a:7 a:1 g:1
vals.erase(vals.begin()); // löscht nur eines der 'a's
cout <<= vals;            // Ausgabe: a:1 g:1

Okt 23, 2024

lst-0782-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/16T5dob75 
map<char,int> data { { 'a',1}, {'b',2}, {'c',3} };
for(auto it=data.rbegin(); it!=data.rend(); ++it) {  // rückwärts
    cout << it->first << ':' << it->second << ' ';   // mit -> dereferenzieren
}
cout << '\n'; // Ausgabe: c:3 b:2 a:1
for(auto &e : data) {                          // vorwärts, nimmt begin() und end()
    cout << e.first << ':' << e.second << ' '; // Paar, Elementzugriff mit .
}
cout << '\n'; // Ausgabe: a:1 b:2 c:3

Okt 23, 2024

lst-0791-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ejMv4ohse 
#include <set>               // set, multiset
#include <unordered_set>     // unordered_set, unordered_multiset
#include <iostream>
#include <string>
#include <chrono>            // Zeitmessung
using std::cout;
using namespace std::chrono;

long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start).count();
}
constexpr size_t ITERATIONS = 100'000;
template<typename Cont, typename Gen>
    requires std::invocable<Gen, size_t> &&  // C++20-Concept
    requires(Gen gen, size_t n) {{gen(n)} -> std::same_as<int>;} &&
    std::same_as<typename Cont::value_type,int>
void timeStuff(std::string name, Cont data, Gen genNum) {
    cout << name << "...";
    auto start = steady_clock::now();
    for(size_t idx=0; idx<ITERATIONS; ++idx) {
        data.insert( genNum(idx) );
    }
    cout << " " << millisSeit(start) << " ms" << std::endl;
}
int alleGleich(size_t) { return 7; }      // erzeugt immer die gleiche Zahl
int gestreut(size_t n) { return int(n); } // erzeugt unterschiedliche Zahlen
struct BadHash {  // die schlechtestmögliche Hashfunktion als Funktor
       size_t   operator()(int) const { return 1uz; }
};

int main() {
   std::multiset<int> m{};
   timeStuff("multiset           alleGleich        ", m, &alleGleich);
   timeStuff("multiset           gestreut          ", m, &gestreut);
   std::set<int> s{};
   timeStuff("set                alleGleich        ", s, &alleGleich);
   timeStuff("set                gestreut          ", s, &gestreut);
   std::unordered_multiset<int> um{};
   timeStuff("unordered_multiset alleGleich        ", um, &alleGleich);
   timeStuff("unordered_multiset gestreut          ", um, &gestreut);
   std::unordered_multiset<int,BadHash> umb{};
   timeStuff("unordered_multiset alleGleich badHash", umb, &alleGleich);
   timeStuff("unordered_multiset gestreut   badHash", umb, &gestreut);
}

Okt 23, 2024

lst-0797-book.cpp

// https://godbolt.org/z/KEb55ds4z 
unordered_set<int> data;
auto res1 = data.insert( 5 );                  // Einfügen per Kopie
if(res1.second) cout << "ja, 5 nun drin\n";    // das klappt
auto res2 = data.emplace( 5 );                 // Einfügen vor Ort
if(res2.second) cout << "zweite 5 nun drin\n"; // das klappt nicht
auto res3 = data.insert(res1.first, 6 );       // mit Positionshinweis
// res3 ist nur ein iterator ohne bool
cout << *res3 << '\n';                         // auf jeden Fall eine 6

Okt 23, 2024

lst-0794-book.cpp

// https://godbolt.org/z/MWrY1cznd 
#include <unordered_set>
#include <iostream>
#include <vector>
#include <string>
using std::string; using std::unordered_set; using std::cout;
struct Word {
    string word_;
    size_t row_;
    Word(const string &word, size_t row)
        : word_{word}, row_{row} {}
    friend bool operator==(const Word& a, const Word &b)
        { return a.word_ == b.word_; } // ignoriert row
 };
 namespace std {
 template<> struct hash<Word> { // ignoriert row
        std::hash<string> stringHash;
        std::size_t operator()(const Word &w) const {
            return stringHash(w.word_);
        }
 }; }
 struct ExactWordHash { // bezieht row mit ein
     std::hash<string> sHash;
     std::hash<size_t> iHash;
     bool operator()(const Word& a) const {
         return sHash(a.word_) ^ iHash(a.row_);
     }
 };
 struct ExactWordEqual { // bezieht row mit ein
     bool operator()(const Word& a, const Word &b) const {
         return std::tie(a.word_, a.row_) == std::tie(b.word_, b.row_);
     }
 };
 int main() {
     std::vector input {
       Word{"eine",0}, Word{"Rose",0},
       Word{"ist",1}, Word{"eine",1}, Word{"Rose",1},
       Word{"ist",2}, Word{"eine",2}, Word{"Rose",2},  };
     // Überladungen nutzen
     unordered_set<Word> words( input.begin(), input.end() );
     cout << words.size() << '\n'; // Ausgabe: 3
     // Eigene Funktoren nutzen
     unordered_set<Word,ExactWordHash,ExactWordEqual> poem(
          input.begin(), input.end() );
     cout << poem.size() << '\n';  // Ausgabe: 8
     // Hash als Lambda
     auto h = [](const auto &a) { return std::hash<string>{}(a.word_); };
     unordered_set<Word,decltype(h)> rose(input.begin(), input.end(), 10, h);
     cout << rose.size() << '\n';  // Ausgabe: 3
 }

Okt 23, 2024

lst-0802-book.cpp

// https://godbolt.org/z/eTYqbedqK 
#include <unordered_set> // unordered_multiset
#include <iostream>
#include <string>
using std::string; using std::unordered_multiset; using std::cout;
struct Stadt {
    string name_;
    explicit Stadt(const string &name) : name_{name} {}
    auto operator<=>(const Stadt &b) const = default;
 };
 struct Eintrag { string stadt_; int plz_; };
 struct EqEintrag {
     bool operator()(const Eintrag&a, const Eintrag&b) const {
         return a.stadt_==b.stadt_;
     }
 };
 struct HashEintrag {
     std::hash<string> sHash;
     size_t operator()(const Eintrag& a) const {
         return sHash(a.stadt_);
     }
 };
 int main() {
     unordered_multiset<Eintrag,HashEintrag,EqEintrag> verzeichnis{
         {Eintrag{"Bielefeld", 33615}},
         {Eintrag{"Bielefeld", 33617}},
         {Eintrag{"Bielefeld", 33621}},
         {Eintrag{"Berlin", 10032}},
         {Eintrag{"Berlin", 10027}},
         };
     const Eintrag such{"Bielefeld", 0}; // plz spielt bei Suche keine Rolle
     cout<<"Bielefeld hat "<<verzeichnis.count(such)<<" Postleitzahlen.\n";
     cout<<"Die Postleitzahlen von Bielefeld sind:\n";
     auto [wo, bis] = verzeichnis.equal_range(such);
     while(wo != bis) {
         cout << "  " << wo->plz_ << '\n';
         ++wo;
     }
 }

Okt 23, 2024

lst-0798-book.cpp

// https://godbolt.org/z/1s41eaWjx 
unordered_set nums{ 1,2,3,4,5,6,7,8,9,10 };
cout <<= nums;               // Ausgabe ähnlich: 9 1 2 3 4 5 6 7 8 10
auto it = nums.begin();
while(it != nums.end()) {
    if(*it % 2 == 0) {       // gerade Zahl?
        it = nums.erase(it); // Restelemente verändern nicht Reihenfolge
    } else {
        ++it;
    }
}
cout <<= nums;               // Ausgabe ähnlich: 9 1 3 5 7

Okt 23, 2024

lst-0797-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KEb55ds4z 
unordered_set<int> data;
auto res1 = data.insert( 5 );                  // Einfügen per Kopie
if(res1.second) cout << "ja, 5 nun drin\n";    // das klappt
auto res2 = data.emplace( 5 );                 // Einfügen vor Ort
if(res2.second) cout << "zweite 5 nun drin\n"; // das klappt nicht
auto res3 = data.insert(res1.first, 6 );       // mit Positionshinweis
// res3 ist nur ein iterator ohne bool
cout << *res3 << '\n';                         // auf jeden Fall eine 6

Okt 23, 2024

lst-0801-book.cpp

// https://godbolt.org/z/Ka3czrn54 
#include <unordered_map>
#include <iostream>
#include <string>
using std::string; using std::unordered_map; using std::cout;
struct Stadt {
    string name_;
    explicit Stadt(const string &name) : name_{name} {}
    auto operator<=>(const Stadt &b) const = default;
 };
 struct StadtHash {
     std::hash<string> sHash;
     size_t operator()(const Stadt& a) const {
         return sHash(a.name_);
     }
 };
 int main() {
     unordered_map<Stadt,string,StadtHash> abk{
         {Stadt{"Bielefeld"}, "BI"},
         {Stadt{"Jetzendorf"}, "JE"},
         {Stadt{"Tharandt"}, "TH"},
         };
     cout << abk[Stadt{"Bielefeld"}] << '\n'; // Ausgabe: BI
 }

Okt 23, 2024

lst-0804-book.cpp

// https://godbolt.org/z/9szMGYK9v 
struct EqEintrag {
    bool operator()(const Eintrag&a, const Eintrag&b) const {
        return a.stadt_==b.stadt_;
    }
};

struct HashEintrag {
    std::hash<string> sHash;
    std::hash<int> iHash;
    size_t operator()(const Eintrag& a) const {
        return sHash(a.stadt_) ^ iHash(a.plz_); //                                          (ERR)  zu viele Elemente
    }
};

Okt 23, 2024

lst-0794-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MWrY1cznd 
#include <unordered_set>
#include <iostream>
#include <vector>
#include <string>
using std::string; using std::unordered_set; using std::cout;
struct Word {
    string word_;
    size_t row_;
    Word(const string &word, size_t row)
        : word_{word}, row_{row} {}
    friend bool operator==(const Word& a, const Word &b)
        { return a.word_ == b.word_; } // ignoriert row
 };
 namespace std {
 template<> struct hash<Word> { // ignoriert row
        std::hash<string> stringHash;
        std::size_t operator()(const Word &w) const {
            return stringHash(w.word_);
        }
 }; }
 struct ExactWordHash { // bezieht row mit ein
     std::hash<string> sHash;
     std::hash<size_t> iHash;
     bool operator()(const Word& a) const {
         return sHash(a.word_) ^ iHash(a.row_);
     }
 };
 struct ExactWordEqual { // bezieht row mit ein
     bool operator()(const Word& a, const Word &b) const {
         return std::tie(a.word_, a.row_) == std::tie(b.word_, b.row_);
     }
 };
 int main() {
     std::vector input {
       Word{"eine",0}, Word{"Rose",0},
       Word{"ist",1}, Word{"eine",1}, Word{"Rose",1},
       Word{"ist",2}, Word{"eine",2}, Word{"Rose",2},  };
     // Überladungen nutzen
     unordered_set<Word> words( input.begin(), input.end() );
     cout << words.size() << '\n'; // Ausgabe: 3
     // Eigene Funktoren nutzen
     unordered_set<Word,ExactWordHash,ExactWordEqual> poem(
          input.begin(), input.end() );
     cout << poem.size() << '\n';  // Ausgabe: 8
     // Hash als Lambda
     auto h = [](const auto &a) { return std::hash<string>{}(a.word_); };
     unordered_set<Word,decltype(h)> rose(input.begin(), input.end(), 10, h);
     cout << rose.size() << '\n';  // Ausgabe: 3
 }

Okt 23, 2024

lst-0781-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7E6cr8GE9 
map<string,string> data { {"Hans","Albers"}, {"Heinz","Ruehmann" }, };
cout <<= data;                         // Hans:Albers Heinz:Ruehmann
data.rbegin()->second = "Erhardt";     // Ziel überschreiben
cout <<= data;                         // Hans:Albers Heinz:Erhardt

Okt 23, 2024

lst-0781-book.cpp

// https://godbolt.org/z/7E6cr8GE9 
map<string,string> data { {"Hans","Albers"}, {"Heinz","Ruehmann" }, };
cout <<= data;                         // Hans:Albers Heinz:Ruehmann
data.rbegin()->second = "Erhardt";     // Ziel überschreiben
cout <<= data;                         // Hans:Albers Heinz:Erhardt

Okt 23, 2024

lst-0804-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9szMGYK9v 
struct EqEintrag {
    bool operator()(const Eintrag&a, const Eintrag&b) const {
        return a.stadt_==b.stadt_;
    }
};

struct HashEintrag {
    std::hash<string> sHash;
    std::hash<int> iHash;
    size_t operator()(const Eintrag& a) const {
        return sHash(a.stadt_) ^ iHash(a.plz_); //                                          (ERR)  zu viele Elemente
    }
};

Okt 23, 2024

lst-0783-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/54zqqhzh6 
string such7(const map<int,string> &data) {
    return data[7];            //                                                  (ERR)  non-const-Methode auf const-Parameter
}
string such5(const map<int,string> &data) {
    auto it = data.find(5);    // nicht automatisch einfügend
    return it==data.end() ? string{} : it->second;
}
// 
map<int,string> zwerge{ {1,"eins"}, {3,"drei"}, {5,"fuenf"}, {7,"sieben"} };
cout << such7(zwerge) << '\n';
cout << such5(zwerge) << '\n';  // Ausgabe: fuenf

Okt 23, 2024

lst-0801-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ka3czrn54 
#include <unordered_map>
#include <iostream>
#include <string>
using std::string; using std::unordered_map; using std::cout;
struct Stadt {
    string name_;
    explicit Stadt(const string &name) : name_{name} {}
    auto operator<=>(const Stadt &b) const = default;
 };
 struct StadtHash {
     std::hash<string> sHash;
     size_t operator()(const Stadt& a) const {
         return sHash(a.name_);
     }
 };
 int main() {
     unordered_map<Stadt,string,StadtHash> abk{
         {Stadt{"Bielefeld"}, "BI"},
         {Stadt{"Jetzendorf"}, "JE"},
         {Stadt{"Tharandt"}, "TH"},
         };
     cout << abk[Stadt{"Bielefeld"}] << '\n'; // Ausgabe: BI
 }

Okt 23, 2024

lst-0792-book.cpp

// https://godbolt.org/z/osdTM7vbx 
#include <unordered_set>     // unordered_set, unordered_multiset
#include <iostream>
#include <string>
#include <chrono>            // Zeitmessung
using std::cout;
using namespace std::chrono;
long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start)
        .count();
}
struct BadHash {  // die schlechtestmögliche Hashfunktion als Funktor
    size_t   operator()(int) const { return 1uz; }
};
void timeStuff(size_t iters) {
    std::unordered_multiset<int,BadHash> data{};
    cout << iters << "...";
    auto start = steady_clock::now();
    for(size_t idx=0; idx<iters; ++idx) {
        data.insert( (int)idx );
    }
    cout << " " << millisSeit(start) << " ms" << std::endl;
}
constexpr size_t LIMIT = 20'000;
int main() {
    size_t iters = 100;
    while(iters < LIMIT) {
        timeStuff(iters);
        iters *= 2; // verdoppeln
    }
}

Okt 23, 2024

lst-0792-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/osdTM7vbx 
#include <unordered_set>     // unordered_set, unordered_multiset
#include <iostream>
#include <string>
#include <chrono>            // Zeitmessung
using std::cout;
using namespace std::chrono;
long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start)
        .count();
}
struct BadHash {  // die schlechtestmögliche Hashfunktion als Funktor
    size_t   operator()(int) const { return 1uz; }
};
void timeStuff(size_t iters) {
    std::unordered_multiset<int,BadHash> data{};
    cout << iters << "...";
    auto start = steady_clock::now();
    for(size_t idx=0; idx<iters; ++idx) {
        data.insert( (int)idx );
    }
    cout << " " << millisSeit(start) << " ms" << std::endl;
}
constexpr size_t LIMIT = 20'000;
int main() {
    size_t iters = 100;
    while(iters < LIMIT) {
        timeStuff(iters);
        iters *= 2; // verdoppeln
    }
}

Okt 23, 2024

lst-0779-book.cpp

// https://godbolt.org/z/bzvrPefvY 
map<int,string> plz2ort;
plz2ort.insert(std::make_pair(53227, "Bonn"));
plz2ort.emplace(50667, "Koeln");
cout <<= plz2ort;                    // Ausgabe: 50667:Koeln 53227:Bonn
map<string,int> ort2plz;
ort2plz.emplace("Koeln", 50667);
ort2plz.emplace("Koeln", 51063);     // überschreibt nicht
cout <<= ort2plz;                    // Ausgabe: Koeln:50667

Okt 23, 2024

lst-0802-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eTYqbedqK 
#include <unordered_set> // unordered_multiset
#include <iostream>
#include <string>
using std::string; using std::unordered_multiset; using std::cout;
struct Stadt {
    string name_;
    explicit Stadt(const string &name) : name_{name} {}
    auto operator<=>(const Stadt &b) const = default;
 };
 struct Eintrag { string stadt_; int plz_; };
 struct EqEintrag {
     bool operator()(const Eintrag&a, const Eintrag&b) const {
         return a.stadt_==b.stadt_;
     }
 };
 struct HashEintrag {
     std::hash<string> sHash;
     size_t operator()(const Eintrag& a) const {
         return sHash(a.stadt_);
     }
 };
 int main() {
     unordered_multiset<Eintrag,HashEintrag,EqEintrag> verzeichnis{
         {Eintrag{"Bielefeld", 33615}},
         {Eintrag{"Bielefeld", 33617}},
         {Eintrag{"Bielefeld", 33621}},
         {Eintrag{"Berlin", 10032}},
         {Eintrag{"Berlin", 10027}},
         };
     const Eintrag such{"Bielefeld", 0}; // plz spielt bei Suche keine Rolle
     cout<<"Bielefeld hat "<<verzeichnis.count(such)<<" Postleitzahlen.\n";
     cout<<"Die Postleitzahlen von Bielefeld sind:\n";
     auto [wo, bis] = verzeichnis.equal_range(such);
     while(wo != bis) {
         cout << "  " << wo->plz_ << '\n';
         ++wo;
     }
 }

Okt 23, 2024

lst-0785-book.cpp

// https://godbolt.org/z/Mej9GjT1j 
#include <vector>
// …
multiset msinit{1,2,2,3,1};                   // sortiert bei Initialisierung
cout <<= msinit; // Ausgabe: 1 1 2 2 3
std::vector in{ 7,7,7,7,7,7,7 };
std::set srange( in.begin(), in.end() );      // set entfernt doppelte
cout << srange.size() << ": " << *srange.begin() << '\n'; // Ausgabe: 1: 7
multiset msrange( in.begin(), in.end() );      // multiset erhält doppelte
cout <<= msrange; // Ausgabe: 7 7 7 7 7 7 7

Okt 23, 2024

lst-0787-book.cpp

// https://godbolt.org/z/sfaEozjzq 
#include <map>        // die Hauptsache
#include <iostream>   // zur Ausgabe
#include <string>     // gerne mal Schlüssel oder Ziel
using std::multimap; using std::cout; using std::string;
template<typename Key, typename Trg, typename Cmp>
std::ostream& operator<<=(std::ostream&os, const multimap<Key,Trg,Cmp>&data){
    for(auto &e : data) {
        os << e.first << ":" << e.second << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0805-book.cpp

// https://godbolt.org/z/qnove9h8o 
#include <unordered_set> // unordered_multiset
#include <vector>
#include <iostream>
using std::unordered_multiset; using std::cout; using std::ostream;
template<typename Elem>
ostream& operator<<=(ostream&os, const unordered_multiset<Elem>&data) {
    for(auto &e : data) { os << e << ' '; } return os << '\n'; }
int main() {
    // ohne Argumente
    unordered_multiset<int> leer(1000); // anfängliche Größe der Hashtabelle
    cout <<= leer;      // Ausgabe:
    // Initialisierungsliste; doppelte werden übernommen:
    unordered_multiset daten{ 1,1,2,2,3,3,4,4,5,5 };
    cout <<= daten;     // Ausgabe in etwa: 5 5 4 4 3 3 2 2 1 1
    // Kopie
    unordered_multiset kopie(daten);
    cout <<= kopie;     // Ausgabe in etwa: 5 5 4 4 3 3 2 2 1 1
    // Bereich
    std::vector in{1,2,3,10,20,30,10,20,30,1,2,3};
    unordered_multiset bereich(in.begin()+3, in.end()-3);
    cout <<= bereich;   // Ausgabe in etwa: 30 30 20 20 10 10
}

Okt 23, 2024

lst-0788-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6no9dW64d 
multimap int2int{ std::make_pair(3,4) };  // multimap<int,int>
using namespace std::literals; // für ""s
multimap<int,string> numlang{
    {7,"sieben"s}, {6,"six"s},
    {7,"siete"s}, {6,"sechs"s},
    {7,"seven"s}, {7,"yedi"s},
    {8,"eight"s} };
cout <<= numlang; // Ausgabe: 6:six 6:sechs 7:sieben 7:siete 7:seven 7:yedi 8:eight

Okt 23, 2024

lst-0784-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PYbexWex3 
#include <set>     // multiset
#include <iostream>
using std::multiset; using std::cout;
template<typename Elem, typename Comp>
std::ostream& operator<<=(std::ostream&os, const multiset<Elem,Comp>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0787-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sfaEozjzq 
#include <map>        // die Hauptsache
#include <iostream>   // zur Ausgabe
#include <string>     // gerne mal Schlüssel oder Ziel
using std::multimap; using std::cout; using std::string;
template<typename Key, typename Trg, typename Cmp>
std::ostream& operator<<=(std::ostream&os, const multimap<Key,Trg,Cmp>&data){
    for(auto &e : data) {
        os << e.first << ":" << e.second << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0793-book.cpp

// https://godbolt.org/z/xv6vrcsY6 
#include <unordered_set>
#include <iostream>
using std::unordered_set; using std::cout; using std::ostream;
template<typename Elem, typename Cmp>
ostream& operator<<=(ostream&os, const unordered_set<Elem,Cmp>&data){
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0790-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TbvKTn4Px 
multimap<char,int> vals{ {'c',1}, {'c',8}, {'g',1},
    {'c',1}, {'a',7}, {'a',1}, {'c',2}, };
cout <<= vals;            // Ausgabe: a:7 a:1 c:1 c:8 c:1 c:2 g:1
vals.erase( 'c' );        // löscht alle 'c's
cout <<= vals;            // Ausgabe: a:7 a:1 g:1
vals.erase(vals.begin()); // löscht nur eines der 'a's
cout <<= vals;            // Ausgabe: a:1 g:1

Okt 23, 2024

lst-0763-book.cpp

// https://godbolt.org/z/1dTPEd3nP 
set quelle{1,2,3,4,5};
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
set ziel( std::move(quelle) ); // verschieben statt kopieren
cout <<= quelle;           // Ausgabe:
cout <<= ziel;             // Ausgabe: 1 2 3 4 5

Okt 23, 2024

lst-0776-book.cpp

// https://godbolt.org/z/nfs15n1Mn 
#include <cstdio> // toupper, tolower
// …
auto comp = [](char a, char b) { return toupper(a) < toupper(b); };
map<char,int,decltype(comp)> lets(comp); // als Templateparameter und Argument
lets['a'] = 1;
lets['B'] = 2;
lets['c'] = 3;
lets['A'] = 4; // überschreibt Position 'a'
cout <<= lets; // Ausgabe: a:4 B:2 c:3
struct Comp {  // Funktor
    bool operator()(char a, char b) const { return toupper(a) < toupper(b); }
};
map<char,int,Comp> lets2; // hier reicht der Templateparameter

Okt 23, 2024

lst-0778-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/79xx8ddoY 
using std::pair; using std::make_pair;
namespace literal_p { // benutzerdefinierte Literale besser in Namespace packen
constexpr pair<char,char> operator "" _p(const char* s, size_t len) {
    return len>=2 ?make_pair(s[0], s[1]) : make_pair( '-', '-' );
} }
struct Q {
    char a_; int n_;
    Q(char a, int n) : a_{a}, n_{n} {}
    operator pair<const char,int>() { return make_pair(a_, n_); }
};
// 
// explizite Paare:
map<int,int> nums { pair<int,int>(3,4), make_pair(7,8), make_pair(11,23) };
map nums2 { pair<int,int>(6,1), make_pair(5,2) };
// implizite Paare aus Initialisierungslisten:
map<int,char> numch{{1,'a'},{2,'b'},{3,'c'}};
map<int,int> nums3 { {7,2}, {9,4} };
using namespace literal_p;
map<char,char> pmap { "ab"_p, "cd"_p, "ef"_p }; // Umweg über eigenes Literal
cout <<= pmap;                                  // Ausgabe: a:b c:d e:f
map<char,int> qmap{Q('a',1),Q('b',2),Q('c',3)}; // implizite Umwandlungen
cout <<= qmap;                                  // Ausgabe: a:1 b:2 c:3

Okt 23, 2024

lst-0762-book.cpp

// https://godbolt.org/z/56rb9qfed 
// ohne Argumente
set<int> leer{};
cout <<= leer;           // Ausgabe:
// Initialisierungsliste
set liste{ 1,1,2,2,3,3,4,4,5,5 };  // set übernimmt keine Doppelten
cout <<= liste;          // Ausgabe: 1 2 3 4 5
// Kopie
set copy(liste);
cout <<= copy;           // Ausgabe: 1 2 3 4 5
// Iteratorpaar
set from_to( std::next(liste.begin()), std::prev(liste.end()));
cout <<= from_to;        // Ausgabe: 2 3 4
// Range
set gerade(from_range, liste | vs::filter([](int i){ return i%2; }));
cout <<= from_to;        // Ausgabe: 2 4

Okt 23, 2024

lst-0752-book.cpp

// https://godbolt.org/z/9b9fY4Mve 
#include <iostream>
#include <forward_list>
int main()     {
    std::forward_list mylist = {20, 30, 40, 50};
    mylist.insert_after(mylist.before_begin(), 11 );
    for (int& x: mylist) std::cout << ' ' << x; // Ausgabe: 11 20 30 40 50
    std::cout << '\n';
}

Okt 23, 2024

lst-0755-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h51oT7r3h 
#include <set>
#include <iostream>
using std::set; using std::cout;
template<typename Elem, typename Comp>
std::ostream& operator<<=(std::ostream&os, const set<Elem,Comp>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0766-book.cpp

// https://godbolt.org/z/PjEKKben4 
// 
template<typename IT> ostream& operator<<(ostream& os,const pair<IT,bool> wo)
  { return os << (wo.second ? "ja" : "nein"); }
struct Punkt {
    double x_, y_;
    Punkt(double x, double y) : x_{x}, y_{y} {}
    auto operator<=>(const Punkt&) const = default;
    friend ostream& operator<<(ostream &os, const Punkt &a) {
        return os << "(" << a.x_ << ',' << a.y_<< ")";
    }
};
int main() {
    set data{ 10, 20, 30, 40, 50, 60, 70 };
    auto wo = data.insert(35);         // fügt zwischen 30 und 40 ein
    cout << "neu? " << wo << '\n';     // Ausgabe: neu? ja
    wo = data.insert(40);              // gibt es schon, fügt also nicht ein
    cout << "neu? " << wo << '\n';     // Ausgabe: neu? nein
    set<Punkt> punkte{};
    punkte.insert( Punkt{3.50,7.25} ); // temporärer Wert
    punkte.emplace(1.25, 2.00);        // Konstruktorargumente
    cout <<= punkte;                   // Ausgabe: (1.25,2) (3.5,7.25)
}

Okt 23, 2024

lst-0762-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/56rb9qfed 
// ohne Argumente
set<int> leer{};
cout <<= leer;           // Ausgabe:
// Initialisierungsliste
set liste{ 1,1,2,2,3,3,4,4,5,5 };  // set übernimmt keine Doppelten
cout <<= liste;          // Ausgabe: 1 2 3 4 5
// Kopie
set copy(liste);
cout <<= copy;           // Ausgabe: 1 2 3 4 5
// Iteratorpaar
set from_to( std::next(liste.begin()), std::prev(liste.end()));
cout <<= from_to;        // Ausgabe: 2 3 4
// Range
set gerade(from_range, liste | vs::filter([](int i){ return i%2; }));
cout <<= from_to;        // Ausgabe: 2 4

Okt 23, 2024

lst-0774-book.cpp

// https://godbolt.org/z/zWa58dYYq 
#include <map>
#include <iostream>
using std::map; using std::cout;
int main() {
    map<int,char> alpha;
    cout << alpha.size() << '\n';       // 0 natürlich
    if( alpha[5] == '3' ) { /* ... */ }
    cout << alpha.size() << '\n';       // nun 1
    char x = alpha[99];                 // klappt
    cout << alpha.size() << '\n';       // und nun 2
}

Okt 23, 2024

lst-0769-book.cpp

// https://godbolt.org/z/rTvovhr5M 
#include <vector>
set data{ 10, 20, 30, };
data.insert( { 40, 50, 60, 70 }); // Initialisierungsliste
std::vector neu{ 5, 25, 35, 15, 25, 75, 95 };
data.insert( neu.cbegin()+1, neu.cend()-1 ); // Bereich
cout <<= data; // Ausgabe: 10 15 20 25 30 35 40 50 60 70 75

Okt 23, 2024

lst-0758-book.cpp

// https://godbolt.org/z/MeGnEez15 
auto vergl = [](auto e, auto f) {return e/10<f/10;}; // zusammenfassen ist okay
std::set<int,decltype(vergl)> data(vergl);
data.insert({ 14,23,56,71 });
cout <<= data;                         // Ausgabe: 14 23 56 71
auto wo = data.find(29);               // 29 findet nun auch die 23
if(wo != data.end()) {
    cout << "hab es: " << *wo << '\n'; // Ausgabe: hab es: 23
}
data.insert(79);                       // nichts passiert, denn 71 ist schon drin
cout <<= data;                         // Ausgabe: 14 23 56 71

Okt 23, 2024

lst-0746-book.cpp

// https://godbolt.org/z/h6nrPYWfM 
#include <array>
#include <iostream>
int main() {
    std::array ports { 80, 443  };          // array<int>
    auto [ http, https ] = ports;           // deklariert Variablen und bindet sie
    std::cout << http << " " << https << "\n";
    auto const& [ rhttp, rhttps ] = ports;  // Referenz und const sind möglich
    std::cout << rhttp << " " << rhttps << "\n";
}

Okt 23, 2024

lst-0775-book.cpp

// https://godbolt.org/z/Eovd71TbT 
#include <map>        // die Hauptsache
#include <iostream>   // zur Ausgabe
#include <string>     // gerne mal Schlüssel oder Ziel
using std::map; using std::cout; using std::string;
template<typename Key, typename Trg, typename Comp>
std::ostream& operator<<=(std::ostream&os, const map<Key,Trg,Comp>&data) {
    for(auto &e : data) os << e.first << ":" << e.second << ' ';
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0757-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GbPsraKxa 
using std::cout; using std::ostream; using std::set;
auto vergl = [](auto e, auto f) { return e <= f; }; //                                          (ERR)  ungültig definiert!
std::set<int,decltype(vergl)> data(vergl);
data.insert({ 9,5,7,2,3,6,8 });
cout <<= data;                     // Ausgabe mit Glück: 2 3 5 6 7 8 9
auto wo = data.find(7);
if(wo != data.end()) {
    cout << "hab es: " << *wo << '\n';
} else {
    cout << "weg isses!" << '\n'; // wahrscheinlich landen Sie hier
}

Okt 23, 2024

lst-0750-book.cpp

// https://godbolt.org/z/7P1Ef7jj4 
#include <deque>
#include <iostream>
#include <iterator>  // ostream_iterator
#include <algorithm> // copy
using namespace std;
ostream& operator<<=(ostream& os, int val) { return os<<val<<'\n'; }
int main() {
    deque d{ 4, 6 };           // deque<int> mit Elementen erzeugen
    // Einfügen
    d.push_front(3);           // am Kopf: effizient
    d.insert(d.begin()+2, 5);  // mittendrin: langsam
    d.push_back(7);            // am Ende: effizient
    // Zugriff
    cout <<= d.front();        // vom Kopf: effizient
    cout <<= d[3];             // mittendrin: effizient
    cout <<= d.back();         // vom Ende: effizient
    // Größe
    cout <<= d.size();         // Größe lesen
    d.resize(4);               // Größe kappen (oder erweitern)
    // Iteratoren
    copy(d.begin(), d.end(), ostream_iterator<int>(cout, " "));
    cout << '\n';              // Ausgabe: 3 4 5 6
    // Entfernen
    d.pop_front();             // am Kopf: effizient
    d.erase(d.begin()+1);      // mittendrin: langsam
    d.pop_back();              // am Ende: effizient
    d.clear();                 // leeren
}

Okt 23, 2024

lst-0755-book.cpp

// https://godbolt.org/z/h51oT7r3h 
#include <set>
#include <iostream>
using std::set; using std::cout;
template<typename Elem, typename Comp>
std::ostream& operator<<=(std::ostream&os, const set<Elem,Comp>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0754-book.cpp

// https://godbolt.org/z/Ka47W5Wjh 
#include <forward_list>
#include <iostream>
using std::cout; using std::forward_list; using std::ostream;

ostream& operator<<=(ostream&os, const forward_list<int> &data)
  { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main() {
  {
    forward_list fw1 {10, 20, 30, 40};
    forward_list fw2 {5, 6, 7, 8};
    fw1.splice_after(fw1.begin(), fw2);  // transferiert alles
    cout <<= fw1;                 // Ausgabe: 10 5 6 7 8 20 30 40
    cout <<= fw2;                 // Ausgabe:
  }
  {
    forward_list fw1 {10, 20, 30, 40};
    forward_list fw2 {5, 6, 7, 8};
    // ein Element übrig:
    fw1.splice_after(fw1.begin(), fw2,fw2.begin(),fw2.end());
    cout <<= fw1;                 // Ausgabe: 10 6 7 8 20 30 40
    cout <<= fw2;                 // Ausgabe: 5
  }
}

Okt 23, 2024

lst-0748-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rc1f3Yd9r 
#include <deque>
#include <iostream>
#include <string>
#include <cctype>   // toupper
#include <iomanip>  // boolalpha
using namespace std;
bool isPalindrome(string_view word) {
    // von beiden Enden gleichzeitig prüfen
    deque<char> deq{};
    for(char ch : word) {
        deq.push_back(toupper(ch));   // Großbuchstaben
    }
    auto ok = true;
    while(deq.size()>1 && ok) {
       if(deq.front() != deq.back()) {
           ok = false;
       }
       deq.pop_front();               // Hallo deque!
       deq.pop_back();
    }
    return ok;
}
int main() {
    cout << boolalpha; // Drucke 'true' und 'false' statt '1' und '0'
    cout << isPalindrome("Abrakadabra") << '\n';   // false
    cout << isPalindrome("Kajak") << '\n';         // true
    cout << isPalindrome("Lagerregal") << '\n';    // true
    cout << isPalindrome("Reliefpfeiler") << '\n'; // true
    cout << isPalindrome("Rentner") << '\n';       // true
    cout << isPalindrome("") << '\n';              // true
}

Okt 23, 2024

lst-0765-book.cpp

// https://godbolt.org/z/1vGPo9a99 
#include <vector>
// …
set data{1,2,3,4,5};
std::vector quelle{10, 20, 30, 40, 50};

// Es gibt kein set::assign:
data.assign(quelle.begin(), quelle.end());   //                                          (ERR)  kein set::assign
// Simulieren Sie es also mittels eines temporären set:
set temp(quelle.begin(), quelle.end());      // aus Quelle kopieren …
data.swap(temp);                             // … Inhalte effizient vertauschen
cout <<= data; // Ausgabe: 10 20 30 40 50
// … oder per vorherigem clear und darauffolgendem insert:
data.clear();                                // leeren …
data.insert(quelle.begin(), quelle.end());   // … und einfügen
cout <<= data; // Ausgabe: 10 20 30 40 50

Okt 23, 2024

lst-0768-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nW3Gxe5Ye 
#include <set>
#include <vector>
#include <iostream>
using std::cout; using std::ostream; using std::set; using std::vector;

template<typename Container>
void insFive(Container& cont, int a, int b, int c, int d, int e) {
    auto it = cont.end();
    for(int x : { a, b, c, d, e }) {
        it = cont.insert(it, x); // geht mit vector, set etc.
    }
}
int main() {
    vector<int> dataVec{ };
    insFive(dataVec, 9, 2, 2, 0, 4 );
    for(auto e : dataVec) cout <<e<<' ';
    cout << '\n'; // Ausgabe: 4 0 2 2 9
    set<int> dataSet{ };
    insFive(dataSet, 9, 4, 2, 2, 0);
    for(auto e : dataSet) cout <<e<<' ';
    cout << '\n'; // Ausgabe: 0 2 4 9
}

Okt 23, 2024

lst-0746-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h6nrPYWfM 
#include <array>
#include <iostream>
int main() {
    std::array ports { 80, 443  };          // array<int>
    auto [ http, https ] = ports;           // deklariert Variablen und bindet sie
    std::cout << http << " " << https << "\n";
    auto const& [ rhttp, rhttps ] = ports;  // Referenz und const sind möglich
    std::cout << rhttp << " " << rhttps << "\n";
}

Okt 23, 2024

lst-0751-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/so5Gebb4M 
#include <list>
#include <iostream>
using std::list; using std::cout; using std::ostream;

ostream& operator<<=(ostream&os, const list<int> &data)
    { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main() {
    list numa { 1, 3, 5, 7, 9 };
    list numb { 2, 4, 6, 8 };
    auto wo = numa.end();
    numa.splice(wo, numb); // transferieren in O(1)
    cout <<= numa; // Ausgabe: 1 3 5 7 9 2 4 6 8
    cout <<= numb; // Ausgabe: (keine)
    numa.sort();   // sort als Methode, nicht aus <algorithm>
    cout <<= numa; // Ausgabe: 1 2 3 4 5 6 7 8 9
}

Okt 23, 2024

lst-0763-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1dTPEd3nP 
set quelle{1,2,3,4,5};
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
set ziel( std::move(quelle) ); // verschieben statt kopieren
cout <<= quelle;           // Ausgabe:
cout <<= ziel;             // Ausgabe: 1 2 3 4 5

Okt 23, 2024

lst-0773-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xW9bTqfG4 
set data{ 10, 20, 30, 40, 50, 60, 70 };
auto lo = data.lower_bound(35);
auto up = data.upper_bound(55);
data.erase(lo, up);      // löscht alle Zahlen zwischen 35 und 55
cout <<= data;           // Ausgabe: 10 20 30 60 70
lo = data.lower_bound(20);
up = data.upper_bound(60);
data.erase(lo, up);      // löscht inklusive 60, weil up auf 70 verweist
cout <<= data;           // Ausgabe: 10 70
auto n = data.erase(69); // löscht nichts
cout << "Anzahl entfernter Elemente: "<< n << '\n'; // Ausgabe: Anzahl  0
n = data.erase(70);      // löscht ein Element
cout << "Anzahl entfernter Elemente: "<< n << '\n';  // Ausgabe: Anzahl  1
cout <<= data;           // Ausgabe: 10

Okt 23, 2024

lst-0767-book.cpp

// https://godbolt.org/z/qzaj79bor 
set data{ 10, 20, 30, 40, 50, 60, 70 };
set<int> ziel;
auto hinweis = ziel.begin();
for(auto &e : data) {
    hinweis =                    // Einfügeposition in nächster Runde nutzen
        ziel.insert(hinweis, e); // Hinweis hilft, weil data sortiert ist
}

Okt 23, 2024

lst-0761-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1Eoh9aoas 
#include <set>
#include <functional> // function
using std::set; using std::function; using std::initializer_list;
bool fcompZehner(int a, int b) { return a%10 < b%10; }
struct Fuenfer {
    bool operator()(int a, int b) const { return a%5 < b% 5; }
};

int main() {
    // Funktor
    set<int, Fuenfer> ff1;
    ff1.insert(5);
    set ff2({5}, Fuenfer{}); 
    set ff3(initializer_list<int>({}), Fuenfer{});
    // Lambda
    set<int,function<bool(int,int)>> ll1([](auto a,auto b){return a%3<b%3;});
    ll1.insert(3);
    auto lcomp = [](int a, int b) { return a%3 < b%3; };
    set<int, decltype(lcomp)> ll2(lcomp);
    ll2.insert(3);
    set ll3({3}, lcomp); 
    // Funktionszeiger
    set<int, bool(*)(int,int)> zz1(&fcompZehner);        // C-Stil
    zz1.insert(10);
    set<int, function<bool(int,int)>> zz2(&fcompZehner); // C++-Stil
    zz2.insert(10);
    set<int, decltype(&fcompZehner)> zz3(&fcompZehner);  // C++-Stil
    zz3.insert(10);
}

Okt 23, 2024

lst-0766-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PjEKKben4 
// 
template<typename IT> ostream& operator<<(ostream& os,const pair<IT,bool> wo)
  { return os << (wo.second ? "ja" : "nein"); }
struct Punkt {
    double x_, y_;
    Punkt(double x, double y) : x_{x}, y_{y} {}
    auto operator<=>(const Punkt&) const = default;
    friend ostream& operator<<(ostream &os, const Punkt &a) {
        return os << "(" << a.x_ << ',' << a.y_<< ")";
    }
};
int main() {
    set data{ 10, 20, 30, 40, 50, 60, 70 };
    auto wo = data.insert(35);         // fügt zwischen 30 und 40 ein
    cout << "neu? " << wo << '\n';     // Ausgabe: neu? ja
    wo = data.insert(40);              // gibt es schon, fügt also nicht ein
    cout << "neu? " << wo << '\n';     // Ausgabe: neu? nein
    set<Punkt> punkte{};
    punkte.insert( Punkt{3.50,7.25} ); // temporärer Wert
    punkte.emplace(1.25, 2.00);        // Konstruktorargumente
    cout <<= punkte;                   // Ausgabe: (1.25,2) (3.5,7.25)
}

Okt 23, 2024

lst-0764-book.cpp

// https://godbolt.org/z/8eGvWY45o 
set quelle{1,2,3,4,5};
set<int> ziel{};
set<int> ziel2{};
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
cout <<= ziel;             // Ausgabe:
cout <<= ziel2;            // Ausgabe:
ziel = quelle;             // nachträglich kopieren
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
cout <<= ziel;             // Ausgabe: 1 2 3 4 5
ziel2 = std::move(quelle); // verschieben
cout <<= quelle;           // Ausgabe:
cout <<= ziel2;            // Ausgabe: 1 2 3 4 5

Okt 23, 2024

lst-0753-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ajn3haEcY 
#include <forward_list>
#include <iostream>
#include <iterator> // next
using std::cout; using std::forward_list; using std::ostream;
ostream& operator<<=(ostream&os, const forward_list<int> &data)
    { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main()     {
    forward_list zahlen {40, 50, 60, 70};
    cout <<= zahlen;                        // Ausgabe: 40 50 60 70
    zahlen.insert_after(zahlen.before_begin(), {10, 20, 30});
    cout <<= zahlen;                        // Ausgabe: 10 20 30 40 50 60 70
    auto wo = std::next(zahlen.begin(), 2); // zwei Elemente weiter
    auto bis = std::next(wo, 3);            // drei Elemente nach wo
    zahlen.erase_after(wo, bis);
    cout <<= zahlen;                        // Ausgabe: 10 20 30 60 70
}

Okt 23, 2024

lst-0747-book.cpp

// https://godbolt.org/z/n16WYf58h 
template<typename E, size_t SZ>
void alle(const array<int,4>& a, const array<int,4>& b) { // absichtlich array& 
                                                          // als Argumente
     cout << "{"<<a<<"} verglichen mit {"<<b<<"} ist "
       << (a < b ? "<, " : "")
       << (a <= b ? "<=, " : "")
       << (a > b ? ">, " : "")
       << (a >= b ? ">=, " : "")
       << (a == b ? "==, " : "")
       << (a != b ? "!=, " : "")
       << '\n';
}
int main() {
    array a{10,10,10,10};
    array b{20, 5, 5, 5};
    array c{10,10,5,21};
    array d{10,10,10,10};
    cout << (a < b ? "kleiner\n" : "nicht kleiner\n"); // "kleiner", weil 10 < 20
    cout << (a < c ? "kleiner\n" : "nicht kleiner\n"); // "nicht …", weil nicht 10 < 5
    cout << (a == d ? "gleich\n" : "nicht gleich\n");  // "gleich", weil alles 10
    for(auto &x : {a,b,c}) {
        for(auto &y : {a,b,c}) {
            alle(x,y);
        }
    }
}

Okt 23, 2024

lst-0769-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rTvovhr5M 
#include <vector>
set data{ 10, 20, 30, };
data.insert( { 40, 50, 60, 70 }); // Initialisierungsliste
std::vector neu{ 5, 25, 35, 15, 25, 75, 95 };
data.insert( neu.cbegin()+1, neu.cend()-1 ); // Bereich
cout <<= data; // Ausgabe: 10 15 20 25 30 35 40 50 60 70 75

Okt 23, 2024

lst-0770-book.cpp

// https://godbolt.org/z/xnv9Wbxbz 
#include <set>
#include <iostream>
using std::cout; using std::ostream; using std::set;
void suchmal(const set<int>&data, int was, ostream&os) {
    os << was << "? ";
    // enthält
    auto drin = data.contains(was);  // C++20
    os << "drin:" << (drin ? "ja." : "nein."); // enthält prüfen
    auto wo = data.find(was);
    if(wo != data.end()) {
        os << " gefunden:" << *wo << " ";
    } else {
        os << " nicht gefunden. ";
    }
    auto lo = data.lower_bound(was);
    if(lo != data.end()) {
        os << "lo:" << *lo;
    } else {
        os << "lo:-";
    }
    auto up = data.upper_bound(was);
    if(up != data.end()) {
        os << " up:" << *up;
    } else {
        os << " up:-";
    }
    // [lo,up] ist nun das Gleiche, was equal_range geliefert hätte
    os << " Bereich:{";
    for( ; lo != up; ++ lo) {
      os << *lo << ' ';
    }
    os << "}";
    // zählen
    os << " C:" << data.count(was) // Treffer zählen
       << "\n";
}
int main() {
    set data{ 10, 20, 30, 40, 50, 60 };
    suchmal(data, 20, cout); // 20? drin:ja. gefunden:20 lo:20 up:30 Bereich:{20 } C:1
    suchmal(data, 25, cout); // 25? drin:nein. lo:30 up:30 Bereich:{} C:0
    suchmal(data, 10, cout); // 10? drin:ja. gefunden:10 lo:10 up:20 Bereich:{10 } C:1
    suchmal(data, 60, cout); // 60? drin:ja. gefunden:60 lo:60 up:- Bereich:{60 } C:1
    suchmal(data, 5, cout);  // 5? drin:nein. lo:10 up:10 Bereich:{} C:0
    suchmal(data, 99, cout); // 99? drin:nein. lo:- up:- Bereich:{} C:0
}

Okt 23, 2024

lst-0759-book.cpp

// https://godbolt.org/z/a3cnTn3zz 
#include <iostream>
#include <set>
#include <string>
struct Dwarf {
  std::string name;
  int height;
  auto operator<=>(const Dwarf& other) const {
    return height <=> other.height;
  }
};
int main() {
  std::set<Dwarf> dwarves {
    {"Thorin", 140}, {"Balin", 136}, {"Kili", 138},
    {"Dwalin", 139}, {"Oin", 135},   {"Gloin", 137},
  };
  for(auto &d: dwarves) {
    std::cout << d.name << ' ';
  } // Ausgabe: Oin Balin Kili Gloin Dwalin Thorin
}

Okt 23, 2024

lst-0774-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zWa58dYYq 
#include <map>
#include <iostream>
using std::map; using std::cout;
int main() {
    map<int,char> alpha;
    cout << alpha.size() << '\n';       // 0 natürlich
    if( alpha[5] == '3' ) { /* ... */ }
    cout << alpha.size() << '\n';       // nun 1
    char x = alpha[99];                 // klappt
    cout << alpha.size() << '\n';       // und nun 2
}

Okt 23, 2024

lst-0768-book.cpp

// https://godbolt.org/z/nW3Gxe5Ye 
#include <set>
#include <vector>
#include <iostream>
using std::cout; using std::ostream; using std::set; using std::vector;

template<typename Container>
void insFive(Container& cont, int a, int b, int c, int d, int e) {
    auto it = cont.end();
    for(int x : { a, b, c, d, e }) {
        it = cont.insert(it, x); // geht mit vector, set etc.
    }
}
int main() {
    vector<int> dataVec{ };
    insFive(dataVec, 9, 2, 2, 0, 4 );
    for(auto e : dataVec) cout <<e<<' ';
    cout << '\n'; // Ausgabe: 4 0 2 2 9
    set<int> dataSet{ };
    insFive(dataSet, 9, 4, 2, 2, 0);
    for(auto e : dataSet) cout <<e<<' ';
    cout << '\n'; // Ausgabe: 0 2 4 9
}

Okt 23, 2024

lst-0771-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jGfeT94as 
#include <string>
#include <set>
#include <iostream>
#include <tuple> // tuple, tie
using std::string; using std::set; using std::cout; using std::tie;
struct Hobbit {
  string vorname;
  string nachname;
  Hobbit(const string v, const string n) : vorname{v}, nachname{n} {}
};
struct CompNachname {
  bool operator()(const Hobbit& x, const Hobbit& y) const { // normales <
    return tie(x.nachname, x.vorname) < tie(y.nachname, y.vorname);
  }
  using is_transparent = std::true_type; // für find erlaubt
  bool operator()(const Hobbit& x, const string& y) const { // für find etc.
    return x.nachname < y;
  }
  bool operator()(const string& x, const Hobbit& y) const { // für find etc.
    return x < y.nachname;
  }
};
int main() {
    using namespace std::literals; // erlaube "…"s
    set<Hobbit,CompNachname> hobbits;
    hobbits.emplace( "Frodo", "Baggins" );
    hobbits.emplace( "Sam", "Gamgee" );
    auto f1 = hobbits.find( Hobbit{"Frodo", "Baggins"} ); // ganzer Schlüssel
    if(f1 != hobbits.end()) {
        cout << "gefunden: " << f1->vorname << '\n'; // Frodo
    }
    auto f2 = hobbits.find( "Gamgee"s );             // äquivalenter Schlüssel
    if(f2 != hobbits.end()) {
        cout << "gefunden: " << f2->vorname << '\n'; // Sam
    }
}

Okt 23, 2024

lst-0757-book.cpp

// https://godbolt.org/z/GbPsraKxa 
using std::cout; using std::ostream; using std::set;
auto vergl = [](auto e, auto f) { return e <= f; }; //                                          (ERR)  ungültig definiert!
std::set<int,decltype(vergl)> data(vergl);
data.insert({ 9,5,7,2,3,6,8 });
cout <<= data;                     // Ausgabe mit Glück: 2 3 5 6 7 8 9
auto wo = data.find(7);
if(wo != data.end()) {
    cout << "hab es: " << *wo << '\n';
} else {
    cout << "weg isses!" << '\n'; // wahrscheinlich landen Sie hier
}

Okt 23, 2024

lst-0759-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a3cnTn3zz 
#include <iostream>
#include <set>
#include <string>
struct Dwarf {
  std::string name;
  int height;
  auto operator<=>(const Dwarf& other) const {
    return height <=> other.height;
  }
};
int main() {
  std::set<Dwarf> dwarves {
    {"Thorin", 140}, {"Balin", 136}, {"Kili", 138},
    {"Dwalin", 139}, {"Oin", 135},   {"Gloin", 137},
  };
  for(auto &d: dwarves) {
    std::cout << d.name << ' ';
  } // Ausgabe: Oin Balin Kili Gloin Dwalin Thorin
}

Okt 23, 2024

lst-0765-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1vGPo9a99 
#include <vector>
// 
set data{1,2,3,4,5};
std::vector quelle{10, 20, 30, 40, 50};

// Es gibt kein set::assign:
data.assign(quelle.begin(), quelle.end());   //                                          (ERR)  kein set::assign
// Simulieren Sie es also mittels eines temporären set:
set temp(quelle.begin(), quelle.end());      // aus Quelle kopieren 
data.swap(temp);                             //  Inhalte effizient vertauschen
cout <<= data; // Ausgabe: 10 20 30 40 50
//  oder per vorherigem clear und darauffolgendem insert:
data.clear();                                // leeren 
data.insert(quelle.begin(), quelle.end());   //  und einfügen
cout <<= data; // Ausgabe: 10 20 30 40 50

Okt 23, 2024

lst-0754-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ka47W5Wjh 
#include <forward_list>
#include <iostream>
using std::cout; using std::forward_list; using std::ostream;

ostream& operator<<=(ostream&os, const forward_list<int> &data)
  { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main() {
  {
    forward_list fw1 {10, 20, 30, 40};
    forward_list fw2 {5, 6, 7, 8};
    fw1.splice_after(fw1.begin(), fw2);  // transferiert alles
    cout <<= fw1;                 // Ausgabe: 10 5 6 7 8 20 30 40
    cout <<= fw2;                 // Ausgabe:
  }
  {
    forward_list fw1 {10, 20, 30, 40};
    forward_list fw2 {5, 6, 7, 8};
    // ein Element übrig:
    fw1.splice_after(fw1.begin(), fw2,fw2.begin(),fw2.end());
    cout <<= fw1;                 // Ausgabe: 10 6 7 8 20 30 40
    cout <<= fw2;                 // Ausgabe: 5
  }
}

Okt 23, 2024

lst-0750-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7P1Ef7jj4 
#include <deque>
#include <iostream>
#include <iterator>  // ostream_iterator
#include <algorithm> // copy
using namespace std;
ostream& operator<<=(ostream& os, int val) { return os<<val<<'\n'; }
int main() {
    deque d{ 4, 6 };           // deque<int> mit Elementen erzeugen
    // Einfügen
    d.push_front(3);           // am Kopf: effizient
    d.insert(d.begin()+2, 5);  // mittendrin: langsam
    d.push_back(7);            // am Ende: effizient
    // Zugriff
    cout <<= d.front();        // vom Kopf: effizient
    cout <<= d[3];             // mittendrin: effizient
    cout <<= d.back();         // vom Ende: effizient
    // Größe
    cout <<= d.size();         // Größe lesen
    d.resize(4);               // Größe kappen (oder erweitern)
    // Iteratoren
    copy(d.begin(), d.end(), ostream_iterator<int>(cout, " "));
    cout << '\n';              // Ausgabe: 3 4 5 6
    // Entfernen
    d.pop_front();             // am Kopf: effizient
    d.erase(d.begin()+1);      // mittendrin: langsam
    d.pop_back();              // am Ende: effizient
    d.clear();                 // leeren
}

Okt 23, 2024

lst-0767-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qzaj79bor 
set data{ 10, 20, 30, 40, 50, 60, 70 };
set<int> ziel;
auto hinweis = ziel.begin();
for(auto &e : data) {
    hinweis =                    // Einfügeposition in nächster Runde nutzen
        ziel.insert(hinweis, e); // Hinweis hilft, weil data sortiert ist
}

Okt 23, 2024

lst-0776-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nfs15n1Mn 
#include <cstdio> // toupper, tolower
// 
auto comp = [](char a, char b) { return toupper(a) < toupper(b); };
map<char,int,decltype(comp)> lets(comp); // als Templateparameter und Argument
lets['a'] = 1;
lets['B'] = 2;
lets['c'] = 3;
lets['A'] = 4; // überschreibt Position 'a'
cout <<= lets; // Ausgabe: a:4 B:2 c:3
struct Comp {  // Funktor
    bool operator()(char a, char b) const { return toupper(a) < toupper(b); }
};
map<char,int,Comp> lets2; // hier reicht der Templateparameter

Okt 23, 2024

lst-0773-book.cpp

// https://godbolt.org/z/xW9bTqfG4 
set data{ 10, 20, 30, 40, 50, 60, 70 };
auto lo = data.lower_bound(35);
auto up = data.upper_bound(55);
data.erase(lo, up);      // löscht alle Zahlen zwischen 35 und 55
cout <<= data;           // Ausgabe: 10 20 30 60 70
lo = data.lower_bound(20);
up = data.upper_bound(60);
data.erase(lo, up);      // löscht inklusive 60, weil up auf 70 verweist
cout <<= data;           // Ausgabe: 10 70
auto n = data.erase(69); // löscht nichts
cout << "Anzahl entfernter Elemente: "<< n << '\n'; // Ausgabe: Anzahl … 0
n = data.erase(70);      // löscht ein Element
cout << "Anzahl entfernter Elemente: "<< n << '\n';  // Ausgabe: Anzahl … 1
cout <<= data;           // Ausgabe: 10

Okt 23, 2024

lst-0771-book.cpp

// https://godbolt.org/z/jGfeT94as 
#include <string>
#include <set>
#include <iostream>
#include <tuple> // tuple, tie
using std::string; using std::set; using std::cout; using std::tie;
struct Hobbit {
  string vorname;
  string nachname;
  Hobbit(const string v, const string n) : vorname{v}, nachname{n} {}
};
struct CompNachname {
  bool operator()(const Hobbit& x, const Hobbit& y) const { // normales <
    return tie(x.nachname, x.vorname) < tie(y.nachname, y.vorname);
  }
  using is_transparent = std::true_type; // für find erlaubt
  bool operator()(const Hobbit& x, const string& y) const { // für find etc.
    return x.nachname < y;
  }
  bool operator()(const string& x, const Hobbit& y) const { // für find etc.
    return x < y.nachname;
  }
};
int main() {
    using namespace std::literals; // erlaube "…"s
    set<Hobbit,CompNachname> hobbits;
    hobbits.emplace( "Frodo", "Baggins" );
    hobbits.emplace( "Sam", "Gamgee" );
    auto f1 = hobbits.find( Hobbit{"Frodo", "Baggins"} ); // ganzer Schlüssel
    if(f1 != hobbits.end()) {
        cout << "gefunden: " << f1->vorname << '\n'; // Frodo
    }
    auto f2 = hobbits.find( "Gamgee"s );             // äquivalenter Schlüssel
    if(f2 != hobbits.end()) {
        cout << "gefunden: " << f2->vorname << '\n'; // Sam
    }
}

Okt 23, 2024

lst-0770-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xnv9Wbxbz 
#include <set>
#include <iostream>
using std::cout; using std::ostream; using std::set;
void suchmal(const set<int>&data, int was, ostream&os) {
    os << was << "? ";
    // enthält
    auto drin = data.contains(was);  // C++20
    os << "drin:" << (drin ? "ja." : "nein."); // enthält prüfen
    auto wo = data.find(was);
    if(wo != data.end()) {
        os << " gefunden:" << *wo << " ";
    } else {
        os << " nicht gefunden. ";
    }
    auto lo = data.lower_bound(was);
    if(lo != data.end()) {
        os << "lo:" << *lo;
    } else {
        os << "lo:-";
    }
    auto up = data.upper_bound(was);
    if(up != data.end()) {
        os << " up:" << *up;
    } else {
        os << " up:-";
    }
    // [lo,up] ist nun das Gleiche, was equal_range geliefert hätte
    os << " Bereich:{";
    for( ; lo != up; ++ lo) {
      os << *lo << ' ';
    }
    os << "}";
    // zählen
    os << " C:" << data.count(was) // Treffer zählen
       << "\n";
}
int main() {
    set data{ 10, 20, 30, 40, 50, 60 };
    suchmal(data, 20, cout); // 20? drin:ja. gefunden:20 lo:20 up:30 Bereich:{20 } C:1
    suchmal(data, 25, cout); // 25? drin:nein. lo:30 up:30 Bereich:{} C:0
    suchmal(data, 10, cout); // 10? drin:ja. gefunden:10 lo:10 up:20 Bereich:{10 } C:1
    suchmal(data, 60, cout); // 60? drin:ja. gefunden:60 lo:60 up:- Bereich:{60 } C:1
    suchmal(data, 5, cout);  // 5? drin:nein. lo:10 up:10 Bereich:{} C:0
    suchmal(data, 99, cout); // 99? drin:nein. lo:- up:- Bereich:{} C:0
}

Okt 23, 2024

lst-0758-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MeGnEez15 
auto vergl = [](auto e, auto f) {return e/10<f/10;}; // zusammenfassen ist okay
std::set<int,decltype(vergl)> data(vergl);
data.insert({ 14,23,56,71 });
cout <<= data;                         // Ausgabe: 14 23 56 71
auto wo = data.find(29);               // 29 findet nun auch die 23
if(wo != data.end()) {
    cout << "hab es: " << *wo << '\n'; // Ausgabe: hab es: 23
}
data.insert(79);                       // nichts passiert, denn 71 ist schon drin
cout <<= data;                         // Ausgabe: 14 23 56 71

Okt 23, 2024

lst-0748-book.cpp

// https://godbolt.org/z/rc1f3Yd9r 
#include <deque>
#include <iostream>
#include <string>
#include <cctype>   // toupper
#include <iomanip>  // boolalpha
using namespace std;
bool isPalindrome(string_view word) {
    // von beiden Enden gleichzeitig prüfen
    deque<char> deq{};
    for(char ch : word) {
        deq.push_back(toupper(ch));   // Großbuchstaben
    }
    auto ok = true;
    while(deq.size()>1 && ok) {
       if(deq.front() != deq.back()) {
           ok = false;
       }
       deq.pop_front();               // Hallo deque!
       deq.pop_back();
    }
    return ok;
}
int main() {
    cout << boolalpha; // Drucke 'true' und 'false' statt '1' und '0'
    cout << isPalindrome("Abrakadabra") << '\n';   // false
    cout << isPalindrome("Kajak") << '\n';         // true
    cout << isPalindrome("Lagerregal") << '\n';    // true
    cout << isPalindrome("Reliefpfeiler") << '\n'; // true
    cout << isPalindrome("Rentner") << '\n';       // true
    cout << isPalindrome("") << '\n';              // true
}

Okt 23, 2024

lst-0761-book.cpp

// https://godbolt.org/z/1Eoh9aoas 
#include <set>
#include <functional> // function
using std::set; using std::function; using std::initializer_list;
bool fcompZehner(int a, int b) { return a%10 < b%10; }
struct Fuenfer {
    bool operator()(int a, int b) const { return a%5 < b% 5; }
};

int main() {
    // Funktor
    set<int, Fuenfer> ff1;
    ff1.insert(5);
    set ff2({5}, Fuenfer{}); 
    set ff3(initializer_list<int>({}), Fuenfer{});
    // Lambda
    set<int,function<bool(int,int)>> ll1([](auto a,auto b){return a%3<b%3;});
    ll1.insert(3);
    auto lcomp = [](int a, int b) { return a%3 < b%3; };
    set<int, decltype(lcomp)> ll2(lcomp);
    ll2.insert(3);
    set ll3({3}, lcomp); 
    // Funktionszeiger
    set<int, bool(*)(int,int)> zz1(&fcompZehner);        // C-Stil
    zz1.insert(10);
    set<int, function<bool(int,int)>> zz2(&fcompZehner); // C++-Stil
    zz2.insert(10);
    set<int, decltype(&fcompZehner)> zz3(&fcompZehner);  // C++-Stil
    zz3.insert(10);
}

Okt 23, 2024

lst-0747-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n16WYf58h 
template<typename E, size_t SZ>
void alle(const array<int,4>& a, const array<int,4>& b) { // absichtlich array& 
                                                          // als Argumente
     cout << "{"<<a<<"} verglichen mit {"<<b<<"} ist "
       << (a < b ? "<, " : "")
       << (a <= b ? "<=, " : "")
       << (a > b ? ">, " : "")
       << (a >= b ? ">=, " : "")
       << (a == b ? "==, " : "")
       << (a != b ? "!=, " : "")
       << '\n';
}
int main() {
    array a{10,10,10,10};
    array b{20, 5, 5, 5};
    array c{10,10,5,21};
    array d{10,10,10,10};
    cout << (a < b ? "kleiner\n" : "nicht kleiner\n"); // "kleiner", weil 10 < 20
    cout << (a < c ? "kleiner\n" : "nicht kleiner\n"); // "nicht …", weil nicht 10 < 5
    cout << (a == d ? "gleich\n" : "nicht gleich\n");  // "gleich", weil alles 10
    for(auto &x : {a,b,c}) {
        for(auto &y : {a,b,c}) {
            alle(x,y);
        }
    }
}

Okt 23, 2024

lst-0764-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8eGvWY45o 
set quelle{1,2,3,4,5};
set<int> ziel{};
set<int> ziel2{};
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
cout <<= ziel;             // Ausgabe:
cout <<= ziel2;            // Ausgabe:
ziel = quelle;             // nachträglich kopieren
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
cout <<= ziel;             // Ausgabe: 1 2 3 4 5
ziel2 = std::move(quelle); // verschieben
cout <<= quelle;           // Ausgabe:
cout <<= ziel2;            // Ausgabe: 1 2 3 4 5

Okt 23, 2024

lst-0775-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Eovd71TbT 
#include <map>        // die Hauptsache
#include <iostream>   // zur Ausgabe
#include <string>     // gerne mal Schlüssel oder Ziel
using std::map; using std::cout; using std::string;
template<typename Key, typename Trg, typename Comp>
std::ostream& operator<<=(std::ostream&os, const map<Key,Trg,Comp>&data) {
    for(auto &e : data) os << e.first << ":" << e.second << ' ';
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0752-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9b9fY4Mve 
#include <iostream>
#include <forward_list>
int main()     {
    std::forward_list mylist = {20, 30, 40, 50};
    mylist.insert_after(mylist.before_begin(), 11 );
    for (int& x: mylist) std::cout << ' ' << x; // Ausgabe: 11 20 30 40 50
    std::cout << '\n';
}

Okt 23, 2024

lst-0778-book.cpp

// https://godbolt.org/z/79xx8ddoY 
using std::pair; using std::make_pair;
namespace literal_p { // benutzerdefinierte Literale besser in Namespace packen
constexpr pair<char,char> operator "" _p(const char* s, size_t len) {
    return len>=2 ?make_pair(s[0], s[1]) : make_pair( '-', '-' );
} }
struct Q {
    char a_; int n_;
    Q(char a, int n) : a_{a}, n_{n} {}
    operator pair<const char,int>() { return make_pair(a_, n_); }
};
// …
// explizite Paare:
map<int,int> nums { pair<int,int>(3,4), make_pair(7,8), make_pair(11,23) };
map nums2 { pair<int,int>(6,1), make_pair(5,2) };
// implizite Paare aus Initialisierungslisten:
map<int,char> numch{{1,'a'},{2,'b'},{3,'c'}};
map<int,int> nums3 { {7,2}, {9,4} };
using namespace literal_p;
map<char,char> pmap { "ab"_p, "cd"_p, "ef"_p }; // Umweg über eigenes Literal
cout <<= pmap;                                  // Ausgabe: a:b c:d e:f
map<char,int> qmap{Q('a',1),Q('b',2),Q('c',3)}; // implizite Umwandlungen
cout <<= qmap;                                  // Ausgabe: a:1 b:2 c:3

Okt 23, 2024

lst-0751-book.cpp

// https://godbolt.org/z/so5Gebb4M 
#include <list>
#include <iostream>
using std::list; using std::cout; using std::ostream;

ostream& operator<<=(ostream&os, const list<int> &data)
    { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main() {
    list numa { 1, 3, 5, 7, 9 };
    list numb { 2, 4, 6, 8 };
    auto wo = numa.end();
    numa.splice(wo, numb); // transferieren in O(1)
    cout <<= numa; // Ausgabe: 1 3 5 7 9 2 4 6 8
    cout <<= numb; // Ausgabe: (keine)
    numa.sort();   // sort als Methode, nicht aus <algorithm>
    cout <<= numa; // Ausgabe: 1 2 3 4 5 6 7 8 9
}

Okt 23, 2024

lst-0753-book.cpp

// https://godbolt.org/z/ajn3haEcY 
#include <forward_list>
#include <iostream>
#include <iterator> // next
using std::cout; using std::forward_list; using std::ostream;
ostream& operator<<=(ostream&os, const forward_list<int> &data)
    { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main()     {
    forward_list zahlen {40, 50, 60, 70};
    cout <<= zahlen;                        // Ausgabe: 40 50 60 70
    zahlen.insert_after(zahlen.before_begin(), {10, 20, 30});
    cout <<= zahlen;                        // Ausgabe: 10 20 30 40 50 60 70
    auto wo = std::next(zahlen.begin(), 2); // zwei Elemente weiter
    auto bis = std::next(wo, 3);            // drei Elemente nach wo
    zahlen.erase_after(wo, bis);
    cout <<= zahlen;                        // Ausgabe: 10 20 30 60 70
}

Okt 23, 2024

lst-0734-book.cpp

// https://godbolt.org/z/n8jn7v5vb 
#include <mdspan>
#include <iostream>
#include <vector>
using namespace std;
int main() {
    // 1D: 12 Elemente
    vector v{1,2,3,4,5,6,7,8,9,10,11,12};
    // 2D: als 2 Zeilen mit je 6 ints
    auto ms2 = mdspan(v.data(), 2, 6);
    // 3D: als Quader mit 2 Ebenen, 3 Reihen, 2 Spalten
    auto ms3 = mdspan(v.data(), 2, 3, 2);
    // via 2D-Ansicht schreiben
    for (auto i = 0; i != ms2.extent(0); ++i)
      for (auto j = 0; j != ms2.extent(1); ++j)
        ms2[i, j] = i * 100 + j;  // schreiben via mehrdimensionalen Index
    // via 3D-Ansicht lesen
    for (auto i = 0; i != ms3.extent(0); ++i) {
      cout << "Ebene " << i << ":\n";
      for (auto j = 0; j != ms3.extent(1); ++j) {
        for (auto k = 0; k != ms3.extent(2); ++k)
          cout << " " << ms3[i, j, k];  // lesen via mehrdimensionalen Index
        cout << '\n';
      }
    }
    // Ausgabe: Ebene 0: 0 1, 2 3, 4 5, Ebene 1: 100 101, 102 103, 104 105
}

Okt 23, 2024

lst-0728-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h7jf4KM1q 
#include <vector>
#include <span>
#include <iostream>
using namespace std;
int sum(span<const int> bereich) { // C++20: span
   int sum = 0;
   for(auto e : bereich) {         // algorithm wäre besser 
    sum += e;
   }
   return sum;
}
int main() {
    vector data {1,2,3,4,5};
    cout << sum(data) << "\n";            // implizit Container zu span
    auto [b, e, sz] = make_tuple(begin(data), end(data), size(data));
    cout << sum(span{b,   sz-1}) << "\n"; // 1..4 (Iter, size)
    cout << sum(span{b+1, sz-1}) << "\n"; // 2..5 (Iter, size)
    cout << sum(span{b,   e-2}) << "\n";  // 1..3 (Iter, Iter)
    cout << sum(span{b+1, e-1}) << "\n";  // 2..4 (Iter, Iter)
    cout << sum(span{b+2, e  }) << "\n";  // 3..5 (Iter, Iter)
    return 0;
}

Okt 23, 2024

lst-0723-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/evse4x8zK 
#include <vector>
#include <iostream>
#include <cstdio> // fopen, fclose, fwrite, fread, remove
using namespace std;
ostream& operator<<(ostream&os, const vector<int>&data) {
    for(auto &e : data) os << e << ' '; return os;
}
static const char* FILENAME = "nums.dat";
int main() {
  const vector nums{10,11,22,34};
  { // Schreiben
    auto out = fopen(FILENAME, "wb"); // Datei mit C zum Schreiben öffnen
    if(out==nullptr) {
        cerr << "Fehler beim Oeffnen\n"; return -1;
    }
    auto ok = fwrite(nums.data(), sizeof(int), nums.size(), out);
    if(ok!=nums.size()) {
        cerr << "Fehler beim Schreiben\n"; return -1;
    }
    fclose(out); // In C muss man explizit schließen. Ehrlich.
  }
  vector<int> gelesen{};
  { // Lesen
    auto in = fopen(FILENAME, "rb"); // Datei mit C zum Lesen öffnen
    if(in==nullptr) {
        cerr << "Fehler beim Oeffnen\n"; return -1;
    }
    const size_t sz = 4; // angenommen, wir wissen, wir lesen 4 Elemente 
    gelesen.resize(sz);  // Platz schaffen für zu lesende Daten
    auto ok = fread(gelesen.data(), sizeof(int), sz, in);
    if(ok!=sz) {
        cerr << "Fehler beim Lesen\n"; return -1;
    }
    fclose(in);
  }
  { // Vergleichen
    cout << nums << '\n';    // 10 11 22 34
    cout << gelesen << '\n'; // 10 11 22 34
  }
  if(remove(FILENAME) == -1) {
      cerr << "Warning: Fehler beim Loeschen\n";
  }
}

Okt 23, 2024

lst-0733-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6Ez5GdozG 
#include <vector>
#include <span>
#include <iostream>
using namespace std;
void inc(span<int> span) {
   for(auto& e :span) {  // Referenz
     e += 1;             // schreiben
   }
}
int main() {
    vector data {1,2,3,4,5};
    span ganz{data};              //    1,2,3,4,5
    inc(ganz.first(3));           // -> 2,3,4,4,5
    inc(ganz.last(3));            // -> 2,3,5,5,6
    inc(ganz.last(4).first(3));   // -> 2,4,6,6,6
    inc(ganz.subspan(1,3));       // -> 2,5,7,7,6
    for(auto i: ganz) cout << i << ' '; cout << '\n'; // Ausgabe: 2 5 7 7 6
    return 0;
}

Okt 23, 2024

lst-0719-book.cpp

// https://godbolt.org/z/vMa8bPaob 
#include <vector>
#include <iostream>
#include <algorithm>                // ranges::sort
using std::vector; using std::cout;
double median(vector<int> daten) {  // kopiert
    std::ranges::sort(daten);       // C++20, sonst std::sort()
    auto it = daten.begin();
    auto sz = daten.size();
    if(sz==0) return 0;             // Sonderfall
    // Median ermitteln:
    auto m = (it+sz/2);             // ungefähr die Mitte
    if(sz%2 != 0) {                 // ungerade Anzahl Elemente
        return *m;
    } else {                        // gerade Anzahl Elemente
        return double(*m + *(m-1)) / 2;
    }
}
int main() {
    vector daten1 { 12, 22, 34, 10, 1, 99, 33 };
    cout << median(daten1) << '\n'; // 22
    vector daten2 { 30, 2, 80, 99, 31, 3 };
    cout << median(daten2) << '\n'; // 30.5
}

Okt 23, 2024

lst-0731-book.cpp

// https://godbolt.org/z/a3qqr1YPM 
int car[5]  {1,2,3,4,5};
span span_1 = car;          // direkt aus einem C-Array
array arr   {1,2,3,4,5};
span span_2 {arr};          // direkt aus einem std::array
vector vec  {1,2,3,4,5};
span<int,3> span_3 {vec};   // mit 'Extent' aus einem std::vector

Okt 23, 2024

lst-0738-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6836bdczd 
std::vector v{ 1, 2, 3, 4, 5, 6 };
for(auto it=v.begin(); it!=v.end(); ++it) {
  it = v.erase(it);
}
// Hier ist v: { 2, 4, 6 }

Okt 23, 2024

lst-0718-book.cpp

// https://godbolt.org/z/6ahzhdjva 
vector vokale { 'A', 'e', 'i', 'o', 'u' };
const vector gerade { '0', '2', '4', '6', '8' };
auto it1 = vokale.begin();                 // vector<char>::iterator
*it1 = 'a';                                // '*it1' liefert 'char&' zurück
auto it2 = gerade.begin();                 // vector<char>::const_iterator
auto it3 = vokale.cbegin();                // erzwingt const_iterator
*i2 = '9'; *i3 = 'x';                      //                                          (ERR)  'const char&' ist nicht veränderbar
for(auto it=vokale.cbegin()+1; it!=vokale.cend(); ++it)
    { cout << *it; } cout << '\n';         // Ausgabe: eiou
for(auto it=vokale.crbegin()+1; it!=vokale.crend(); ++it) // ++ trotz reverse!
    { cout << *it; } cout << '\n';         // Ausgabe: oiea

Okt 23, 2024

lst-0742-book.cpp

// https://godbolt.org/z/Y1W8WfxYn 
#include <array>
void berechne(const std::array<int,4>& data) { /* ... */ }
void berechne(const std::array<int,5>& data) { /* ... */ }

Okt 23, 2024

Okt 23, 2024

lst-0713-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EK4e7Trv3 
#include <list>
#include <string>
#include <iterator>                      // make_move_iterator
using std::make_move_iterator; using std::string;
vector<int> erzeuge() { return vector<int>{8, 9, 10}; }
size_t zaehle(vector<int> d) { return d.size(); }
// 
vector input{1,2,3};
vector outputA(std::move(input));       // Verschiebung
vector outputB = std::move(input);      // auch Verschiebung, keine Zuweisung
vector data = erzeuge();                // Return-Value-Optimization
cout << zaehle(input) << '\n';          // Aufruf per Copy-by-Value
// elementweise aus einem anderen Container verschieben
std::list<string> quelle{ "a", "a", "a", "BB", "CC", "DD", "b", "b" };
auto von = quelle.begin();
std::advance(von, 3); // 3 vorwärts, bei list aber langsam
auto bis = von;
std::advance(bis, 3); // noch mal 3 vorwärts
vector ziel(make_move_iterator(von), make_move_iterator(bis));
// quelle ist nun {"a", "a", "a", "", "", "", "b", "b"}, ziel ist nun {"BB", "CC", "DD"}

Okt 23, 2024

lst-0712-book.cpp

// https://godbolt.org/z/cE6G1aErs 
auto zaehle(vector<int> arg) { return arg.size(); }
// …
vector input{1,2,3};           // vector<int>
vector outputA(input);         // Kopie
vector outputB = input;        // auch Kopie, keine Zuweisung
cout << zaehle(input) << '\n'; // Aufruf per Copy-by-Value

Okt 23, 2024

lst-0717-book.cpp

// https://godbolt.org/z/Yb4jEdaKj 
vector<int> von{ 2,3,4 };
vector<int> nach{};
nach = von;                         // Zuweisung mit operator=, nun beide gleich

vector<int> abfluss{};
abfluss = std::move(von);           // Verschieben, nun ist 'von' leer
vector<int> v;
v.assign(4, 100);                   // v ist nun {100, 100, 100, 100}
v.assign(nach.begin(), nach.end()); // v ist nun {2,3,4}
int z[] = { 10, 20, 30, 40 };
v.assign(z+1, z+4);                 // v ist nun {20, 30, 40}

Okt 23, 2024

lst-0714-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4T7fjxdPa 
vector<int> prims{ 2,3,5,7,11 };
vector gerade{ 2,4,6,8,10 };
vector<int> soNicht{ 'a', 4.3, 8L };     //                                          (ERR)  "Narrowing" double nicht okay
vector<string> namen{ "sind", "nur" };   // konvertiert Argumente
vector schall{ "rauch", "qualm" };       // gefährlich: vector<const char[]>
vector nass{ "regen"s, "wasser"s };      // vector<string>
vector kalt{ "eis"sv, "pol"sv };         // vector<string_view>

Okt 23, 2024

lst-0733-book.cpp

// https://godbolt.org/z/6Ez5GdozG 
#include <vector>
#include <span>
#include <iostream>
using namespace std;
void inc(span<int> span) {
   for(auto& e :span) {  // Referenz
     e += 1;             // schreiben
   }
}
int main() {
    vector data {1,2,3,4,5};
    span ganz{data};              //    1,2,3,4,5
    inc(ganz.first(3));           // -> 2,3,4,4,5
    inc(ganz.last(3));            // -> 2,3,5,5,6
    inc(ganz.last(4).first(3));   // -> 2,4,6,6,6
    inc(ganz.subspan(1,3));       // -> 2,5,7,7,6
    for(auto i: ganz) cout << i << ' '; cout << '\n'; // Ausgabe: 2 5 7 7 6
    return 0;
}

Okt 23, 2024

lst-0744-book.cpp

// https://godbolt.org/z/PrM4fGcWo 
#include <array>
#include <iostream>
using std::array; using std::cout;
template<typename Elem, size_t SZ>
std::ostream& operator<<(std::ostream&os, const array<Elem,SZ>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os;
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0713-book.cpp

// https://godbolt.org/z/EK4e7Trv3 
#include <list>
#include <string>
#include <iterator>                      // make_move_iterator
using std::make_move_iterator; using std::string;
vector<int> erzeuge() { return vector<int>{8, 9, 10}; }
size_t zaehle(vector<int> d) { return d.size(); }
// …
vector input{1,2,3};
vector outputA(std::move(input));       // Verschiebung
vector outputB = std::move(input);      // auch Verschiebung, keine Zuweisung
vector data = erzeuge();                // Return-Value-Optimization
cout << zaehle(input) << '\n';          // Aufruf per Copy-by-Value
// elementweise aus einem anderen Container verschieben
std::list<string> quelle{ "a", "a", "a", "BB", "CC", "DD", "b", "b" };
auto von = quelle.begin();
std::advance(von, 3); // 3 vorwärts, bei list aber langsam
auto bis = von;
std::advance(bis, 3); // noch mal 3 vorwärts
vector ziel(make_move_iterator(von), make_move_iterator(bis));
// quelle ist nun {"a", "a", "a", "", "", "", "b", "b"}, ziel ist nun {"BB", "CC", "DD"}

Okt 23, 2024

lst-0731-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a3qqr1YPM 
int car[5]  {1,2,3,4,5};
span span_1 = car;          // direkt aus einem C-Array
array arr   {1,2,3,4,5};
span span_2 {arr};          // direkt aus einem std::array
vector vec  {1,2,3,4,5};
span<int,3> span_3 {vec};   // mit 'Extent' aus einem std::vector

Okt 23, 2024

lst-0722-book.cpp

// https://godbolt.org/z/YhYs3z5Ex 
vector<string> autos{ "Diesel", "Benzin", "Super", "Gas" };
cout << autos[1] << '\n';             // Ausgabe: Benzin
autos.insert(autos.begin(), "Strom"); // verschiebt alles um eins nach hinten
cout << autos[1] << '\n';             // Ausgabe: Diesel

Okt 23, 2024

lst-0743-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nqbKT9GEa 
#include <array>
#include <numeric> // accumulate
#include <iostream>
template<size_t SZ>
int sumSz(const std::array<int,SZ>& data) {
    int result = 0;
    for(auto i=0uz; i<SZ; ++i)           // uz ist das Suffix für size_t seit C++23
        result += data[i];
    return result;
}
template<typename Elem, size_t SZ>
Elem sumElem(const std::array<Elem,SZ>& data) {
    Elem result {0};
    for(auto i=0uz; i<SZ; ++i)
        result += data[i];
    return result;
}
// C++20-Concept input_iterator, sonst typename
template<std::input_iterator It>
int sumIt(It begin, It end) {
    return std::accumulate(begin, end, 0);
}
int sumAuto(std::input_iterator auto begin, std::input_iterator auto end) {
    return std::accumulate(begin, end, 0);
}
// abgekürztes funktionstemplate mit auto
int main() {
   using namespace std;
   array<int,4> a4 { 1, 2, 5, 8 };
   cout << sumSz<4>(a4) << '\n';                  // Ausgabe: 16
   array<int,5> a5 { 1, -5, 3, 7, 2 };
   cout << sumElem(a5) << '\n';                   // Ausgabe: 8
   array<int,6> a6 { 1,2,3, 4,5,6 };
   cout << sumIt(a6.begin(), a6.end()) << '\n';   // Ausgabe: 21
   array a7 { 1,2,3, 4,5,6, 7 };                  // array<int,7>
   cout << sumIt(a7.begin(), a7.end()) << '\n';   // Ausgabe: 28
   cout << sumAuto(a7.begin(), a7.end()) << '\n'; // Ausgabe: 28
}

Okt 23, 2024

lst-0712-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cE6G1aErs 
auto zaehle(vector<int> arg) { return arg.size(); }
// 
vector input{1,2,3};           // vector<int>
vector outputA(input);         // Kopie
vector outputB = input;        // auch Kopie, keine Zuweisung
cout << zaehle(input) << '\n'; // Aufruf per Copy-by-Value

Okt 23, 2024

lst-0714-book.cpp

// https://godbolt.org/z/4T7fjxdPa 
vector<int> prims{ 2,3,5,7,11 };
vector gerade{ 2,4,6,8,10 };
vector<int> soNicht{ 'a', 4.3, 8L };     //                                          (ERR)  "Narrowing" double nicht okay
vector<string> namen{ "sind", "nur" };   // konvertiert Argumente
vector schall{ "rauch", "qualm" };       // gefährlich: vector<const char[]>
vector nass{ "regen"s, "wasser"s };      // vector<string>
vector kalt{ "eis"sv, "pol"sv };         // vector<string_view>

Okt 23, 2024

lst-0716-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/addobjfsK 
vector<int> zeros(10);        // 10 Nullen
vector<int> sechsen(10, 6);   // 10 Sechsen
vector<int> zehn{10};         //                                          (ERR)  Achtung! Nur eine 10
vector<int> zehnSechs{10, 6}; //                                          (ERR)  Achtung! Zwei Elemente 10 und 6

Okt 23, 2024

lst-0739-book.cpp

// https://godbolt.org/z/fe8bev9Y9 
std::vector v{ 1, 2, 3, 4, 5, 6 };
v.erase(v.begin()+2, v.begin()+5); // v ist nun {1, 6}
v.erase(v.begin(), v.end());       // löscht den Rest

Okt 23, 2024

lst-0715-book.cpp

// https://godbolt.org/z/foPadWsKs 
#include <deque>
#include <ranges>                       // C++20
// …
std::deque in{1,2,33,34,35,99};
vector dreissig(in.begin()+2, in.begin()+5);
for(auto &e : dreissig) {
    cout << e << ' ';
}
cout << '\n';
namespace vs = std::ranges::views;      // C++20
auto v = in | vs::drop(2) | vs::take(3);
vector otuz(v.begin(), v.end());
vector trente(std::from_range, in);     // C++23

Okt 23, 2024

lst-0742-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y1W8WfxYn 
#include <array>
void berechne(const std::array<int,4>& data) { /* ... */ }
void berechne(const std::array<int,5>& data) { /* ... */ }

Okt 23, 2024

lst-0719-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vMa8bPaob 
#include <vector>
#include <iostream>
#include <algorithm>                // ranges::sort
using std::vector; using std::cout;
double median(vector<int> daten) {  // kopiert
    std::ranges::sort(daten);       // C++20, sonst std::sort()
    auto it = daten.begin();
    auto sz = daten.size();
    if(sz==0) return 0;             // Sonderfall
    // Median ermitteln:
    auto m = (it+sz/2);             // ungefähr die Mitte
    if(sz%2 != 0) {                 // ungerade Anzahl Elemente
        return *m;
    } else {                        // gerade Anzahl Elemente
        return double(*m + *(m-1)) / 2;
    }
}
int main() {
    vector daten1 { 12, 22, 34, 10, 1, 99, 33 };
    cout << median(daten1) << '\n'; // 22
    vector daten2 { 30, 2, 80, 99, 31, 3 };
    cout << median(daten2) << '\n'; // 30.5
}

Okt 23, 2024

lst-0723-book.cpp

// https://godbolt.org/z/evse4x8zK 
#include <vector>
#include <iostream>
#include <cstdio> // fopen, fclose, fwrite, fread, remove
using namespace std;
ostream& operator<<(ostream&os, const vector<int>&data) {
    for(auto &e : data) os << e << ' '; return os;
}
static const char* FILENAME = "nums.dat";
int main() {
  const vector nums{10,11,22,34};
  { // Schreiben
    auto out = fopen(FILENAME, "wb"); // Datei mit C zum Schreiben öffnen
    if(out==nullptr) {
        cerr << "Fehler beim Oeffnen\n"; return -1;
    }
    auto ok = fwrite(nums.data(), sizeof(int), nums.size(), out);
    if(ok!=nums.size()) {
        cerr << "Fehler beim Schreiben\n"; return -1;
    }
    fclose(out); // In C muss man explizit schließen. Ehrlich.
  }
  vector<int> gelesen{};
  { // Lesen
    auto in = fopen(FILENAME, "rb"); // Datei mit C zum Lesen öffnen
    if(in==nullptr) {
        cerr << "Fehler beim Oeffnen\n"; return -1;
    }
    const size_t sz = 4; // angenommen, wir wissen, wir lesen 4 Elemente …
    gelesen.resize(sz);  // Platz schaffen für zu lesende Daten
    auto ok = fread(gelesen.data(), sizeof(int), sz, in);
    if(ok!=sz) {
        cerr << "Fehler beim Lesen\n"; return -1;
    }
    fclose(in);
  }
  { // Vergleichen
    cout << nums << '\n';    // 10 11 22 34
    cout << gelesen << '\n'; // 10 11 22 34
  }
  if(remove(FILENAME) == -1) {
      cerr << "Warning: Fehler beim Loeschen\n";
  }
}

Okt 23, 2024

lst-0721-book.cpp

// https://godbolt.org/z/jGx51caTj 
#include <vector>
#include <iostream>
void printAndMore(const std::vector<int>& data) { // by-const-ref
    std::cout << data[0] << std::endl;
    data[0] = 666;  //                                          (ERR)  geht nicht, weil 'const int&'
}
int main() {
    std::vector zahlen {1,2,3};
    printAndMore(zahlen);
}

Okt 23, 2024

lst-0718-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6ahzhdjva 
vector vokale { 'A', 'e', 'i', 'o', 'u' };
const vector gerade { '0', '2', '4', '6', '8' };
auto it1 = vokale.begin();                 // vector<char>::iterator
*it1 = 'a';                                // '*it1' liefert 'char&' zurück
auto it2 = gerade.begin();                 // vector<char>::const_iterator
auto it3 = vokale.cbegin();                // erzwingt const_iterator
*i2 = '9'; *i3 = 'x';                      //                                          (ERR)  'const char&' ist nicht veränderbar
for(auto it=vokale.cbegin()+1; it!=vokale.cend(); ++it)
    { cout << *it; } cout << '\n';         // Ausgabe: eiou
for(auto it=vokale.crbegin()+1; it!=vokale.crend(); ++it) // ++ trotz reverse!
    { cout << *it; } cout << '\n';         // Ausgabe: oiea

Okt 23, 2024

lst-0743-book.cpp

// https://godbolt.org/z/nqbKT9GEa 
#include <array>
#include <numeric> // accumulate
#include <iostream>
template<size_t SZ>
int sumSz(const std::array<int,SZ>& data) {
    int result = 0;
    for(auto i=0uz; i<SZ; ++i)           // uz ist das Suffix für size_t seit C++23
        result += data[i];
    return result;
}
template<typename Elem, size_t SZ>
Elem sumElem(const std::array<Elem,SZ>& data) {
    Elem result {0};
    for(auto i=0uz; i<SZ; ++i)
        result += data[i];
    return result;
}
// C++20-Concept input_iterator, sonst typename
template<std::input_iterator It>
int sumIt(It begin, It end) {
    return std::accumulate(begin, end, 0);
}
int sumAuto(std::input_iterator auto begin, std::input_iterator auto end) {
    return std::accumulate(begin, end, 0);
}
// abgekürztes funktionstemplate mit auto
int main() {
   using namespace std;
   array<int,4> a4 { 1, 2, 5, 8 };
   cout << sumSz<4>(a4) << '\n';                  // Ausgabe: 16
   array<int,5> a5 { 1, -5, 3, 7, 2 };
   cout << sumElem(a5) << '\n';                   // Ausgabe: 8
   array<int,6> a6 { 1,2,3, 4,5,6 };
   cout << sumIt(a6.begin(), a6.end()) << '\n';   // Ausgabe: 21
   array a7 { 1,2,3, 4,5,6, 7 };                  // array<int,7>
   cout << sumIt(a7.begin(), a7.end()) << '\n';   // Ausgabe: 28
   cout << sumAuto(a7.begin(), a7.end()) << '\n'; // Ausgabe: 28
}

Okt 23, 2024

lst-0741-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xYsherrjs 
#include <vector>
#include <iostream>
#include <format> // C++20
using namespace std;
ostream& operator<<(ostream&os, const vector<int> &vec) {
  for(auto &elem : vec) { os << elem << ' '; } return os;
}
int main() {
  vector<int> data {};     // erzeugt einen leeren vector
  data.reserve(3);         // Platz für 3 Elemente
  cout << format("{}/{}\n", data.size(), data.capacity()); // 0/3
  data.push_back(111);     // ein Element hinzufügen
  data.resize(3);          // Größe verändern; hier fügt es neue Elemente an
  data.push_back(999);     // noch ein Element hinzufügen
  cout << format("{}/{}\n", data.size(), data.capacity()); // 4/6
  cout << data << '\n';    // 111, 0, 0, 999
  data.push_back(333);     // noch ein Element anfügen
  cout << data << '\n';    // 111, 0, 0, 999, 333
  data.reserve(1);         // nichts passiert, denn capacity() > 1
  data.resize(3);          // schrumpfen; Elemente werden entfernt
  cout << data << '\n';    // 111, 0, 0
  cout << format("{}/{}\n", data.size(), data.capacity()); // 3/6
  data.resize(6, 44);      // noch mal vergrößern, mit 44en auffüllen
  cout << data << '\n';    // 111, 0, 0, 44, 44, 44
}

Okt 23, 2024

lst-0720-book.cpp

// https://godbolt.org/z/aW3McGofx 
vector d{ 1, 2, 4, -1, 1, 2, -2 };
for(size_t idx=0; idx < d.size(); ) { // prüft vector-Grenze
    cout << d[idx] << ' ';            // zusätzliche Prüfung mit at nicht nötig
    idx += d[idx];                    // hier ebenso wenig
}
cout << '\n';
// Ausgabe: 1 2 -1 4 -2 1 2

Okt 23, 2024

lst-0728-book.cpp

// https://godbolt.org/z/h7jf4KM1q 
#include <vector>
#include <span>
#include <iostream>
using namespace std;
int sum(span<const int> bereich) { // C++20: span
   int sum = 0;
   for(auto e : bereich) {         // algorithm wäre besser …
    sum += e;
   }
   return sum;
}
int main() {
    vector data {1,2,3,4,5};
    cout << sum(data) << "\n";            // implizit Container zu span
    auto [b, e, sz] = make_tuple(begin(data), end(data), size(data));
    cout << sum(span{b,   sz-1}) << "\n"; // 1..4 (Iter, size)
    cout << sum(span{b+1, sz-1}) << "\n"; // 2..5 (Iter, size)
    cout << sum(span{b,   e-2}) << "\n";  // 1..3 (Iter, Iter)
    cout << sum(span{b+1, e-1}) << "\n";  // 2..4 (Iter, Iter)
    cout << sum(span{b+2, e  }) << "\n";  // 3..5 (Iter, Iter)
    return 0;
}

Okt 23, 2024

lst-0734-godb.cpp

//#(compile) c++; compiler:gsnapshot; options:"-std=c++23"; libs:-
// https://godbolt.org/z/n8jn7v5vb 
#include <mdspan>
#include <iostream>
#include <vector>
using namespace std;
int main() {
    // 1D: 12 Elemente
    vector v{1,2,3,4,5,6,7,8,9,10,11,12};
    // 2D: als 2 Zeilen mit je 6 ints
    auto ms2 = mdspan(v.data(), 2, 6);
    // 3D: als Quader mit 2 Ebenen, 3 Reihen, 2 Spalten
    auto ms3 = mdspan(v.data(), 2, 3, 2);
    // via 2D-Ansicht schreiben
    for (auto i = 0; i != ms2.extent(0); ++i)
      for (auto j = 0; j != ms2.extent(1); ++j)
        ms2[i, j] = i * 100 + j;  // schreiben via mehrdimensionalen Index
    // via 3D-Ansicht lesen
    for (auto i = 0; i != ms3.extent(0); ++i) {
      cout << "Ebene " << i << ":\n";
      for (auto j = 0; j != ms3.extent(1); ++j) {
        for (auto k = 0; k != ms3.extent(2); ++k)
          cout << " " << ms3[i, j, k];  // lesen via mehrdimensionalen Index
        cout << '\n';
      }
    }
    // Ausgabe: Ebene 0: 0 1, 2 3, 4 5, Ebene 1: 100 101, 102 103, 104 105
}

Okt 23, 2024

lst-0717-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Yb4jEdaKj 
vector<int> von{ 2,3,4 };
vector<int> nach{};
nach = von;                         // Zuweisung mit operator=, nun beide gleich

vector<int> abfluss{};
abfluss = std::move(von);           // Verschieben, nun ist 'von' leer
vector<int> v;
v.assign(4, 100);                   // v ist nun {100, 100, 100, 100}
v.assign(nach.begin(), nach.end()); // v ist nun {2,3,4}
int z[] = { 10, 20, 30, 40 };
v.assign(z+1, z+4);                 // v ist nun {20, 30, 40}

Okt 23, 2024

lst-0738-book.cpp

// https://godbolt.org/z/6836bdczd 
std::vector v{ 1, 2, 3, 4, 5, 6 };
for(auto it=v.begin(); it!=v.end(); ++it) {
  it = v.erase(it);
}
// Hier ist v: { 2, 4, 6 }

Okt 23, 2024

lst-0739-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fe8bev9Y9 
std::vector v{ 1, 2, 3, 4, 5, 6 };
v.erase(v.begin()+2, v.begin()+5); // v ist nun {1, 6}
v.erase(v.begin(), v.end());       // löscht den Rest

Okt 23, 2024

lst-0745-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KrbTrx1aG 
array<int,5> data{ 10, 11, 12, 13, 14};
cout << std::get<2>(data) << '\n'; // 12

Okt 23, 2024

lst-0722-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YhYs3z5Ex 
vector<string> autos{ "Diesel", "Benzin", "Super", "Gas" };
cout << autos[1] << '\n';             // Ausgabe: Benzin
autos.insert(autos.begin(), "Strom"); // verschiebt alles um eins nach hinten
cout << autos[1] << '\n';             // Ausgabe: Diesel

Okt 23, 2024

lst-0721-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jGx51caTj 
#include <vector>
#include <iostream>
void printAndMore(const std::vector<int>& data) { // by-const-ref
    std::cout << data[0] << std::endl;
    data[0] = 666;  //                                          (ERR)  geht nicht, weil 'const int&'
}
int main() {
    std::vector zahlen {1,2,3};
    printAndMore(zahlen);
}

Okt 23, 2024

lst-0720-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/aW3McGofx 
vector d{ 1, 2, 4, -1, 1, 2, -2 };
for(size_t idx=0; idx < d.size(); ) { // prüft vector-Grenze
    cout << d[idx] << ' ';            // zusätzliche Prüfung mit at nicht nötig
    idx += d[idx];                    // hier ebenso wenig
}
cout << '\n';
// Ausgabe: 1 2 -1 4 -2 1 2

Okt 23, 2024

lst-0735-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/P6MrKfaj9 
#include <vector>
#include <string>
struct Praesident {
  std::string name_; int jahr_;
  Praesident(std::string name,  int jahr)    // name ist by Value
    : name_{std::move(name)}, jahr_{jahr}    // move spart hier eine weitere Kopie
    { }
};
int main() {
    using namespace std; // Stringliterale ermöglichen
    vector<Praesident> praesidenten{};
    praesidenten.emplace_back("Heuss"s, 1949);
    praesidenten.emplace_back("Luebke"s, 1959);
    praesidenten.emplace_back("Heinemann"s, 1969);
    // 
    vector<int> v{};
    v.reserve(100);
    for(int idx = 0; idx < 100; ++idx)
        v.push_back(idx);
    // 
}

Okt 23, 2024

lst-0741-book.cpp

// https://godbolt.org/z/xYsherrjs 
#include <vector>
#include <iostream>
#include <format> // C++20
using namespace std;
ostream& operator<<(ostream&os, const vector<int> &vec) {
  for(auto &elem : vec) { os << elem << ' '; } return os;
}
int main() {
  vector<int> data {};     // erzeugt einen leeren vector
  data.reserve(3);         // Platz für 3 Elemente
  cout << format("{}/{}\n", data.size(), data.capacity()); // 0/3
  data.push_back(111);     // ein Element hinzufügen
  data.resize(3);          // Größe verändern; hier fügt es neue Elemente an
  data.push_back(999);     // noch ein Element hinzufügen
  cout << format("{}/{}\n", data.size(), data.capacity()); // 4/6
  cout << data << '\n';    // 111, 0, 0, 999
  data.push_back(333);     // noch ein Element anfügen
  cout << data << '\n';    // 111, 0, 0, 999, 333
  data.reserve(1);         // nichts passiert, denn capacity() > 1
  data.resize(3);          // schrumpfen; Elemente werden entfernt
  cout << data << '\n';    // 111, 0, 0
  cout << format("{}/{}\n", data.size(), data.capacity()); // 3/6
  data.resize(6, 44);      // noch mal vergrößern, mit 44en auffüllen
  cout << data << '\n';    // 111, 0, 0, 44, 44, 44
}

Okt 23, 2024

lst-0744-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PrM4fGcWo 
#include <array>
#include <iostream>
using std::array; using std::cout;
template<typename Elem, size_t SZ>
std::ostream& operator<<(std::ostream&os, const array<Elem,SZ>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os;
}
int main() {
   // Beispielcode hier
}

Okt 23, 2024

lst-0735-book.cpp

// https://godbolt.org/z/P6MrKfaj9 
#include <vector>
#include <string>
struct Praesident {
  std::string name_; int jahr_;
  Praesident(std::string name,  int jahr)    // name ist by Value
    : name_{std::move(name)}, jahr_{jahr}    // move spart hier eine weitere Kopie
    { }
};
int main() {
    using namespace std; // Stringliterale ermöglichen
    vector<Praesident> praesidenten{};
    praesidenten.emplace_back("Heuss"s, 1949);
    praesidenten.emplace_back("Luebke"s, 1959);
    praesidenten.emplace_back("Heinemann"s, 1969);
    // …
    vector<int> v{};
    v.reserve(100);
    for(int idx = 0; idx < 100; ++idx)
        v.push_back(idx);
    // …
}

Okt 23, 2024

lst-0715-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/foPadWsKs 
#include <deque>
#include <ranges>                       // C++20
// 
std::deque in{1,2,33,34,35,99};
vector dreissig(in.begin()+2, in.begin()+5);
for(auto &e : dreissig) {
    cout << e << ' ';
}
cout << '\n';
namespace vs = std::ranges::views;      // C++20
auto v = in | vs::drop(2) | vs::take(3);
vector otuz(v.begin(), v.end());
vector trente(std::from_range, in);     // C++23

Okt 23, 2024

lst-0716-book.cpp

// https://godbolt.org/z/addobjfsK 
vector<int> zeros(10);        // 10 Nullen
vector<int> sechsen(10, 6);   // 10 Sechsen
vector<int> zehn{10};         //                                          (ERR)  Achtung! Nur eine 10
vector<int> zehnSechs{10, 6}; //                                          (ERR)  Achtung! Zwei Elemente 10 und 6

Okt 23, 2024

lst-0695-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M1d9jEP74 
#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector numbers{ 1,2,3,4,5 };
    numbers.erase(numbers.begin(), numbers.end());
    cout << numbers.size() << "\n"; // Ausgabe: 0
}

Okt 23, 2024

lst-0672-book.cpp

// https://godbolt.org/z/c6W6EWb1K 
#include <typeinfo>               // operator typeid
#include <typeindex>              // type_index
#include <map>
#include <string>
#include <iostream>
template <typename T>
void output(std::ostream& os, T val) { // einen Typnamen ausgeben
    // static: beim ersten Mal initialisiert
    static const std::map<std::type_index,std::string> type_names {
        { std::type_index(typeid(const char*)), "const char*"},
        { std::type_index(typeid(char)), "char"},
        { std::type_index(typeid(int)), "int"},
        { std::type_index(typeid(double)), "double"},
        { std::type_index(typeid(bool)), "bool"},
    };
    const std::string name = type_names.at(std::type_index(typeid(T)));
    os << name << ": " << val << '\n';
}
// rekursives variadisches Funktionstemplate:
template<typename First, typename ... Rest>
void output(std::ostream &os, First first, Rest ... rest) {
    output(os, first);           // einzelner Aufruf mit vorderstem Element
    output(os, rest ...);        // Rekursion mit Rest der Elemente
}
int main() {
  output(std::cout, 3.1415);                      // normales Template
  output(std::cout, "ende", 2, 3.14, 'A', false); // rekursive variadische Funktion
}

Okt 23, 2024

lst-0700-book.cpp

// https://godbolt.org/z/TG1qd31Mq 
using namespace std; namespace views = std::ranges::views;
vector in { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
auto out = in
    | views::filter([](int i) { return i%3 == 0; })
    | views::transform([](int i) {return i*i; });

Okt 23, 2024

lst-0711-book.cpp

// https://godbolt.org/z/7zMP5fo7c 
vector<int> dataA;
vector<int> dataB{};
vector<int> dataC = {};   // keine Zuweisung
cout << format("{} {} {}\n", dataA.size(), dataB.size(), dataC.size()); // 0 0 0

Okt 23, 2024

lst-0710-book.cpp

// https://godbolt.org/z/WK86eaz1x 
#include <vector>
#include <iostream>
using std::vector; using std::cout;
template<typename T>
std::ostream& operator<<(std::ostream&os, const vector<T>& data) {
    for(const auto &e : data) {
        os << e << ' ';
    }
    return os;
}
int main() {h
   // Beispielcode hier
}

Okt 23, 2024

lst-0706-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7xYcqqh68 
#include <vector>
#include <iostream>   // cout
#include <iterator>   // ostream_iterator
#include <algorithm>  // copy

int main() {
  std::vector data { 1, 2, 3, 7, 9, 10 };
  std::ostream_iterator<int> out_it (std::cout,", "); // bei Zuweisung nach cout
  std::copy(data.begin(), data.end(), out_it); // alle Elemente in den Iterator
  std::cout << "\n";                           // Ausgabe: 1, 2, 3, 7, 9, 10,
  // oder ab C++20 mit Ranges:
  std::ranges::copy(data, out_it);
  std::cout << "\n";                           // Ausgabe: 1, 2, 3, 7, 9, 10,
}

Okt 23, 2024

lst-0683-book.cpp

// https://godbolt.org/z/KvsGh4f1v 
namespace lits {
  // Templatehilfsfunktion für ein Argument
  template<char C> int bin() {  // allgemeiner Fall
    if constexpr (C=='0') return 0;
    else if constexpr (C=='1') return 1;
  }
  // Templatehilfsfunktion ab zwei Argumente
  // 
}

Okt 23, 2024

lst-0680-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mevoshb3o 
namespace lits {
  long double operator"" _w(long double);
  string      operator"" _w(const char16_t*, size_t);
  unsigned    operator"" _w(const char*);
}
int main() {
  using namespace lits;
  1.2_w;       // operator"" _w(long double), mit (1.2L)
  u"one"_w;    // operator"" _w(char16_t, size_t), mit (u"one", 3)
  12_w;        // operator"" _w(const char*), mit "12"
  "two"_w;     //                                  (ERR)  operator"" _w(const char*, size_t) nicht definiert
}

Okt 23, 2024

lst-0697-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/babK485oT 
#include <vector>
#include <iostream>
int main() {
    std::vector<int> numbers{ 1,2,3,4,5 };
    for(auto it = begin(numbers); it != end(numbers); ++it) {
        auto val = *it;
        std::cout << val << ' ';
    }
    std::cout << '\n';
}

Okt 23, 2024

lst-0694-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qGrYPrqYn 
#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector nums{ 1,2,3 };
    vector vier{ 4,5,6 };
    vector sieben{ 7,8,9 } ;
    nums.insert(nums.begin(), vier.begin(), vier.end());
    cout << nums.size() << "\n";                      // Ausgabe: 9
    nums.insert_range(nums.begin(), sieben);          // C++23
}

Okt 23, 2024

lst-0707-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TzvK9hTsj 
#include <set>
#include <vector>
#include <iostream>
template<class T> class HappsAllocator  {
public:
    using value_type = T;
    T* allocate(size_t count) {
        size_t add = sizeof(T)*count;
        std::cout << "allocate("<<add<<"/"<<(buf_.size()-current_)<<")\n";
        if(current_+add > buf_.size()) throw std::bad_alloc{};
        char* result = buf_.data()+current_;
        current_ += add;
        return reinterpret_cast<T*>(result);
    }
    void deallocate(T* p, size_t count) {
        size_t del = sizeof(T)*count;
        std::cout << "deallocate("<<del<<")\n";
        if(del==current_ && p==reinterpret_cast<T*>(buf_.data())) {
            std::cout << "...alles frei.\n";
            current_ = 0;// alles wieder freigeben
        }
    }
    HappsAllocator() : HappsAllocator{1024} {}
    explicit HappsAllocator(size_t mx)
      : buf_(mx, 0), current_{0} { }
private:
       std::vector<char> buf_;
       size_t current_;
};
int main() {
    constexpr size_t ANZ = 1*1000*1000;
    using Happs = HappsAllocator<int>;
    try {
        Happs happs(ANZ*sizeof(int)); // Allokator vorbereiten
        std::vector<int,Happs> data(happs);
        data.reserve(ANZ);            // Speicher in einem Schwung holen
        for(int val=0; val < (int)ANZ; ++val)
            data.push_back(val);
    } catch(std::bad_alloc &ex) {
        std::cout << "Speicher alle.\n";
    }
}

Okt 23, 2024

lst-0709-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/c97qra3M7 
#include <vector>
#include <map>
#include <iostream>
using std::cout; using std::ostream;
template<typename K, typename T>
ostream& operator<<(ostream& os, std::pair<const K,T> value) {
    return os << '[' << value.first << ':' << value.second << ']';
}
int main() {
  {
    using Cont = std::vector<int>;
    Cont cont{ 1, 2, 3, 4, 5, 6 };
    Cont::size_type sz = cont.size();
    cout << "size=" << sz << " content= ";
    for(Cont::const_iterator it = cont.begin(); it != cont.end(); ++it) 
        cout << *it << ' ';
    cout << '\n';
  }
  {
    using Cont = std::map<int,char>;
    Cont cont{ {1,'a'}, {2,'b'}, {3,'c'}, {4,'d'}, {5,'e'}, {6,'f'} };
    Cont::size_type sz = cont.size();
    cout << "size=" << sz << " content= ";
    for(Cont::const_iterator it = cont.begin(); it != cont.end(); ++it) 
        cout << *it << ' ';
    cout << '\n';
  }
}

Okt 23, 2024

lst-0684-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cPoEjqzM7 
#include <iostream>
#include <string>
namespace lits {
    // operator"" _sx
    template<char...CS> std::string operator"" _sx() {
        return (std::string{} + ... + CS); // ein Faltausdruck
    };
}
int main() {
    using namespace lits;
    std::cout << 10000000_sx << '\n';     // Ausgabe: 10000000
    std::cout << 10'000'000_sx << '\n';   // Ausgabe: 10'000'000
    std::cout << 0x00af_sx << '\n';       // Ausgabe: 0x00af
    std::cout << 0x0'c'0'a'f_sx << '\n';  // Ausgabe: 0x0'c'0'a'f
    std::cout << 007_sx << '\n';          // Ausgabe: 007
    std::cout << 0b01_sx << '\n';         // Ausgabe: 0b01
}

Okt 23, 2024

lst-0672-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/c6W6EWb1K 
#include <typeinfo>               // operator typeid
#include <typeindex>              // type_index
#include <map>
#include <string>
#include <iostream>
template <typename T>
void output(std::ostream& os, T val) { // einen Typnamen ausgeben
    // static: beim ersten Mal initialisiert
    static const std::map<std::type_index,std::string> type_names {
        { std::type_index(typeid(const char*)), "const char*"},
        { std::type_index(typeid(char)), "char"},
        { std::type_index(typeid(int)), "int"},
        { std::type_index(typeid(double)), "double"},
        { std::type_index(typeid(bool)), "bool"},
    };
    const std::string name = type_names.at(std::type_index(typeid(T)));
    os << name << ": " << val << '\n';
}
// rekursives variadisches Funktionstemplate:
template<typename First, typename ... Rest>
void output(std::ostream &os, First first, Rest ... rest) {
    output(os, first);           // einzelner Aufruf mit vorderstem Element
    output(os, rest ...);        // Rekursion mit Rest der Elemente
}
int main() {
  output(std::cout, 3.1415);                      // normales Template
  output(std::cout, "ende", 2, 3.14, 'A', false); // rekursive variadische Funktion
}

Okt 23, 2024

lst-0696-book.cpp

// https://godbolt.org/z/Yv3vcxPv5 
#include <vector>
#include <iostream>
int main() {
    std::vector<int> numbers{ 1,2,3,4,5 };
    for(auto val : numbers) {
        std::cout << val << ' ';
    }
    std::cout << '\n';
}

Okt 23, 2024

lst-0679-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cjx49ef19 
namespace my {
  Complex operator"" _i(const char*); // 0+ni
  Complex operator"" _j(long double); // n+0i
  Puzzle operator"" _puzzle(const char*, size_t);
}
using namespace my;
Complex imag4 = 4_i;      // operator"" _i(const char*)
Complex real3 = 3.331_j;  // operator"" _j(long double)

Puzzle p1 = "oXo"         // operator"" _puzzle(const char*, size_t)
            "XoX"_puzzle;

Okt 23, 2024

lst-0698-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nj14e6Wq4 
#include <set>
#include <iostream>
int main() {
    std::set<int> numbers{ 10, 20, 90 };
    auto nein = numbers.find(30);
    if(nein == numbers.end()) { std::cout << "nicht da.\n"; }
    auto ja = numbers.find(20);
    if(ja != numbers.end()) { std::cout << *ja << '\n'; }
}

Okt 23, 2024

lst-0682-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sbxojqjqs 
namespace lits {
  // Templatehilfsfunktion für ein Argument
  template<char C> int bin();  // allgemeiner Fall
  template<>       int bin<'1'>() { return 1; } // Spezialisierung.
  template<>       int bin<'0'>() { return 0; } // Spezialisierung.
  // Templatehilfsfunktion ab zwei Argumente
  template<char C, char D, char... ES>
  int bin() {
    return bin<C>() << (sizeof...(ES)+1) | bin<D,ES...>(); // Bit-Shift, Bit-Oder
  }
  // eigentlicher operator""
  template<char...CS> int operator"" _bin()
    { return bin<CS...>(); };
}
int main() {
  using namespace lits;
  int eins = 1_bin;
  int acht = 1000_bin;
  int neun = 1001_bin;
  int zehn = 1010_bin;
  int elf  = 1011_bin;
  int hundertachtundzwanzig = 10000000_bin;
}

Okt 23, 2024

lst-0685-book.cpp

// https://godbolt.org/z/Yd4sser5j 
#include <complex>
// rohe Form
int operator"" _dual(const char*);
int answer = 101010_dual;    // dezimal 42
// vorverarbeitete Form
std::complex<long double> operator"" _i(long double d) {
  return std::complex<long double>(0, d);
}
auto val = 3.14_i; // val = std::complex<long double>(0, 3.14)

Okt 23, 2024

lst-0706-book.cpp

// https://godbolt.org/z/7xYcqqh68 
#include <vector>
#include <iostream>   // cout
#include <iterator>   // ostream_iterator
#include <algorithm>  // copy

int main() {
  std::vector data { 1, 2, 3, 7, 9, 10 };
  std::ostream_iterator<int> out_it (std::cout,", "); // bei Zuweisung nach cout
  std::copy(data.begin(), data.end(), out_it); // alle Elemente in den Iterator
  std::cout << "\n";                           // Ausgabe: 1, 2, 3, 7, 9, 10,
  // oder ab C++20 mit Ranges:
  std::ranges::copy(data, out_it);
  std::cout << "\n";                           // Ausgabe: 1, 2, 3, 7, 9, 10,
}

Okt 23, 2024

lst-0682-book.cpp

// https://godbolt.org/z/sbxojqjqs 
namespace lits {
  // Templatehilfsfunktion für ein Argument
  template<char C> int bin();  // allgemeiner Fall
  template<>       int bin<'1'>() { return 1; } // Spezialisierung.
  template<>       int bin<'0'>() { return 0; } // Spezialisierung.
  // Templatehilfsfunktion ab zwei Argumente
  template<char C, char D, char... ES>
  int bin() {
    return bin<C>() << (sizeof...(ES)+1) | bin<D,ES...>(); // Bit-Shift, Bit-Oder
  }
  // eigentlicher operator""
  template<char...CS> int operator"" _bin()
    { return bin<CS...>(); };
}
int main() {
  using namespace lits;
  int eins = 1_bin;
  int acht = 1000_bin;
  int neun = 1001_bin;
  int zehn = 1010_bin;
  int elf  = 1011_bin;
  int hundertachtundzwanzig = 10000000_bin;
}

Okt 23, 2024

lst-0684-book.cpp

// https://godbolt.org/z/cPoEjqzM7 
#include <iostream>
#include <string>
namespace lits {
    // operator"" _sx
    template<char...CS> std::string operator"" _sx() {
        return (std::string{} + ... + CS); // ein Faltausdruck
    };
}
int main() {
    using namespace lits;
    std::cout << 10000000_sx << '\n';     // Ausgabe: 10000000
    std::cout << 10'000'000_sx << '\n';   // Ausgabe: 10'000'000
    std::cout << 0x00af_sx << '\n';       // Ausgabe: 0x00af
    std::cout << 0x0'c'0'a'f_sx << '\n';  // Ausgabe: 0x0'c'0'a'f
    std::cout << 007_sx << '\n';          // Ausgabe: 007
    std::cout << 0b01_sx << '\n';         // Ausgabe: 0b01
}

Okt 23, 2024

lst-0685-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Yd4sser5j 
#include <complex>
// rohe Form
int operator"" _dual(const char*);
int answer = 101010_dual;    // dezimal 42
// vorverarbeitete Form
std::complex<long double> operator"" _i(long double d) {
  return std::complex<long double>(0, d);
}
auto val = 3.14_i; // val = std::complex<long double>(0, 3.14)

Okt 23, 2024

lst-0696-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Yv3vcxPv5 
#include <vector>
#include <iostream>
int main() {
    std::vector<int> numbers{ 1,2,3,4,5 };
    for(auto val : numbers) {
        std::cout << val << ' ';
    }
    std::cout << '\n';
}

Okt 23, 2024

lst-0709-book.cpp

// https://godbolt.org/z/c97qra3M7 
#include <vector>
#include <map>
#include <iostream>
using std::cout; using std::ostream;
template<typename K, typename T>
ostream& operator<<(ostream& os, std::pair<const K,T> value) {
    return os << '[' << value.first << ':' << value.second << ']';
}
int main() {
  {
    using Cont = std::vector<int>;
    Cont cont{ 1, 2, 3, 4, 5, 6 };
    Cont::size_type sz = cont.size();
    cout << "size=" << sz << " content= ";
    for(Cont::const_iterator it = cont.begin(); it != cont.end(); ++it) 
        cout << *it << ' ';
    cout << '\n';
  }
  {
    using Cont = std::map<int,char>;
    Cont cont{ {1,'a'}, {2,'b'}, {3,'c'}, {4,'d'}, {5,'e'}, {6,'f'} };
    Cont::size_type sz = cont.size();
    cout << "size=" << sz << " content= ";
    for(Cont::const_iterator it = cont.begin(); it != cont.end(); ++it) 
        cout << *it << ' ';
    cout << '\n';
  }
}

Okt 23, 2024

lst-0707-book.cpp

// https://godbolt.org/z/TzvK9hTsj 
#include <set>
#include <vector>
#include <iostream>
template<class T> class HappsAllocator  {
public:
    using value_type = T;
    T* allocate(size_t count) {
        size_t add = sizeof(T)*count;
        std::cout << "allocate("<<add<<"/"<<(buf_.size()-current_)<<")\n";
        if(current_+add > buf_.size()) throw std::bad_alloc{};
        char* result = buf_.data()+current_;
        current_ += add;
        return reinterpret_cast<T*>(result);
    }
    void deallocate(T* p, size_t count) {
        size_t del = sizeof(T)*count;
        std::cout << "deallocate("<<del<<")\n";
        if(del==current_ && p==reinterpret_cast<T*>(buf_.data())) {
            std::cout << "...alles frei.\n";
            current_ = 0;// alles wieder freigeben
        }
    }
    HappsAllocator() : HappsAllocator{1024} {}
    explicit HappsAllocator(size_t mx)
      : buf_(mx, 0), current_{0} { }
private:
       std::vector<char> buf_;
       size_t current_;
};
int main() {
    constexpr size_t ANZ = 1*1000*1000;
    using Happs = HappsAllocator<int>;
    try {
        Happs happs(ANZ*sizeof(int)); // Allokator vorbereiten
        std::vector<int,Happs> data(happs);
        data.reserve(ANZ);            // Speicher in einem Schwung holen
        for(int val=0; val < (int)ANZ; ++val)
            data.push_back(val);
    } catch(std::bad_alloc &ex) {
        std::cout << "Speicher alle.\n";
    }
}

Okt 23, 2024

lst-0711-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7zMP5fo7c 
vector<int> dataA;
vector<int> dataB{};
vector<int> dataC = {};   // keine Zuweisung
cout << format("{} {} {}\n", dataA.size(), dataB.size(), dataC.size()); // 0 0 0

Okt 23, 2024

lst-0694-book.cpp

// https://godbolt.org/z/qGrYPrqYn 
#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector nums{ 1,2,3 };
    vector vier{ 4,5,6 };
    vector sieben{ 7,8,9 } ;
    nums.insert(nums.begin(), vier.begin(), vier.end());
    cout << nums.size() << "\n";                      // Ausgabe: 9
    nums.insert_range(nums.begin(), sieben);          // C++23
}

Okt 23, 2024

lst-0699-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/arfee3TTP 
using namespace std;
vector in { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
vector<int> tmp{};
vector<int> out{};
copy_if(in.begin(), in.end(), back_inserter(tmp), [](int i) { return i%3 == 0; });
transform(tmp.begin(), tmp.end(), back_inserter(out), [](int i) {return i*i; });

Okt 23, 2024

lst-0681-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5rdzn8YP4 
namespace lits {
  // allgemeines Template
  template<char...> int operator"" _bin2();
  // Spezialisierungen
  template<> int operator"" _bin2<'0','0'>() { return 0; }
  template<> int operator"" _bin2<'0','1'>() { return 1; }
  template<> int operator"" _bin2<'1','0'>() { return 2; }
  template<> int operator"" _bin2<'1','1'>() { return 3; }
}
int main() {
  using namespace lits;
  int one   = 01_bin2;
  int three = 11_bin2;
}

Okt 23, 2024

lst-0702-book.cpp

// https://godbolt.org/z/dxb98rWzo 
#include <iostream>                // cout
#include <vector>
using std::vector;

vector<int> createData(size_t sz) {
    return vector<int>(sz);        // sz x null
}
void fibonacci(vector<int> &data) {
    for(auto it = begin(data)+2; it != end(data); ++it) { // iterator it
        *it = *(it-1) + *(it-2);
    }
}

std::ostream& show(std::ostream &os, const vector<int> &data) {
    for(auto it=begin(data); it != end(data); ++it)       // const_iterator it
        std::cout << *it << " ";
    return os;
}

int main() {
    vector<int> data = createData(10);
    data[0] = 1;
    data[1] = 1;
    fibonacci(data);
    show(std::cout, data) << "\n";
}

Okt 23, 2024

lst-0683-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KvsGh4f1v 
namespace lits {
  // Templatehilfsfunktion für ein Argument
  template<char C> int bin() {  // allgemeiner Fall
    if constexpr (C=='0') return 0;
    else if constexpr (C=='1') return 1;
  }
  // Templatehilfsfunktion ab zwei Argumente
  // 
}

Okt 23, 2024

lst-0700-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TG1qd31Mq 
using namespace std; namespace views = std::ranges::views;
vector in { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
auto out = in
    | views::filter([](int i) { return i%3 == 0; })
    | views::transform([](int i) {return i*i; });

Okt 23, 2024

lst-0681-book.cpp

// https://godbolt.org/z/5rdzn8YP4 
namespace lits {
  // allgemeines Template
  template<char...> int operator"" _bin2();
  // Spezialisierungen
  template<> int operator"" _bin2<'0','0'>() { return 0; }
  template<> int operator"" _bin2<'0','1'>() { return 1; }
  template<> int operator"" _bin2<'1','0'>() { return 2; }
  template<> int operator"" _bin2<'1','1'>() { return 3; }
}
int main() {
  using namespace lits;
  int one   = 01_bin2;
  int three = 11_bin2;
}

Okt 23, 2024

lst-0671-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/baPeoTbM8 
template<>   // vollständige Spezialisierung
class MyPair<std::string, std::string> {
    std::vector<std::string> data_;
public:
    MyPair(const std::string& t, const std::string& u) : data_{t, u} { }
};
int main() {
    // nutzt die vollständige Spezialisierung:
    MyPair<std::string,std::string> strStr{"c","d"};
}

Okt 23, 2024

lst-0680-book.cpp

// https://godbolt.org/z/Mevoshb3o 
namespace lits {
  long double operator"" _w(long double);
  string      operator"" _w(const char16_t*, size_t);
  unsigned    operator"" _w(const char*);
}
int main() {
  using namespace lits;
  1.2_w;       // operator"" _w(long double), mit (1.2L)
  u"one"_w;    // operator"" _w(char16_t, size_t), mit (u"one", 3)
  12_w;        // operator"" _w(const char*), mit "12"
  "two"_w;     //                                  (ERR)  operator"" _w(const char*, size_t) nicht definiert
}

Okt 23, 2024

lst-0710-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WK86eaz1x 
#include <vector>
#include <iostream>
using std::vector; using std::cout;
template<typename T>
std::ostream& operator<<(std::ostream&os, const vector<T>& data) {
    for(const auto &e : data) {
        os << e << ' ';
    }
    return os;
}
int main() {h
   // Beispielcode hier
}

Okt 23, 2024

lst-0678-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8oYaWYnbx 
#include <tuple>
#include <iostream>
template<typename ... Args>
auto conv2tuple(Args ... args) {
    return std::make_tuple(args...);
}
int main() {
    auto mytuple = conv2tuple("ende", 2, 3.14, 'A', false);
    std::cout << std::get<2>(mytuple) << '\n'; // Ausgabe: 3.14
}

Okt 23, 2024

lst-0699-book.cpp

// https://godbolt.org/z/arfee3TTP 
using namespace std;
vector in { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
vector<int> tmp{};
vector<int> out{};
copy_if(in.begin(), in.end(), back_inserter(tmp), [](int i) { return i%3 == 0; });
transform(tmp.begin(), tmp.end(), back_inserter(out), [](int i) {return i*i; });

Okt 23, 2024

lst-0702-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dxb98rWzo 
#include <iostream>                // cout
#include <vector>
using std::vector;

vector<int> createData(size_t sz) {
    return vector<int>(sz);        // sz x null
}
void fibonacci(vector<int> &data) {
    for(auto it = begin(data)+2; it != end(data); ++it) { // iterator it
        *it = *(it-1) + *(it-2);
    }
}

std::ostream& show(std::ostream &os, const vector<int> &data) {
    for(auto it=begin(data); it != end(data); ++it)       // const_iterator it
        std::cout << *it << " ";
    return os;
}

int main() {
    vector<int> data = createData(10);
    data[0] = 1;
    data[1] = 1;
    fibonacci(data);
    show(std::cout, data) << "\n";
}

Okt 23, 2024

lst-0698-book.cpp

// https://godbolt.org/z/nj14e6Wq4 
#include <set>
#include <iostream>
int main() {
    std::set<int> numbers{ 10, 20, 90 };
    auto nein = numbers.find(30);
    if(nein == numbers.end()) { std::cout << "nicht da.\n"; }
    auto ja = numbers.find(20);
    if(ja != numbers.end()) { std::cout << *ja << '\n'; }
}

Okt 23, 2024

lst-0695-book.cpp

// https://godbolt.org/z/M1d9jEP74 
#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector numbers{ 1,2,3,4,5 };
    numbers.erase(numbers.begin(), numbers.end());
    cout << numbers.size() << "\n"; // Ausgabe: 0
}

Okt 23, 2024

lst-0678-book.cpp

// https://godbolt.org/z/8oYaWYnbx 
#include <tuple>
#include <iostream>
template<typename ... Args>
auto conv2tuple(Args ... args) {
    return std::make_tuple(args...);
}
int main() {
    auto mytuple = conv2tuple("ende", 2, 3.14, 'A', false);
    std::cout << std::get<2>(mytuple) << '\n'; // Ausgabe: 3.14
}

Okt 23, 2024

lst-0697-book.cpp

// https://godbolt.org/z/babK485oT 
#include <vector>
#include <iostream>
int main() {
    std::vector<int> numbers{ 1,2,3,4,5 };
    for(auto it = begin(numbers); it != end(numbers); ++it) {
        auto val = *it;
        std::cout << val << ' ';
    }
    std::cout << '\n';
}

Okt 23, 2024

lst-0679-book.cpp

// https://godbolt.org/z/cjx49ef19 
namespace my {
  Complex operator"" _i(const char*); // 0+ni
  Complex operator"" _j(long double); // n+0i
  Puzzle operator"" _puzzle(const char*, size_t);
}
using namespace my;
Complex imag4 = 4_i;      // operator"" _i(const char*)
Complex real3 = 3.331_j;  // operator"" _j(long double)

Puzzle p1 = "oXo"         // operator"" _puzzle(const char*, size_t)
            "XoX"_puzzle;

Okt 23, 2024

lst-0648-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Tcxnr6jTM 
template<typename T>
  concept dbl_quotable = copyable<T> &&
  requires (T t) { mk_string(t) + mk_string(t); } &&
  requires(T t) {
    {mk_string(t)} -> same_as<string>;
  };
string dbl_quote(const dbl_quotable auto& val) {
  auto val2{val}; // Kopie erzeugen (nur zu Demozwecken)
  return '"' + mk_string(val) + mk_string(val2) + '"';
}

Okt 23, 2024

lst-0670-book.cpp

// https://godbolt.org/z/Y6v6cKE3v 
#include <string>
#include <tuple>
#include <concepts>             // copyable, C++20
template <std::copyable T, std::copyable U=T> // allgemeiner Fall
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t, const U& u) : data01_{t}, data02_{u} {}
};
template <std::copyable T>      // teilweise Spezialisierung, T bleibt formal
class MyPair<T, std::string> {  // U ist auf string spezialisiert
    std::tuple<T,std::string> data_;
public:
    MyPair(const T& t, const std::string& str) : data_{t, str} { }
};
template <std::copyable U>      // teilweise Spezialisierung, U bleibt formal
class MyPair<std::string, U> {  // T ist auf string spezialisiert
    std::tuple<std::string, U> data_;
public:
    MyPair(const std::string& str, const U& u) : data_{str, u} { }
};
int main() {
  // nutzt partielle Spezialisierung
  MyPair<int,std::string> intString{1, "a"};
  MyPair<std::string,int> stringInt{"b", 2};

  MyPair<int,int> intInt{3,4};                     // nutzt allgemeinen Fall
  MyPair intInt2{3,4};                             // auch MyPair<int,int>
  MyPair<std::string,std::string> strStr{"c","d"}; //                                          (ERR)  mehrdeutig
}

Okt 23, 2024

lst-0665-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xPrheoeEd 
#include <iostream>
template <typename T, size_t n=1>    // Non-Type-Parameter mit Defaultwert
class FixedArray {
    T data_[n] {0};                  // Non-Type-Parameter verwenden
public:
    T& operator[](size_t index) { return data_[index]; }
    static constexpr size_t size() { return n; }
    void print(std::ostream &os) const {
        for(auto it : data_)
            os << it << ' ';
        os << '\n';
    }
};
int main() {
    FixedArray<int,10> vals {};        // n = 10
    for(size_t idx=0; idx < vals.size(); ++idx) {
        vals[idx] = idx+idx;
    }
    vals.print(std::cout);             // Ausgabe: 0 2 4 6 8 10 12 14 16 18
    FixedArray<double> dvals;          // Defaultparameter für n
    std::cout << dvals.size() << '\n'; // Ausgabe: 1
}

Okt 23, 2024

lst-0646-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eaGre4bqr 
auto min2(const std::integral auto &a, const std::integral auto &b) {
    return a<b ? a : b;
};

auto min3 = []<std::integral T>(const T &a, const T &b, const T &c) {
    return min2(a, min2(b,c));
};

int main() {
    cout << min3( 3, 7, 2 ) << '\n';
    cout << min3( 8.11, 113.2, -3.1 ) << '\n'; //                                  (ERR)  Fehler: kein integraler Typ

Okt 23, 2024

lst-0643-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/W6cdra8K9 
#include <concepts>  // integral
#include <iostream>
using namespace std;
// Concept explizit mit requires
template<typename T> requires integral<T>
auto add_1(T val) { return val+1; }
// abgekürztes Concept
template<integral T>
auto add_2(T val) { return val+2; }
// abgekürztes Funktionstemplate mit Concept
auto add_3(integral auto val) { return val+3; }
// Ad-hoc-requires für Funktionstemplate
auto add_4(auto val) requires integral<decltype(val)>
{ return val+4; }
int main() {
  cout << add_1(1) << '\n';              // Ausgabe: 2
  cout << add_2(1) << '\n';              // Ausgabe: 3
  cout << add_3(1) << '\n';              // Ausgabe: 4
  cout << add_4(1) << '\n';              // Ausgabe: 5
  cout << add_3("text") << '\n';         //                                  (ERR)  Fehler
  integral auto val = add_1(99);         // auch für auto-Variablen
  cout << val << '\n';                   // Ausgabe: 100
}

Okt 23, 2024

lst-0661-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dMTnbT1v4 
#include <iostream>
#include <concepts>    // copyable, C+20
template<std::copyable T, std::copyable U>
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t,const U& u) : data01_{t}, data02_{u} {}
    void print(std::ostream& os) const {
        os << data01_ << " : " << data02_ << std::endl;
    }
};
int main() {
    std::string month{"Januar"};
    int temp = -5;
    MyPair<std::string, int> temperatur{month, temp};
    temperatur.print(std::cout);
}

Okt 23, 2024

lst-0649-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9qsGW6M8Y 
template<std::ranges::range T>         // eine Range über Typ T
using ValueTypeOfRange = std::ranges::range_value_t<T>;
// oder
template<typename T>
requires std::ranges::range<T>         // eine Range über Typ T
using ValueTypeOfRange = std::ranges::range_value_t<T>;
// ergibt:
ValueTypeOfRange<std::vector<int>> x;  // x ist int
ValueTypeOfRange<std::string> y;       // y ist char
ValueTypeOfRange<std::list<double>> z; // z ist double
ValueTypeOfRange<int> w;               //                                  (ERR)  int ist keine Range

Okt 23, 2024

lst-0647-book.cpp

// https://godbolt.org/z/orTK9daa3 
#include <concepts>
#include <iostream>
#include <string>
using namespace std; using namespace std::literals;

string mk_string(integral auto val) { return to_string(val); }
string mk_string(string val) { return '['+val+']'; }
template<typename T>
  requires copyable<T> &&                            // Typanforderung
  requires (T t) { mk_string(t) + mk_string(t); } && // einfache Anforderung
  requires (T t) {                     // zusammengesetzte Anforderung
    {mk_string(t)} -> same_as<string>; // gültiger Ausdruck muss Bedingung erfüllen
  }
string dbl_quote(const T& val) {
  T val2{val};                      // Kopie erzeugen (nur zu Demozwecken)
  return '"' + mk_string(val) + mk_string(val2) + '"';
}
int main() {
  cout << dbl_quote(10) << '\n';    // Ausgabe: "1010"
  cout << dbl_quote("ab"s) << '\n'; // Ausgabe: "[ab][ab]"
  cout << dbl_quote(3.14) << '\n';  //                                  (ERR)  Fehler: keine passende mk_string-Überladung
}

Okt 23, 2024

lst-0623-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/53EcTMo3e 
set<Zwerg,NachJahr> zwerge2{begin(zwerge), end(zwerge)};
for(const auto& z : zwerge2) // anders sortierte Ausgabe
    cout << z.jahr_ << " ";

Okt 23, 2024

lst-0634-book.cpp

// https://godbolt.org/z/ers9eWPbG 
#include <vector>
#include <string>
#include <algorithm> // sort
#include <iostream>  // cout
using std::string; using std::vector; using std::cout;
// wie zuvor
int main() {
    vector zwerge{    // wie zuvor
    /* sortieren */
    bool rueckwaerts = true; // oder false. Variable außerhalb des Lambdas
    std::ranges::sort(zwerge,
        [rueckwaerts](const Zwerg& a, const Zwerg& b) {
            if(rueckwaerts)
                return a.name_ > b.name_;
            else
                return a.name_ < b.name_;
        }
    );
    /* ausgeben */
    for(const auto& z : zwerge) // rückwärts: "Thorin" bis "Balin"
        cout << z.name_  << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0659-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7KzcWE8Pz 
#include <string>
#include <vector>
#include <set>
#include <tuple>
#include <memory> // shared_ptr
template <typename T>
class MyStuff {
    T data_;
public:
    MyStuff() : data_{} {}             // default c'tor
    MyStuff(const T& d) : data_{d} { } // copy c'tor
    T getStuff() const { return data_; }
};
class IntValue {
    int val_;
public:
    explicit IntValue(int val=0) : val_(val) {}
    int getInt() const { return val_; }
};
int main() {
    MyStuff intStuff(12);              // wird zu MyStuff<int>
    std::vector vs{ 1,2,3,4 };         // wird zu vector<int>
    MyStuff ivalStuff{ IntValue{33} }; // wird zu MyStuff<IntValue>
    std::tuple tpl{ 23, 'a' };         // wird zu tuple<int,char>
    std::set zweiDrei (vs.begin()+1, vs.end()-1); // wird zu set<int>
    // Kann der Compiler nicht deduzieren:
    MyStuff<double> dblStuff;              // kein Konstruktorargument
    std::vector<char> vcs(10);             // Größe 10, aber von welchem Typ?
    std::shared_ptr<int> ptr{new int{88}}; // keine Regel für int*
}

Okt 23, 2024

lst-0638-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8GxPMEc5o 
#include <iostream>
int main() {
    int count = 0;
    auto plus1 = [&count](int x) { // count als Referenz
        ++count; return x+1;
    };
    for(int i=0; i<5; ++i) { plus1(i); }
    std::cout << "plus1 wurde " << count << " Mal aufgerufen\n";
    // Ausgabe: plus1 wurde 5 Mal aufgerufen
}

Okt 23, 2024

lst-0657-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M6earoWMn 
#include <iostream>
#include <string>
#include <concepts>    // copyable, C++20
template <std::copyable T>
class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; } // allgemeiner Fall
    T getData() const { return data_; }     // allgemeiner Fall
};
template<>                                  // Spezialisierung
void MyContainer<std::string>::setData(const std::string& d) {
    data_ = "[" + d + "]";
}
int main() {
    MyContainer<std::string> mcString;
    mcString.setData("Geschichte");
    std::cout << mcString.getData() << '\n';  // Ausgabe: [Geschichte]
    MyContainer<int> mcInt;
    mcInt.setData(5);
    std::cout << mcInt.getData() << '\n';     // Ausgabe: 5
}

Okt 23, 2024

lst-0665-book.cpp

// https://godbolt.org/z/xPrheoeEd 
#include <iostream>
template <typename T, size_t n=1>    // Non-Type-Parameter mit Defaultwert
class FixedArray {
    T data_[n] {0};                  // Non-Type-Parameter verwenden
public:
    T& operator[](size_t index) { return data_[index]; }
    static constexpr size_t size() { return n; }
    void print(std::ostream &os) const {
        for(auto it : data_)
            os << it << ' ';
        os << '\n';
    }
};
int main() {
    FixedArray<int,10> vals {};        // n = 10
    for(size_t idx=0; idx < vals.size(); ++idx) {
        vals[idx] = idx+idx;
    }
    vals.print(std::cout);             // Ausgabe: 0 2 4 6 8 10 12 14 16 18
    FixedArray<double> dvals;          // Defaultparameter für n
    std::cout << dvals.size() << '\n'; // Ausgabe: 1
}

Okt 23, 2024

lst-0641-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YWe15Ehd8 
#include <iostream>
#include <string>
using std::cout; using std::string; using namespace std::literals;
auto min2 = [](const auto &a, const auto &b) {
    return a<b ? a : b;
};
auto min3 = [](const auto &a, const auto &b, const auto &c) {
    return min2(a, min2(b,c));
};
int main() {
    cout << min3( 3, 7, 2 ) << '\n';                  // Ausgabe: 2
    cout << min3( 8.11, 113.2, -3.1 ) << '\n';        // Ausgabe: 3.1
    cout << min3( "Zoo"s, "Affe"s, "Muli"s ) << '\n'; // Ausgabe: Affe
}

Okt 23, 2024

lst-0648-book.cpp

// https://godbolt.org/z/Tcxnr6jTM 
template<typename T>
  concept dbl_quotable = copyable<T> &&
  requires (T t) { mk_string(t) + mk_string(t); } &&
  requires(T t) {
    {mk_string(t)} -> same_as<string>;
  };
string dbl_quote(const dbl_quotable auto& val) {
  auto val2{val}; // Kopie erzeugen (nur zu Demozwecken)
  return '"' + mk_string(val) + mk_string(val2) + '"';
}

Okt 23, 2024

lst-0658-book.cpp

// https://godbolt.org/z/9vP3o68bW 
#include <iostream>
#include <string>
#include <concepts>    // copyable, C++20
template <std::copyable T>

class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; }
    T getData() const { return data_; }
};

class IntValue {
    int val_;
public:
    explicit IntValue(int val=0) : val_(val) {}
    int getInt() const { return val_; }
};
int main() {
    // C-Array mit drei MyContainer<double>-Instanzen
    MyContainer<double> dcont[3];
    dcont[0].setData(123.123);
    dcont[1].setData(234.234);
    std::cout << dcont[0].getData() << std::endl;
    std::cout << dcont[1].getData() << std::endl;
    // eigener Datentyp als formaler Parameter
    IntValue ival{100'000};
    MyContainer<IntValue> scont;
    scont.setData(ival);
    std::cout << scont.getData().getInt() << std::endl;
    // string als formaler Parameter
    std::string str("Text");
    MyContainer<std::string> strCont;
    strCont.setData(str);
    std::cout << strCont.getData() << std::endl;
}

Okt 23, 2024

lst-0643-book.cpp

// https://godbolt.org/z/W6cdra8K9 
#include <concepts>  // integral
#include <iostream>
using namespace std;
// Concept explizit mit requires
template<typename T> requires integral<T>
auto add_1(T val) { return val+1; }
// abgekürztes Concept
template<integral T>
auto add_2(T val) { return val+2; }
// abgekürztes Funktionstemplate mit Concept
auto add_3(integral auto val) { return val+3; }
// Ad-hoc-requires für Funktionstemplate
auto add_4(auto val) requires integral<decltype(val)>
{ return val+4; }
int main() {
  cout << add_1(1) << '\n';              // Ausgabe: 2
  cout << add_2(1) << '\n';              // Ausgabe: 3
  cout << add_3(1) << '\n';              // Ausgabe: 4
  cout << add_4(1) << '\n';              // Ausgabe: 5
  cout << add_3("text") << '\n';         //                                  (ERR)  Fehler
  integral auto val = add_1(99);         // auch für auto-Variablen
  cout << val << '\n';                   // Ausgabe: 100
}

Okt 23, 2024

lst-0649-book.cpp

// https://godbolt.org/z/9qsGW6M8Y 
template<std::ranges::range T>         // eine Range über Typ T
using ValueTypeOfRange = std::ranges::range_value_t<T>;
// oder
template<typename T>
requires std::ranges::range<T>         // eine Range über Typ T
using ValueTypeOfRange = std::ranges::range_value_t<T>;
// ergibt:
ValueTypeOfRange<std::vector<int>> x;  // x ist int
ValueTypeOfRange<std::string> y;       // y ist char
ValueTypeOfRange<std::list<double>> z; // z ist double
ValueTypeOfRange<int> w;               //                                  (ERR)  int ist keine Range

Okt 23, 2024

lst-0637-book.cpp

// https://godbolt.org/z/zMWo69974 
#include <iostream>
int main() {
    int count = 0;
    auto plus1 = [count](int x) mutable { // count als Kopie
        std::cout << ++count; return x+1;
    };
    for(int i=0; i<5; ++i) {
        plus1(i);
    }
    std::cout << "\n";
    // Ausgabe: 12345
}

Okt 23, 2024

lst-0661-book.cpp

// https://godbolt.org/z/dMTnbT1v4 
#include <iostream>
#include <concepts>    // copyable, C+20
template<std::copyable T, std::copyable U>
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t,const U& u) : data01_{t}, data02_{u} {}
    void print(std::ostream& os) const {
        os << data01_ << " : " << data02_ << std::endl;
    }
};
int main() {
    std::string month{"Januar"};
    int temp = -5;
    MyPair<std::string, int> temperatur{month, temp};
    temperatur.print(std::cout);
}

Okt 23, 2024

lst-0637-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zMWo69974 
#include <iostream>
int main() {
    int count = 0;
    auto plus1 = [count](int x) mutable { // count als Kopie
        std::cout << ++count; return x+1;
    };
    for(int i=0; i<5; ++i) {
        plus1(i);
    }
    std::cout << "\n";
    // Ausgabe: 12345
}

Okt 23, 2024

lst-0635-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4zYsWW9Wq 
#include <vector>
#include <string>
#include <algorithm> // sort
#include <iostream>  // cout
using std::string; using std::vector; using std::cout;
// wie zuvor
int main() {
    vector zwerge{           // wie zuvor
    /* sortieren */
    bool rueckwaerts = true; // oder false. Variable außerhalb des Lambdas
    unsigned richtigrum = 0; // zählt < mit
    unsigned falschrum = 0;  // zählt > mit
    std::ranges::sort(zwerge,
        [rueckwaerts,&falschrum,&richtigrum](const Zwerg& a, const Zwerg& b) {
            bool result = rueckwaerts
                ? a.name_ > b.name_
                : a.name_ < b.name_;
            if(result==false) ++falschrum; else ++richtigrum;
            return result;
        }
    );
    /* ausgeben */
    cout << "Falschrum:" << falschrum << " Richtigrum: " << richtigrum << "\n";
    for(const auto& z : zwerge) // rückwärts: "Thorin" bis "Balin"
        cout << z.name_  << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0623-book.cpp

// https://godbolt.org/z/53EcTMo3e 
set<Zwerg,NachJahr> zwerge2{begin(zwerge), end(zwerge)};
for(const auto& z : zwerge2) // anders sortierte Ausgabe
    cout << z.jahr_ << " ";

Okt 23, 2024

lst-0654-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jqzTMxYKv 
template <std::copyable T>      // C++20-Concept
class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; }
    T getData() const { return data_; }
};

Okt 23, 2024

lst-0635-book.cpp

// https://godbolt.org/z/4zYsWW9Wq 
#include <vector>
#include <string>
#include <algorithm> // sort
#include <iostream>  // cout
using std::string; using std::vector; using std::cout;
// wie zuvor
int main() {
    vector zwerge{           // wie zuvor
    /* sortieren */
    bool rueckwaerts = true; // oder false. Variable außerhalb des Lambdas
    unsigned richtigrum = 0; // zählt < mit
    unsigned falschrum = 0;  // zählt > mit
    std::ranges::sort(zwerge,
        [rueckwaerts,&falschrum,&richtigrum](const Zwerg& a, const Zwerg& b) {
            bool result = rueckwaerts
                ? a.name_ > b.name_
                : a.name_ < b.name_;
            if(result==false) ++falschrum; else ++richtigrum;
            return result;
        }
    );
    /* ausgeben */
    cout << "Falschrum:" << falschrum << " Richtigrum: " << richtigrum << "\n";
    for(const auto& z : zwerge) // rückwärts: "Thorin" bis "Balin"
        cout << z.name_  << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0638-book.cpp

// https://godbolt.org/z/8GxPMEc5o 
#include <iostream>
int main() {
    int count = 0;
    auto plus1 = [&count](int x) { // count als Referenz
        ++count; return x+1;
    };
    for(int i=0; i<5; ++i) { plus1(i); }
    std::cout << "plus1 wurde " << count << " Mal aufgerufen\n";
    // Ausgabe: plus1 wurde 5 Mal aufgerufen
}

Okt 23, 2024

lst-0662-book.cpp

// https://godbolt.org/z/jbafeEdoW 
#include <iostream>
#include <concepts>    // copyable, C++20
template<std::copyable T, std::copyable U=T>
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t,const U& u) : data01_{t}, data02_{u} {}
    void print(std::ostream& os) const {
        os << data01_ << " : " << data02_ << std::endl;
    }
};
int main() {
    MyPair<double> zahlen{11.11, 22.22};
    zahlen.print(std::cout);
}

Okt 23, 2024

lst-0662-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jbafeEdoW 
#include <iostream>
#include <concepts>    // copyable, C++20
template<std::copyable T, std::copyable U=T>
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t,const U& u) : data01_{t}, data02_{u} {}
    void print(std::ostream& os) const {
        os << data01_ << " : " << data02_ << std::endl;
    }
};
int main() {
    MyPair<double> zahlen{11.11, 22.22};
    zahlen.print(std::cout);
}

Okt 23, 2024

lst-0646-book.cpp

// https://godbolt.org/z/eaGre4bqr 
auto min2(const std::integral auto &a, const std::integral auto &b) {
    return a<b ? a : b;
};

auto min3 = []<std::integral T>(const T &a, const T &b, const T &c) {
    return min2(a, min2(b,c));
};

int main() {
    cout << min3( 3, 7, 2 ) << '\n';
    cout << min3( 8.11, 113.2, -3.1 ) << '\n'; //                                  (ERR)  Fehler: kein integraler Typ

Okt 23, 2024

lst-0627-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MrcGhxTdT 
#include <vector>
#include <algorithm>  // sort
// Definitionen und weitere Includes wie zuvor
int main() {
    vector zwerge{    // initialisieren wie zuvor
    /* sortieren */
    std::sort(begin(zwerge), end(zwerge));
    // ausgeben wie zuvor 

Okt 23, 2024

lst-0644-book.cpp

// https://godbolt.org/z/Kxrz5ETh6 
#include <concepts>  // integral, floating_point
#include <iostream>
using namespace std;
int64_t trunc_to_10(integral auto val) { return (val/10)*10; }
int64_t trunc_to_10(floating_point auto val) { return int64_t(val/10)*10; }
int main() {
  cout << trunc_to_10(144) << '\n';    // Ausgabe: 140
  cout << trunc_to_10(122.2) << '\n';  // Ausgabe: 120
}

Okt 23, 2024

lst-0627-book.cpp

// https://godbolt.org/z/MrcGhxTdT 
#include <vector>
#include <algorithm>  // sort
// Definitionen und weitere Includes wie zuvor
int main() {
    vector zwerge{    // initialisieren wie zuvor
    /* sortieren */
    std::sort(begin(zwerge), end(zwerge));
    // ausgeben wie zuvor …

Okt 23, 2024

lst-0658-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9vP3o68bW 
#include <iostream>
#include <string>
#include <concepts>    // copyable, C++20
template <std::copyable T>

class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; }
    T getData() const { return data_; }
};

class IntValue {
    int val_;
public:
    explicit IntValue(int val=0) : val_(val) {}
    int getInt() const { return val_; }
};
int main() {
    // C-Array mit drei MyContainer<double>-Instanzen
    MyContainer<double> dcont[3];
    dcont[0].setData(123.123);
    dcont[1].setData(234.234);
    std::cout << dcont[0].getData() << std::endl;
    std::cout << dcont[1].getData() << std::endl;
    // eigener Datentyp als formaler Parameter
    IntValue ival{100'000};
    MyContainer<IntValue> scont;
    scont.setData(ival);
    std::cout << scont.getData().getInt() << std::endl;
    // string als formaler Parameter
    std::string str("Text");
    MyContainer<std::string> strCont;
    strCont.setData(str);
    std::cout << strCont.getData() << std::endl;
}

Okt 23, 2024

lst-0642-book.cpp

// https://godbolt.org/z/nenW8aM81 
auto min2 = []<typename T>(const T &a, const T &b) {
    return a<b ? a : b;
};
auto min3 = []<typename T>(const T &a, const T &b, const T &c) {
    return min2(a, min2(b,c));
};

Okt 23, 2024

lst-0634-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ers9eWPbG 
#include <vector>
#include <string>
#include <algorithm> // sort
#include <iostream>  // cout
using std::string; using std::vector; using std::cout;
// wie zuvor
int main() {
    vector zwerge{    // wie zuvor
    /* sortieren */
    bool rueckwaerts = true; // oder false. Variable außerhalb des Lambdas
    std::ranges::sort(zwerge,
        [rueckwaerts](const Zwerg& a, const Zwerg& b) {
            if(rueckwaerts)
                return a.name_ > b.name_;
            else
                return a.name_ < b.name_;
        }
    );
    /* ausgeben */
    for(const auto& z : zwerge) // rückwärts: "Thorin" bis "Balin"
        cout << z.name_  << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0641-book.cpp

// https://godbolt.org/z/YWe15Ehd8 
#include <iostream>
#include <string>
using std::cout; using std::string; using namespace std::literals;
auto min2 = [](const auto &a, const auto &b) {
    return a<b ? a : b;
};
auto min3 = [](const auto &a, const auto &b, const auto &c) {
    return min2(a, min2(b,c));
};
int main() {
    cout << min3( 3, 7, 2 ) << '\n';                  // Ausgabe: 2
    cout << min3( 8.11, 113.2, -3.1 ) << '\n';        // Ausgabe: –3.1
    cout << min3( "Zoo"s, "Affe"s, "Muli"s ) << '\n'; // Ausgabe: Affe
}

Okt 23, 2024

lst-0656-book.cpp

// https://godbolt.org/z/4fK5WdoG8 
template <std::copyable T>
class MyContainer {
    T data_;
public:
    void setData(const T& d);
    T getData() const;
};
template <std::copyable T>
void MyContainer<T>::setData(const T& d) {
    data_ = d;
}
template <std::copyable T>
T MyContainer<T>::getData() const {
    return data_;
}

Okt 23, 2024

lst-0657-book.cpp

// https://godbolt.org/z/M6earoWMn 
#include <iostream>
#include <string>
#include <concepts>    // copyable, C++20
template <std::copyable T>
class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; } // allgemeiner Fall
    T getData() const { return data_; }     // allgemeiner Fall
};
template<>                                  // Spezialisierung
void MyContainer<std::string>::setData(const std::string& d) {
    data_ = "[" + d + "]";
}
int main() {
    MyContainer<std::string> mcString;
    mcString.setData("Geschichte");
    std::cout << mcString.getData() << '\n';  // Ausgabe: [Geschichte]
    MyContainer<int> mcInt;
    mcInt.setData(5);
    std::cout << mcInt.getData() << '\n';     // Ausgabe: 5
}

Okt 23, 2024

lst-0644-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Kxrz5ETh6 
#include <concepts>  // integral, floating_point
#include <iostream>
using namespace std;
int64_t trunc_to_10(integral auto val) { return (val/10)*10; }
int64_t trunc_to_10(floating_point auto val) { return int64_t(val/10)*10; }
int main() {
  cout << trunc_to_10(144) << '\n';    // Ausgabe: 140
  cout << trunc_to_10(122.2) << '\n';  // Ausgabe: 120
}

Okt 23, 2024

lst-0642-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nenW8aM81 
auto min2 = []<typename T>(const T &a, const T &b) {
    return a<b ? a : b;
};
auto min3 = []<typename T>(const T &a, const T &b, const T &c) {
    return min2(a, min2(b,c));
};

Okt 23, 2024

lst-0670-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y6v6cKE3v 
#include <string>
#include <tuple>
#include <concepts>             // copyable, C++20
template <std::copyable T, std::copyable U=T> // allgemeiner Fall
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t, const U& u) : data01_{t}, data02_{u} {}
};
template <std::copyable T>      // teilweise Spezialisierung, T bleibt formal
class MyPair<T, std::string> {  // U ist auf string spezialisiert
    std::tuple<T,std::string> data_;
public:
    MyPair(const T& t, const std::string& str) : data_{t, str} { }
};
template <std::copyable U>      // teilweise Spezialisierung, U bleibt formal
class MyPair<std::string, U> {  // T ist auf string spezialisiert
    std::tuple<std::string, U> data_;
public:
    MyPair(const std::string& str, const U& u) : data_{str, u} { }
};
int main() {
  // nutzt partielle Spezialisierung
  MyPair<int,std::string> intString{1, "a"};
  MyPair<std::string,int> stringInt{"b", 2};

  MyPair<int,int> intInt{3,4};                     // nutzt allgemeinen Fall
  MyPair intInt2{3,4};                             // auch MyPair<int,int>
  MyPair<std::string,std::string> strStr{"c","d"}; //                                          (ERR)  mehrdeutig
}

Okt 23, 2024

lst-0671-book.cpp

// https://godbolt.org/z/baPeoTbM8 
template<>   // vollständige Spezialisierung
class MyPair<std::string, std::string> {
    std::vector<std::string> data_;
public:
    MyPair(const std::string& t, const std::string& u) : data_{t, u} { }
};
int main() {
    // nutzt die vollständige Spezialisierung:
    MyPair<std::string,std::string> strStr{"c","d"};
}

Okt 23, 2024

lst-0659-book.cpp

// https://godbolt.org/z/7KzcWE8Pz 
#include <string>
#include <vector>
#include <set>
#include <tuple>
#include <memory> // shared_ptr
template <typename T>
class MyStuff {
    T data_;
public:
    MyStuff() : data_{} {}             // default c'tor
    MyStuff(const T& d) : data_{d} { } // copy c'tor
    T getStuff() const { return data_; }
};
class IntValue {
    int val_;
public:
    explicit IntValue(int val=0) : val_(val) {}
    int getInt() const { return val_; }
};
int main() {
    MyStuff intStuff(12);              // wird zu MyStuff<int>
    std::vector vs{ 1,2,3,4 };         // wird zu vector<int>
    MyStuff ivalStuff{ IntValue{33} }; // wird zu MyStuff<IntValue>
    std::tuple tpl{ 23, 'a' };         // wird zu tuple<int,char>
    std::set zweiDrei (vs.begin()+1, vs.end()-1); // wird zu set<int>
    // Kann der Compiler nicht deduzieren:
    MyStuff<double> dblStuff;              // kein Konstruktorargument
    std::vector<char> vcs(10);             // Größe 10, aber von welchem Typ?
    std::shared_ptr<int> ptr{new int{88}}; // keine Regel für int*
}

Okt 23, 2024

lst-0654-book.cpp

// https://godbolt.org/z/jqzTMxYKv 
template <std::copyable T>      // C++20-Concept
class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; }
    T getData() const { return data_; }
};

Okt 23, 2024

lst-0656-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4fK5WdoG8 
template <std::copyable T>
class MyContainer {
    T data_;
public:
    void setData(const T& d);
    T getData() const;
};
template <std::copyable T>
void MyContainer<T>::setData(const T& d) {
    data_ = d;
}
template <std::copyable T>
T MyContainer<T>::getData() const {
    return data_;
}

Okt 23, 2024

lst-0647-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/orTK9daa3 
#include <concepts>
#include <iostream>
#include <string>
using namespace std; using namespace std::literals;

string mk_string(integral auto val) { return to_string(val); }
string mk_string(string val) { return '['+val+']'; }
template<typename T>
  requires copyable<T> &&                            // Typanforderung
  requires (T t) { mk_string(t) + mk_string(t); } && // einfache Anforderung
  requires (T t) {                     // zusammengesetzte Anforderung
    {mk_string(t)} -> same_as<string>; // gültiger Ausdruck muss Bedingung erfüllen
  }
string dbl_quote(const T& val) {
  T val2{val};                      // Kopie erzeugen (nur zu Demozwecken)
  return '"' + mk_string(val) + mk_string(val2) + '"';
}
int main() {
  cout << dbl_quote(10) << '\n';    // Ausgabe: "1010"
  cout << dbl_quote("ab"s) << '\n'; // Ausgabe: "[ab][ab]"
  cout << dbl_quote(3.14) << '\n';  //                                  (ERR)  Fehler: keine passende mk_string-Überladung
}

Okt 23, 2024

lst-0570-book.cpp

// https://godbolt.org/z/acMjvxcM5 
#include <string>
#include <cmath> // sin, cos
template<typename TYP>
constexpr TYP max2(const TYP &a, const TYP &b)
    { return  a > b ? a : b; }
int main() {
    double e = max2(sin(3.141592/2), cos(3.141592/2));
    double i = max2(10+12+45, 100/5+20);
    std::string s = max2(std::string("Ernie"), std::string("Bert"));
}

Okt 23, 2024

lst-0596-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/c9xzM7EhP 
#include <array>
#include <iostream> // cout
using std::array; using std::cout;
template<size_t SIZE>
array<int,SIZE> createArray() {
    array<int,SIZE> result{};
    return result;
}
int main() {
    auto data = createArray<5>();
    data[3] = 33;
    for(auto e : data) cout << e << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0620-book.cpp

// https://godbolt.org/z/3ch51ov87 
#include <set>
#include <string>
#include <iostream> // cout
using std::string; using std::set; using std::cout;
struct Zwerg {
    string name_;
    unsigned jahr_;
};
bool operator<(const Zwerg& a, const Zwerg& b) {
    return a.name_ < b.name_;
}
int main() {
    set zwerge{ Zwerg{"Balin", 2763}, Zwerg{"Dwalin", 2772},
        Zwerg{"Oin", 2774}, Zwerg{"Gloin", 2783}, Zwerg{"Thorin", 2746},
        Zwerg{"Fili", 2859}, Zwerg{"Kili", 2864} };
    for(const auto& z : zwerge) // sortierte Ausgabe: "Balin" bis "Thorin"
        cout << z.name_  << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0577-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9Trh8h8Mb 
#include <string>
#include <vector>
#include <span>      // C++20
#include <fstream>   // ifstream
#include <stdexcept> // runtime_error
#include <iostream>  // cerr
// C-Header:
#include <zlib.h>    // gzXyz; sudo aptitude install libz-dev
#include <cerrno>    // errno
#include <cstring>   // strerror
namespace {
using std::string; using std::span; using std::byte;

Okt 23, 2024

lst-0615-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WbnThTs8e 
#include <functional> // function
#include <iostream>   // cout
int berechne(int a, int b, std::function<int(int,int)> binop) {
    return binop(a,b);
}
int plus(int a, int b) { return a+b; }
int mal(int a, int b) { return a*b; }
int main() {
    std::cout << berechne(3, 4, plus) << "\n";  // Wert-Schreibweise
    std::cout << berechne(3, 4, mal) << "\n";   // Wert-Schreibweise
    std::cout << berechne(3, 4, &plus) << "\n"; // Zeiger-Schreibweise
    std::cout << berechne(3, 4, &mal) << "\n";  // Zeiger-Schreibweise
}

Okt 23, 2024

lst-0604-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oTn1K4sGG 
#include <vector>
#include <iostream>  // cout, ostream
#include <algorithm> // sort, copy
#include <iterator>  // ostream_iterator
int main() {
    std::ostream_iterator<int> oit(std::cout," ");
    std::vector data { 100, 50, 1, 75, 25, 0 };       // vector<int>
    std::sort(std::begin(data), std::end(data));      // Iteratorenpaar
    std::copy(std::begin(data), std::end(data), oit); // Iteratorenpaar
    std::cout << '\n';                                // Ausgabe: 0 1 25 50 75 100
    std::ranges::reverse(data);                       // Range
    std::ranges::copy(data, oit);                     // Range
    std::cout << '\n';                                // Ausgabe: 100 75 50 25 1 0
}

Okt 23, 2024

lst-0581-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4sod8vrr6 
} // namespace
int main(int argc, const char* argv[]) {
    try {
        const std::vector<string> fNamen {argv+1, argv+argc};
        for(auto fName : fNamen) {
            std::cout << "packe " << fName << "... ";
            packe(fName, fName+".gz");
            std::cout << fName << ".gz"<< "\n";
        }
    } catch(std::runtime_error &exc) {
        std::cerr << "Fehler: " << exc.what() << "\n";
    }
}

Okt 23, 2024

lst-0570-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/acMjvxcM5 
#include <string>
#include <cmath> // sin, cos
template<typename TYP>
constexpr TYP max2(const TYP &a, const TYP &b)
    { return  a > b ? a : b; }
int main() {
    double e = max2(sin(3.141592/2), cos(3.141592/2));
    double i = max2(10+12+45, 100/5+20);
    std::string s = max2(std::string("Ernie"), std::string("Bert"));
}

Okt 23, 2024

lst-0604-book.cpp

// https://godbolt.org/z/oTn1K4sGG 
#include <vector>
#include <iostream>  // cout, ostream
#include <algorithm> // sort, copy
#include <iterator>  // ostream_iterator
int main() {
    std::ostream_iterator<int> oit(std::cout," ");
    std::vector data { 100, 50, 1, 75, 25, 0 };       // vector<int>
    std::sort(std::begin(data), std::end(data));      // Iteratorenpaar
    std::copy(std::begin(data), std::end(data), oit); // Iteratorenpaar
    std::cout << '\n';                                // Ausgabe: 0 1 25 50 75 100
    std::ranges::reverse(data);                       // Range
    std::ranges::copy(data, oit);                     // Range
    std::cout << '\n';                                // Ausgabe: 100 75 50 25 1 0
}

Okt 23, 2024

lst-0612-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7YKjcTbhn 
#include <functional> // function
#include <iostream>   // cout
int berechne(int a, int b, std::function<int(int,int)> binop) {
    return binop(a,b);
}
int plus(int a, int b) { return a+b; }
int mal(int a, int b) { return a*b; }
int main() {
    std::cout << berechne(3, 4, plus) << "\n"; // Ausgabe: 7
    std::cout << berechne(3, 4, mal) << "\n";  // Ausgabe: 12
}

Okt 23, 2024

lst-0606-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/13eMxKTfj 
#include <iostream>
#include <vector>
#include <set>
#include <bitset>
template<typename IT>
std::ostream& druckeBinaer(std::ostream& os, IT begin, IT end)
{
    for(IT it=begin; it != end; ++it) {
        std::bitset<4> x(*it); // Zahl in bitset kopieren
        os << x << " ";
    }
    return os;
}
int main()
{
    std::vector<int> vdata { 2, 0, 15, 12 };
    druckeBinaer(std::cout, vdata.cbegin(), vdata.cend()) << "\n";
    // Ausgabe: 0010 0000 1111 1100
    std::set<int> sdata { 2, 0, 12, 15 };
    druckeBinaer(std::cout, std::begin(sdata), std::end(sdata)) << "\n";
    // Ausgabe: 0000 0010 1100 1111
    int adata[] = { 0,1,2,13,14,15 };
    druckeBinaer(std::cout, std::begin(adata), std::end(adata)) << "\n";
    // Ausgabe: 0000 0001 0010 1101 1110 1111
}

Okt 23, 2024

lst-0601-book.cpp

// https://godbolt.org/z/cYsTo371z 
#include <iostream>
const int& a_oder_b(int auswahl) {
    static const int a = 42;
    static const int b = 73;
    if(auswahl==1)
        return a; // const& auf innere Variable a zurückgeben
    else
        return b; // const& auf innere Variable b zurückgeben
}
template<typename TYP>
TYP add(TYP a, TYP b) {
    return a + b;
}
int main() {
    auto res = add(
        a_oder_b(0),   // const int&
        a_oder_b(1) ); // const int&
    std::cout << res << "\n"; // Ausgabe: 115
}

Okt 23, 2024

lst-0603-book.cpp

// https://godbolt.org/z/bfofn76Ke 
#include <iostream>
class Printer {
    std::ostream& trg_;
public:
    explicit Printer(std::ostream& target)
        : trg_(target)
        {}
    template<typename TYP>
    Printer& print(const TYP& arg) {
        trg_ << arg;
        return *this;
    }
};
int main() {
    Printer normal(std::cout);
    normal.print(7).print(" ").print(3.1415).print("\n");
    Printer fehler(std::cerr);
    fehler.print(8).print(" ").print(2.7183).print("\n");
}

Okt 23, 2024

lst-0601-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cYsTo371z 
#include <iostream>
const int& a_oder_b(int auswahl) {
    static const int a = 42;
    static const int b = 73;
    if(auswahl==1)
        return a; // const& auf innere Variable a zurückgeben
    else
        return b; // const& auf innere Variable b zurückgeben
}
template<typename TYP>
TYP add(TYP a, TYP b) {
    return a + b;
}
int main() {
    auto res = add(
        a_oder_b(0),   // const int&
        a_oder_b(1) ); // const int&
    std::cout << res << "\n"; // Ausgabe: 115
}

Okt 23, 2024

lst-0568-book.cpp

// https://godbolt.org/z/5zrfvovaW 
#include <string>
#include <cmath> // sin, cos
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    double e = MAX2(sin(3.141592/2), cos(3.141592/2));
    int i = MAX2(10+12+45, 100/5+20);
    std::string s = MAX2(std::string("Ernie"), std::string("Bert"));
}

Okt 23, 2024

lst-0567-book.cpp

// https://godbolt.org/z/YzYz3x1zx 
#include <iostream>
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    int x = 0;
    int y = 0;
    int z = MAX2( ++x, ++y ); //             (ERR)  expandiert Argumente mehrfach
    std::cout << "x:"<< x << " y:"<< y << " z:"<<z << '\n';
}

Okt 23, 2024

lst-0603-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bfofn76Ke 
#include <iostream>
class Printer {
    std::ostream& trg_;
public:
    explicit Printer(std::ostream& target)
        : trg_(target)
        {}
    template<typename TYP>
    Printer& print(const TYP& arg) {
        trg_ << arg;
        return *this;
    }
};
int main() {
    Printer normal(std::cout);
    normal.print(7).print(" ").print(3.1415).print("\n");
    Printer fehler(std::cerr);
    fehler.print(8).print(" ").print(2.7183).print("\n");
}

Okt 23, 2024

lst-0605-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h3baE65od 
#include <iostream>
#include <vector>
#include <set>
#include <bitset>
#include <ranges>
namespace rng = std::ranges;
std::ostream& druckeBinaer(std::ostream& os, rng::input_range auto&& range) {
    for(auto&& elem : range) {
        std::bitset<4> x(elem); // Zahl in bitset kopieren
        os << x << " ";
    }
    return os;
}
int main()
{
    std::vector vdata { 2, 0, 15, 12 };
    druckeBinaer(std::cout, vdata) << "\n";
    // Ausgabe: 0010 0000 1111 1100
    std::set sdata { 2, 0, 12, 15 };
    druckeBinaer(std::cout, sdata) << "\n";
    // Ausgabe: 0000 0010 1100 1111
    int adata[] = { 0,1,2,13,14,15 };
    druckeBinaer(std::cout, adata) << "\n";
    // Ausgabe: 0000 0001 0010 1101 1110 1111
}

Okt 23, 2024

lst-0612-book.cpp

// https://godbolt.org/z/7YKjcTbhn 
#include <functional> // function
#include <iostream>   // cout
int berechne(int a, int b, std::function<int(int,int)> binop) {
    return binop(a,b);
}
int plus(int a, int b) { return a+b; }
int mal(int a, int b) { return a*b; }
int main() {
    std::cout << berechne(3, 4, plus) << "\n"; // Ausgabe: 7
    std::cout << berechne(3, 4, mal) << "\n";  // Ausgabe: 12
}

Okt 23, 2024

lst-0616-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Px83WPKfq 
#include <iostream>                      // cout
using std::cout;
class Inkrement {
   int menge_;
public:
    explicit Inkrement(int menge) : menge_{menge} {}
    int operator()(int wert) const  {    // macht Instanzen aufrufbar
        return wert + menge_;
    }
    void clear() {
        menge_ = 0;
    }
};
int main() {
    Inkrement plusVier{4};               // Instanz erzeugen
    Inkrement plusElf{11};               // noch eine Instanz
    cout << plusVier(8) << "\n";         // Ausgabe: 12
    int erg = 2 * plusElf(5) - 7;        // erg ist 25
    cout << plusElf(erg/5) << "\n";      // Ausgabe: 16
    cout << 3 * Inkrement{1}(7) << "\n"; // Ausgabe: 24
    Inkrement plusNix = plusElf;
    plusNix.clear();                     // Zustand ändern
    cout << plusNix(1) << "\n";          // Ausgabe: 1
}

Okt 23, 2024

lst-0568-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5zrfvovaW 
#include <string>
#include <cmath> // sin, cos
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    double e = MAX2(sin(3.141592/2), cos(3.141592/2));
    int i = MAX2(10+12+45, 100/5+20);
    std::string s = MAX2(std::string("Ernie"), std::string("Bert"));
}

Okt 23, 2024

lst-0591-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/aMPj3K7EE 
#include <iostream>
struct Zahl {
    int wert_;
};
template<typename TYP>
void print(TYP value) {
    std::cout << value << "\n";
}
int main() {
    print(5);
    print(-10.25);
    print("Flamingo");
    Zahl sieben { 7 };
    print(sieben); //                                  (ERR)  cout << sieben gibt es nicht
}

Okt 23, 2024

lst-0606-book.cpp

// https://godbolt.org/z/13eMxKTfj 
#include <iostream>
#include <vector>
#include <set>
#include <bitset>
template<typename IT>
std::ostream& druckeBinaer(std::ostream& os, IT begin, IT end)
{
    for(IT it=begin; it != end; ++it) {
        std::bitset<4> x(*it); // Zahl in bitset kopieren
        os << x << " ";
    }
    return os;
}
int main()
{
    std::vector<int> vdata { 2, 0, 15, 12 };
    druckeBinaer(std::cout, vdata.cbegin(), vdata.cend()) << "\n";
    // Ausgabe: 0010 0000 1111 1100
    std::set<int> sdata { 2, 0, 12, 15 };
    druckeBinaer(std::cout, std::begin(sdata), std::end(sdata)) << "\n";
    // Ausgabe: 0000 0010 1100 1111
    int adata[] = { 0,1,2,13,14,15 };
    druckeBinaer(std::cout, std::begin(adata), std::end(adata)) << "\n";
    // Ausgabe: 0000 0001 0010 1101 1110 1111
}

Okt 23, 2024

lst-0619-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EExfde3vP 
#include <iostream>              // cout
using std::cout;

class Hinzu {
   int menge_;
public:
    explicit Hinzu(int menge) : menge_{menge} {}
    int hinzu(int wert) const  {            // statt operator()
        return wert + menge_;
    }
    void clear() {
        menge_ = 0;
    }
};
int main() {
    Hinzu plusVier{4};                      // Instanz erzeugen
    Hinzu plusElf{11};                      // noch eine Instanz
    cout << plusVier.hinzu(8) << "\n";      // Ausgabe: 12
    int erg = 2 * plusElf.hinzu(5) - 7;     // erg ist 25
    cout << plusElf.hinzu(erg/5) << "\n";   // Ausgabe: 16
    cout << 3 * Hinzu{1}.hinzu(7) << "\n";  // Ausgabe: 24
    Hinzu plusNix = plusElf;
    plusNix.clear();                        // Zustand ändern
    cout << plusNix.hinzu(1) << "\n";       // Ausgabe: 1
}

Okt 23, 2024

lst-0569-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6xzTx83zE 
#include <string>
#include <cmath> // sin, cos
constexpr double max2(double a, double b) { return  a > b ? a : b; }
constexpr int max2(int a, int b) { return  a > b ? a : b; }
std::string max2(const std::string &a, const std::string &b)
    { return  a > b ? a : b; }
int main() {
    double e = max2(sin(3.141592/2), cos(3.141592/2));
    double i = max2(10+12+45, 100/5+20);
    std::string s = max2("Ernie", "Bert");
}

Okt 23, 2024

lst-0596-book.cpp

// https://godbolt.org/z/c9xzM7EhP 
#include <array>
#include <iostream> // cout
using std::array; using std::cout;
template<size_t SIZE>
array<int,SIZE> createArray() {
    array<int,SIZE> result{};
    return result;
}
int main() {
    auto data = createArray<5>();
    data[3] = 33;
    for(auto e : data) cout << e << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0578-book.cpp

// https://godbolt.org/z/Yh7j1WEGc 
class GzWriteStream {                         // RAII-Wrapper
public:
    gzFile gz_ ;                              // C-Struct aus zlib.h
    explicit GzWriteStream(const string& filename)
        : gz_{gzopen(filename.c_str(),"wb9")} // 'w': write, 'b':binary, '9':level
    {
        if(gz_==NULL) throw std::runtime_error(std::strerror(errno));
    }
    ~GzWriteStream() {
        gzclose(gz_);
    }
    GzWriteStream& operator<<(span<char> &data) {
        write(data);
        return *this;
    }
private:
    void write(span<char> data) {
        auto bytes = std::as_bytes(data); // C++20
        auto res = gzwrite(gz_, bytes.data(), size(bytes));
        if(res==0) throw std::runtime_error("Fehler beim Schreiben");
    }
    GzWriteStream(const GzWriteStream&) = delete;            // keine Kopie
    GzWriteStream& operator=(const GzWriteStream&) = delete; // keine Zuweisung
};

Okt 23, 2024

lst-0580-book.cpp

// https://godbolt.org/z/3P9ToPEYq 
std::vector<char> leseDatei(const string& fName) {
    std::ifstream file{ fName, std::ifstream::binary };
    if(!file) throw std::runtime_error("Fehler beim Oeffnen der Eingabe");
    file.seekg(0, file.end);          // ans Dateiende springen
    const auto laenge = file.tellg(); // aktuelle Position ist Dateigröße
    if(laenge > 1024*1024*1024)
        throw std::runtime_error("Nicht mehr als 1 GB bitte");
    file.seekg(0, file.beg);          // zurück an den Anfang
    std::vector<char> data(laenge);   // Platz schaffen
    file.read(data.data(), laenge);   // in einem Rutsch lesen
    return data;                      // wird nicht kopiert (Stichwort: RVO)
}
void packe(const string& fNameIn, const string& fNameOut) {
    auto data = leseDatei(fNameIn);   // lese Eingabe
    GzWriteStream gz{fNameOut};       // initialisiere Ausgabe
    gz << data;
}

Okt 23, 2024

lst-0620-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3ch51ov87 
#include <set>
#include <string>
#include <iostream> // cout
using std::string; using std::set; using std::cout;
struct Zwerg {
    string name_;
    unsigned jahr_;
};
bool operator<(const Zwerg& a, const Zwerg& b) {
    return a.name_ < b.name_;
}
int main() {
    set zwerge{ Zwerg{"Balin", 2763}, Zwerg{"Dwalin", 2772},
        Zwerg{"Oin", 2774}, Zwerg{"Gloin", 2783}, Zwerg{"Thorin", 2746},
        Zwerg{"Fili", 2859}, Zwerg{"Kili", 2864} };
    for(const auto& z : zwerge) // sortierte Ausgabe: "Balin" bis "Thorin"
        cout << z.name_  << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0567-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YzYz3x1zx 
#include <iostream>
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    int x = 0;
    int y = 0;
    int z = MAX2( ++x, ++y ); //             (ERR)  expandiert Argumente mehrfach
    std::cout << "x:"<< x << " y:"<< y << " z:"<<z << '\n';
}

Okt 23, 2024

lst-0569-book.cpp

// https://godbolt.org/z/6xzTx83zE 
#include <string>
#include <cmath> // sin, cos
constexpr double max2(double a, double b) { return  a > b ? a : b; }
constexpr int max2(int a, int b) { return  a > b ? a : b; }
std::string max2(const std::string &a, const std::string &b)
    { return  a > b ? a : b; }
int main() {
    double e = max2(sin(3.141592/2), cos(3.141592/2));
    double i = max2(10+12+45, 100/5+20);
    std::string s = max2("Ernie", "Bert");
}

Okt 23, 2024

lst-0608-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oY9v9a8d6 
#include <iostream>                                  // cout
#include <limits>                                    // numeric_limits
template<typename INT_TYP>                           // Template mit Typargument
void infos(const char* name) {
    using L = typename std::numeric_limits<INT_TYP>; // kürzer umbenennen
    std::cout
        << name
        << " zahlenbits:" << L::digits               // Bits ohne Vorzeichenbit
        << " vorzeichen:" << L::is_signed            // speichert Vorzeichen?
        << " min:"<< (long long)L::min()             // kleinster möglicher Wert
        << " max:"<< (long long)L::max()             // größter möglicher Wert
        << "\n";
}
int main() {
    infos<signed char>("char");                      // kleinster int-Typ
    infos<short>("short");
    infos<int>("int");
    infos<long>("long");
    infos<long long>("long long");                   // größter int-Typ
}

Okt 23, 2024

lst-0616-book.cpp

// https://godbolt.org/z/Px83WPKfq 
#include <iostream>                      // cout
using std::cout;
class Inkrement {
   int menge_;
public:
    explicit Inkrement(int menge) : menge_{menge} {}
    int operator()(int wert) const  {    // macht Instanzen aufrufbar
        return wert + menge_;
    }
    void clear() {
        menge_ = 0;
    }
};
int main() {
    Inkrement plusVier{4};               // Instanz erzeugen
    Inkrement plusElf{11};               // noch eine Instanz
    cout << plusVier(8) << "\n";         // Ausgabe: 12
    int erg = 2 * plusElf(5) - 7;        // erg ist 25
    cout << plusElf(erg/5) << "\n";      // Ausgabe: 16
    cout << 3 * Inkrement{1}(7) << "\n"; // Ausgabe: 24
    Inkrement plusNix = plusElf;
    plusNix.clear();                     // Zustand ändern
    cout << plusNix(1) << "\n";          // Ausgabe: 1
}

Okt 23, 2024

lst-0578-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Yh7j1WEGc 
class GzWriteStream {                         // RAII-Wrapper
public:
    gzFile gz_ ;                              // C-Struct aus zlib.h
    explicit GzWriteStream(const string& filename)
        : gz_{gzopen(filename.c_str(),"wb9")} // 'w': write, 'b':binary, '9':level
    {
        if(gz_==NULL) throw std::runtime_error(std::strerror(errno));
    }
    ~GzWriteStream() {
        gzclose(gz_);
    }
    GzWriteStream& operator<<(span<char> &data) {
        write(data);
        return *this;
    }
private:
    void write(span<char> data) {
        auto bytes = std::as_bytes(data); // C++20
        auto res = gzwrite(gz_, bytes.data(), size(bytes));
        if(res==0) throw std::runtime_error("Fehler beim Schreiben");
    }
    GzWriteStream(const GzWriteStream&) = delete;            // keine Kopie
    GzWriteStream& operator=(const GzWriteStream&) = delete; // keine Zuweisung
};

Okt 23, 2024

lst-0577-book.cpp

// https://godbolt.org/z/9Trh8h8Mb 
#include <string>
#include <vector>
#include <span>      // C++20
#include <fstream>   // ifstream
#include <stdexcept> // runtime_error
#include <iostream>  // cerr
// C-Header:
#include <zlib.h>    // gzXyz; sudo aptitude install libz-dev
#include <cerrno>    // errno
#include <cstring>   // strerror
namespace {
using std::string; using std::span; using std::byte;

Okt 23, 2024

lst-0581-book.cpp

// https://godbolt.org/z/4sod8vrr6 
} // namespace
int main(int argc, const char* argv[]) {
    try {
        const std::vector<string> fNamen {argv+1, argv+argc};
        for(auto fName : fNamen) {
            std::cout << "packe " << fName << "... ";
            packe(fName, fName+".gz");
            std::cout << fName << ".gz"<< "\n";
        }
    } catch(std::runtime_error &exc) {
        std::cerr << "Fehler: " << exc.what() << "\n";
    }
}

Okt 23, 2024

lst-0594-book.cpp

// https://godbolt.org/z/816Ys17aT 
#include <iostream>
using std::cout;
template<typename TYP>
  void func(TYP a) { cout << a <<" TYP\n"; }
void func(int a) { cout << a << " int\n"; }
int main() {
    func<int>(8); // Ausgabe: 8 TYP
    func(8);      // Ausgabe: 8 int
}

Okt 23, 2024

lst-0608-book.cpp

// https://godbolt.org/z/oY9v9a8d6 
#include <iostream>                                  // cout
#include <limits>                                    // numeric_limits
template<typename INT_TYP>                           // Template mit Typargument
void infos(const char* name) {
    using L = typename std::numeric_limits<INT_TYP>; // kürzer umbenennen
    std::cout
        << name
        << " zahlenbits:" << L::digits               // Bits ohne Vorzeichenbit
        << " vorzeichen:" << L::is_signed            // speichert Vorzeichen?
        << " min:"<< (long long)L::min()             // kleinster möglicher Wert
        << " max:"<< (long long)L::max()             // größter möglicher Wert
        << "\n";
}
int main() {
    infos<signed char>("char");                      // kleinster int-Typ
    infos<short>("short");
    infos<int>("int");
    infos<long>("long");
    infos<long long>("long long");                   // größter int-Typ
}

Okt 23, 2024

lst-0594-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/816Ys17aT 
#include <iostream>
using std::cout;
template<typename TYP>
  void func(TYP a) { cout << a <<" TYP\n"; }
void func(int a) { cout << a << " int\n"; }
int main() {
    func<int>(8); // Ausgabe: 8 TYP
    func(8);      // Ausgabe: 8 int
}

Okt 23, 2024

lst-0565-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jzKfabPh3 
#include <cmath> // sin, cos
constexpr double max2(double a, double b) { return a > b ? a : b; }
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    double f = max2(sin(3.141592/2), cos(3.141592/2));
    double e = MAX2(sin(3.141592/2), cos(3.141592/2));
}

Okt 23, 2024

lst-0619-book.cpp

// https://godbolt.org/z/EExfde3vP 
#include <iostream>              // cout
using std::cout;

class Hinzu {
   int menge_;
public:
    explicit Hinzu(int menge) : menge_{menge} {}
    int hinzu(int wert) const  {            // statt operator()
        return wert + menge_;
    }
    void clear() {
        menge_ = 0;
    }
};
int main() {
    Hinzu plusVier{4};                      // Instanz erzeugen
    Hinzu plusElf{11};                      // noch eine Instanz
    cout << plusVier.hinzu(8) << "\n";      // Ausgabe: 12
    int erg = 2 * plusElf.hinzu(5) - 7;     // erg ist 25
    cout << plusElf.hinzu(erg/5) << "\n";   // Ausgabe: 16
    cout << 3 * Hinzu{1}.hinzu(7) << "\n";  // Ausgabe: 24
    Hinzu plusNix = plusElf;
    plusNix.clear();                        // Zustand ändern
    cout << plusNix.hinzu(1) << "\n";       // Ausgabe: 1
}

Okt 23, 2024

lst-0591-book.cpp

// https://godbolt.org/z/aMPj3K7EE 
#include <iostream>
struct Zahl {
    int wert_;
};
template<typename TYP>
void print(TYP value) {
    std::cout << value << "\n";
}
int main() {
    print(5);
    print(-10.25);
    print("Flamingo");
    Zahl sieben { 7 };
    print(sieben); //                                  (ERR)  cout << sieben gibt es nicht
}

Okt 23, 2024

lst-0605-book.cpp

// https://godbolt.org/z/h3baE65od 
#include <iostream>
#include <vector>
#include <set>
#include <bitset>
#include <ranges>
namespace rng = std::ranges;
std::ostream& druckeBinaer(std::ostream& os, rng::input_range auto&& range) {
    for(auto&& elem : range) {
        std::bitset<4> x(elem); // Zahl in bitset kopieren
        os << x << " ";
    }
    return os;
}
int main()
{
    std::vector vdata { 2, 0, 15, 12 };
    druckeBinaer(std::cout, vdata) << "\n";
    // Ausgabe: 0010 0000 1111 1100
    std::set sdata { 2, 0, 12, 15 };
    druckeBinaer(std::cout, sdata) << "\n";
    // Ausgabe: 0000 0010 1100 1111
    int adata[] = { 0,1,2,13,14,15 };
    druckeBinaer(std::cout, adata) << "\n";
    // Ausgabe: 0000 0001 0010 1101 1110 1111
}

Okt 23, 2024

lst-0580-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3P9ToPEYq 
std::vector<char> leseDatei(const string& fName) {
    std::ifstream file{ fName, std::ifstream::binary };
    if(!file) throw std::runtime_error("Fehler beim Oeffnen der Eingabe");
    file.seekg(0, file.end);          // ans Dateiende springen
    const auto laenge = file.tellg(); // aktuelle Position ist Dateigröße
    if(laenge > 1024*1024*1024)
        throw std::runtime_error("Nicht mehr als 1 GB bitte");
    file.seekg(0, file.beg);          // zurück an den Anfang
    std::vector<char> data(laenge);   // Platz schaffen
    file.read(data.data(), laenge);   // in einem Rutsch lesen
    return data;                      // wird nicht kopiert (Stichwort: RVO)
}
void packe(const string& fNameIn, const string& fNameOut) {
    auto data = leseDatei(fNameIn);   // lese Eingabe
    GzWriteStream gz{fNameOut};       // initialisiere Ausgabe
    gz << data;
}

Okt 23, 2024

lst-0615-book.cpp

// https://godbolt.org/z/WbnThTs8e 
#include <functional> // function
#include <iostream>   // cout
int berechne(int a, int b, std::function<int(int,int)> binop) {
    return binop(a,b);
}
int plus(int a, int b) { return a+b; }
int mal(int a, int b) { return a*b; }
int main() {
    std::cout << berechne(3, 4, plus) << "\n";  // Wert-Schreibweise
    std::cout << berechne(3, 4, mal) << "\n";   // Wert-Schreibweise
    std::cout << berechne(3, 4, &plus) << "\n"; // Zeiger-Schreibweise
    std::cout << berechne(3, 4, &mal) << "\n";  // Zeiger-Schreibweise
}

Okt 23, 2024

lst-0517-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ehhGPjabz 
#include <string>
#include <vector>
class Image {
    std::vector<char> bilddaten_;
public:
    explicit Image(const std::string& filename) { /* Bild laden */ }
    void draw() const { /* Bild malen */ };
};

Okt 23, 2024

lst-0523-book.cpp

// https://godbolt.org/z/Mqrxxs11Y 
struct StereoImage {
    Image* rechts_;        //             (ERR)  roher Zeiger
    Image* links_;         //             (ERR)  roher Zeiger
    StereoImage(const string& nameBase)           // konstruieren
      : rechts_{new Image{nameBase+"rechts.jpg"}} // okay
      , links_{new Image{nameBase+"links.jpg"}}   // gefährlich
      { }
    ~StereoImage() {       // entfernen
        delete rechts_; delete links_;
    }
    StereoImage(const StereoImage&) = delete;     // keine Kopie
    StereoImage& operator=(const StereoImage&) = delete; // keine Zuweisung
};
int main() {
    Image* bild = new Image{"bild.jpg"};          //             (ERR)  einem rohen Zeiger?
    StereoImage stereo{"3d"};
    delete bild;
}

Okt 23, 2024

lst-0549-book.cpp

// https://godbolt.org/z/M13eYMrjG 
#include <map>
#include <memory> // unique_ptr
#include <string>
#include <iostream>
#include <chrono> // Zeitmessung
using std::map; using std::cout; using std::endl; using namespace std::chrono;
struct Node {
  std::unique_ptr<int> d_;
  Node() : Node{0}  { }
  explicit Node(int d) : d_{ new int } { *d_ = d; } // auch etwas Speicher
  friend bool operator<(const Node& a, const Node& b) {return *a.d_<*b.d_;}
  friend bool operator==(const Node& a, const Node& b) {return *a.d_==*b.d_;}
};
long long millisSeit(steady_clock::time_point start) { // Helfer zur Zeitmessung
  return duration_cast<milliseconds>(steady_clock::now()-start).count();
}

int main() {
  std::unique_ptr<map<int,Node>> riesig{ new map<int,Node>{} };
  cout << "Aufbau..." << endl;
  steady_clock::time_point start = steady_clock::now();
  for(int idx=0; idx < 100*1000*1000; ++idx) {   // massive Menge in der map
      (*riesig)[idx] = Node{idx};
  }
  cout << "Fertig: " << millisSeit(start) << " ms" << endl; // Zeitmessung hier
  start = steady_clock::now();
  riesig.reset();                                           // wegräumen hier
  cout << "Ende: " << millisSeit(start) << " ms" << endl;   // Zeitmessung hier
}

Okt 23, 2024

lst-0525-book.cpp

// https://godbolt.org/z/YMe5PY6aT 
#include <vector>
#include <numeric>   // iota
#include <iostream>
using std::vector; using std::cout;
struct Zahl {        // stellvertretend für ein großes, teures Objekt
    unsigned long val_;
    Zahl(unsigned long val) : val_{val} {}
    Zahl() : val_{0} {}
};
/* ermittelt anhand bisheriger Primzahlen, ob z eine Primzahl ist */
bool isPrim(const Zahl& z, const vector<Zahl*> prims) {
    for(Zahl* p : prims) {
        if((p->val_*p->val_) > z.val_) return true;   // zu groß
        if(z.val_ % p->val_ == 0) return false;       // ist Teiler
    }
    return true;
}
int main() {
    vector<Zahl> alleZahlen(98);   // 98 mit null initialisierte Elemente
    std::iota(begin(alleZahlen), end(alleZahlen), 3); // 3..100
    /* alleZahlen enthält jetzt {3..100} */
    vector<Zahl*> prims{};         // bekommt ermittelte Primzahlen
    Zahl zwei{2};
    prims.push_back(&zwei);        // die 2 wird gebraucht
    for(Zahl &z : alleZahlen) {    // über alle Zahlen iterieren
        if(isPrim(z, prims)) {
            prims.push_back( &z ); // speichere Adresse
        }
    }
    /* Rest ausgeben */
    for(Zahl* p : prims)
        cout << p->val_ << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0549-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M13eYMrjG 
#include <map>
#include <memory> // unique_ptr
#include <string>
#include <iostream>
#include <chrono> // Zeitmessung
using std::map; using std::cout; using std::endl; using namespace std::chrono;
struct Node {
  std::unique_ptr<int> d_;
  Node() : Node{0}  { }
  explicit Node(int d) : d_{ new int } { *d_ = d; } // auch etwas Speicher
  friend bool operator<(const Node& a, const Node& b) {return *a.d_<*b.d_;}
  friend bool operator==(const Node& a, const Node& b) {return *a.d_==*b.d_;}
};
long long millisSeit(steady_clock::time_point start) { // Helfer zur Zeitmessung
  return duration_cast<milliseconds>(steady_clock::now()-start).count();
}

int main() {
  std::unique_ptr<map<int,Node>> riesig{ new map<int,Node>{} };
  cout << "Aufbau..." << endl;
  steady_clock::time_point start = steady_clock::now();
  for(int idx=0; idx < 100*1000*1000; ++idx) {   // massive Menge in der map
      (*riesig)[idx] = Node{idx};
  }
  cout << "Fertig: " << millisSeit(start) << " ms" << endl; // Zeitmessung hier
  start = steady_clock::now();
  riesig.reset();                                           // wegräumen hier
  cout << "Ende: " << millisSeit(start) << " ms" << endl;   // Zeitmessung hier
}

Okt 23, 2024

lst-0547-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4nqz4ed4W 
#include <vector>
#include <iostream> // cout

using std::vector;
int main() {
    vector data{ 5,4,3,2,1 };
    vector<int>::const_iterator ende = data.end(); // oder end(data)
    for(vector<int>::const_iterator it = data.begin(); it!=ende; ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";
}

Okt 23, 2024

lst-0548-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zsqKz76cj 
#include <iostream>   // cout
#include <iterator>   // ostream_iterator
#include <algorithm>  // copy, ranges::copy
int main () {
  int data[6] = { 1, 2, 3, 7, 9, 10 };
  std::ostream_iterator<int> out_it (std::cout,", ");
  std::copy(data, data+6, out_it);           // Zeiger als Iteratoren
  std::cout << "\n";                         // Ausgabe: 1, 2, 3, 7, 9, 10
  std::ranges::copy(data, out_it);           // C-Array-Zeiger als Range
  std::cout << "\n";                         // Ausgabe: 1, 2, 3, 7, 9, 10
}

Okt 23, 2024

lst-0547-book.cpp

// https://godbolt.org/z/4nqz4ed4W 
#include <vector>
#include <iostream> // cout

using std::vector;
int main() {
    vector data{ 5,4,3,2,1 };
    vector<int>::const_iterator ende = data.end(); // oder end(data)
    for(vector<int>::const_iterator it = data.begin(); it!=ende; ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";
}

Okt 23, 2024

lst-0504-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vxTsveGjT 
#include <vector>
#include <memory> // unique_ptr
#include <iostream> // cout
enum class ShapeTag { CIRC, RECT };
struct Shape { // Data
    ShapeTag tag_;
    double v1_, v2_;
    Shape(double w, double h) : tag_{ShapeTag::RECT}, v1_{w}, v2_{h} {}
    Shape(double r) : tag_{ShapeTag::CIRC}, v1_{r}, v2_{0} {}
};
class AreaCalculator { // Logic
public:
    double area(const std::vector<std::unique_ptr<Shape>> &shapes) const {
        double result = 0;
        for(auto &shape :  shapes) {
            switch(shape->tag_) {
            case ShapeTag::CIRC:
                 result += 3.1415 * shape->v1_ * shape->v1_;
                 break;
            case ShapeTag::RECT:
                 result += shape->v1_*shape->v2_;
                 break;
            }
        }
        return result;
    }
};
int main() {
    std::vector<std::unique_ptr<Shape>> data{};
    data.push_back(std::make_unique<Shape>(10.));     // ein Kreis
    data.push_back(std::make_unique<Shape>(4., 6.));  // ein Rechteck
    // rechnen
    AreaCalculator calc{};
    std::cout  << calc.area( data ) << "\n";
}

Okt 23, 2024

lst-0557-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6coqbhfKM 
// …hier Inhalt von <vector>…
// …hier Inhalt von <iostream>…
using container_type = std::vector<int>;
static constexpr unsigned SIZE = 10;
int main() {
  { (std::cout) << "Programmstart" << "\n"; }
  container_type data(SIZE);
  { (std::cout) << "Der Container hat " << data.size() << " Elemente." << "\n";}
  { (std::cout) << "Programmende" << "\n"; }
  { std::cout << "Das ging ja noch mal gut.\n"; }
}

Okt 23, 2024

lst-0541-book.cpp

// https://godbolt.org/z/MEqcExjrY 
#include <memory>      // unique_ptr
#include <iostream>    // cout
std::unique_ptr<int[]> createData(size_t sz) {
    return std::unique_ptr<int[]>(new int[sz]);
}
void fibonacci(int data[], int* ende) {
    for(int* p = data+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);
    }
}
std::ostream& print(std::ostream &os, int data[], int* ende) {
    for(int const* p= data; p != ende; ++p)
        std::cout << *p << " ";
    return os;
}
int main() {
    std::unique_ptr<int[]> data { createData(10) };
    data[0] = 1; // setzen Sie Werte im Array durch den unique_ptr
    data[1] = 1;
    fibonacci(data.get(), data.get()+10); // holen Sie sich den C-Array-Zeiger mit get()
    print(std::cout, data.get(), data.get()+10) << "\n";
}

Okt 23, 2024

lst-0517-book.cpp

// https://godbolt.org/z/ehhGPjabz 
#include <string>
#include <vector>
class Image {
    std::vector<char> bilddaten_;
public:
    explicit Image(const std::string& filename) { /* Bild laden */ }
    void draw() const { /* Bild malen */ };
};

Okt 23, 2024

lst-0537-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1qx16Gr61 
#include <iostream>
void fibonacci(int data[], int* ende) {
    for(int* p = data+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);
    }
}
std::ostream& print(std::ostream &os, int data[], int* ende) {
    for(int const * p=data; p != ende; ++p)
        std::cout << *p << " ";
    return os;
}
int main() {
    int carray[10] = { 1,1 }; // initialisiert zu { 1,1,0,0,0,0,0,0,0,0 }
    fibonacci(carray, carray+10);
    print(std::cout, carray, carray+10) << "\n";
}

Okt 23, 2024

lst-0520-book.cpp

// https://godbolt.org/z/sas3b1E3b 
#include <vector>
#include <iostream>
#include <memory>                    // shared_ptr
#include <random>                    // uniform_int_distribution, random_device
namespace {                          // Beginn des anonymen Namensraums
using std::shared_ptr; using std::make_shared;
using std::vector; using std::cout;
struct Asteroid {
    int points_ = 100;
    int structure_ = 10;
};
struct Ship {
    shared_ptr<Asteroid> firedLastOn_{};
    int score_ = 0;
    int firepower = 1;
    bool fireUpon(shared_ptr<Asteroid> a);
};
struct GameBoard {
    vector<shared_ptr<Asteroid>> asteroids_;
    explicit GameBoard(int nAsteroids);
    bool shipFires(Ship& ship);
};
// Implementierung von Ship
bool Ship::fireUpon(shared_ptr<Asteroid> a) {
    if(!a) return false;             // ungültiger Asteroid
    a->structure_ -= firepower;
    if(a.get() == firedLastOn_.get())
        firepower *= 2 ;             // Schaden vergrößern
    else
        firepower = 1;               // zurücksetzen
    firedLastOn_ = a;
    return a->structure_ <= 0;       // kaputt?
}
// Implementierung von GameBoard
GameBoard::GameBoard(int nAsteroids) : asteroids_{}
{   // einige Standard-Asteroiden
    for(int idx=0; idx<nAsteroids; ++idx)
        asteroids_.push_back( make_shared<Asteroid>() );
}
int wuerfel(int min, int max) {
    /* static std::default_random_engine e{}; */   // Pseudozufallsgenerator
    static std::random_device e{};           // Zufallsgenerator
    return std::uniform_int_distribution<int>{min, max}(e); // würfeln
}
bool GameBoard::shipFires(Ship &ship) {
    int idx = wuerfel(0, asteroids_.size()-1);
    bool kaputt = ship.fireUpon(asteroids_[idx]);
    if(kaputt) {
        ship.score_ += asteroids_[idx]->points_;
        asteroids_.erase(asteroids_.begin()+idx);           // entfernen
    }
    return asteroids_.size() == 0;                          // alles kaputt
}
} // Ende des anonymen Namensraums
int main() {
    GameBoard game{10};                                     // 10 Asteroiden
    Ship ship{};
    for(int idx = 0; idx < 85; ++idx) {                     // 85 Schüsse
        if(game.shipFires(ship)) {
            cout << "Der Weltraum ist nach " << idx+1 << " Schuessen leer. ";
            break;
        }
    }
    cout << "Sie haben " << ship.score_ << " Punkte erreicht.\n";
}

Okt 23, 2024

lst-0510-book.cpp

// https://godbolt.org/z/4536hxvEK 
int value = 42;
int& valueRef = value; // Referenz; kein Adressoperator & nötig
valueRef = 18;         // kein Dereferenzierungsoperator * nötig
cout << value << "\n"; // Ausgabe: 18

Okt 23, 2024

lst-0506-book.cpp

// https://godbolt.org/z/rc67xWWfT 
#include <iostream>
struct Point { int x, y; };
class Rectangle {
protected:
    Point origin_;  int width_;  int height_;
public:
    Rectangle(Point o, int w, int h) : origin_{o}, width_{w}, height_{h} {}
    virtual void setHeight(int height) { height_ = height; }
    virtual int  getHeight() const { return height_; }
    virtual void setWidth(int width) { width_ = width; }
    virtual int getWidth() const { return width_; }
    virtual int getArea() const { return width_ * height_; }
};
class Square : public Rectangle {
public:
    Square(Point o, int wh) : Rectangle{o, wh, wh} {}
    void setHeight(int wh) override { width_ = height_ = wh; }
    void setWidth(int wh) override { width_ = height_ = wh; }
};
void areaCheck(Rectangle &rect) {
    rect.setWidth(5);
    rect.setHeight(4);
    auto areaValue = rect.getArea();
    if(areaValue != 20) {
        std::cout << "error!\n";
    } else {
        std::cout << "all fine\n";
    }
}
int main() {
    Rectangle rect{ {0,0}, 0,0 };
    areaCheck( rect );          // Ausgabe: all fine
    Square square{ {0,0}, 0 };
    areaCheck( square );        // Ausgabe: error!
}

Okt 23, 2024

lst-0505-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YWE4bT4zG 
#include <vector>
#include <memory>    // unique_ptr
#include <iostream>  // cout
struct Shape {
    virtual ~Shape() {}
    virtual double area() const = 0; // abstrakt
};
class Rectangle : public Shape {
    double w_, h_;
public:
    Rectangle(double w, double h) : w_{w}, h_{h} {}
    double area() const override { return w_ * h_; }
};
class Circle : public Shape {
    double r_;
public:
    Circle(double r) : r_{r} {}
    double area() const override { return 3.1415*r_* r_; }
};
class AreaCalculator { // Logic
public:
    double area(const std::vector<std::unique_ptr<Shape>> &shapes) const {
        double result = 0;
        for(auto &shape :  shapes) {
            result += shape->area();
        }
        return result;
    }
};
int main() {
    std::vector<std::unique_ptr<Shape>> data{};
    data.push_back(std::make_unique<Circle>(10.));        // ein Kreis
    data.push_back(std::make_unique<Rectangle>(4., 6.));  // ein Rechteck
    // rechnen
    AreaCalculator calc{};
    std::cout  << calc.area( data ) << "\n";
}

Okt 23, 2024

lst-0505-book.cpp

// https://godbolt.org/z/YWE4bT4zG 
#include <vector>
#include <memory>    // unique_ptr
#include <iostream>  // cout
struct Shape {
    virtual ~Shape() {}
    virtual double area() const = 0; // abstrakt
};
class Rectangle : public Shape {
    double w_, h_;
public:
    Rectangle(double w, double h) : w_{w}, h_{h} {}
    double area() const override { return w_ * h_; }
};
class Circle : public Shape {
    double r_;
public:
    Circle(double r) : r_{r} {}
    double area() const override { return 3.1415*r_* r_; }
};
class AreaCalculator { // Logic
public:
    double area(const std::vector<std::unique_ptr<Shape>> &shapes) const {
        double result = 0;
        for(auto &shape :  shapes) {
            result += shape->area();
        }
        return result;
    }
};
int main() {
    std::vector<std::unique_ptr<Shape>> data{};
    data.push_back(std::make_unique<Circle>(10.));        // ein Kreis
    data.push_back(std::make_unique<Rectangle>(4., 6.));  // ein Rechteck
    // rechnen
    AreaCalculator calc{};
    std::cout  << calc.area( data ) << "\n";
}

Okt 23, 2024

lst-0520-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sas3b1E3b 
#include <vector>
#include <iostream>
#include <memory>                    // shared_ptr
#include <random>                    // uniform_int_distribution, random_device
namespace {                          // Beginn des anonymen Namensraums
using std::shared_ptr; using std::make_shared;
using std::vector; using std::cout;
struct Asteroid {
    int points_ = 100;
    int structure_ = 10;
};
struct Ship {
    shared_ptr<Asteroid> firedLastOn_{};
    int score_ = 0;
    int firepower = 1;
    bool fireUpon(shared_ptr<Asteroid> a);
};
struct GameBoard {
    vector<shared_ptr<Asteroid>> asteroids_;
    explicit GameBoard(int nAsteroids);
    bool shipFires(Ship& ship);
};
// Implementierung von Ship
bool Ship::fireUpon(shared_ptr<Asteroid> a) {
    if(!a) return false;             // ungültiger Asteroid
    a->structure_ -= firepower;
    if(a.get() == firedLastOn_.get())
        firepower *= 2 ;             // Schaden vergrößern
    else
        firepower = 1;               // zurücksetzen
    firedLastOn_ = a;
    return a->structure_ <= 0;       // kaputt?
}
// Implementierung von GameBoard
GameBoard::GameBoard(int nAsteroids) : asteroids_{}
{   // einige Standard-Asteroiden
    for(int idx=0; idx<nAsteroids; ++idx)
        asteroids_.push_back( make_shared<Asteroid>() );
}
int wuerfel(int min, int max) {
    /* static std::default_random_engine e{}; */   // Pseudozufallsgenerator
    static std::random_device e{};           // Zufallsgenerator
    return std::uniform_int_distribution<int>{min, max}(e); // würfeln
}
bool GameBoard::shipFires(Ship &ship) {
    int idx = wuerfel(0, asteroids_.size()-1);
    bool kaputt = ship.fireUpon(asteroids_[idx]);
    if(kaputt) {
        ship.score_ += asteroids_[idx]->points_;
        asteroids_.erase(asteroids_.begin()+idx);           // entfernen
    }
    return asteroids_.size() == 0;                          // alles kaputt
}
} // Ende des anonymen Namensraums
int main() {
    GameBoard game{10};                                     // 10 Asteroiden
    Ship ship{};
    for(int idx = 0; idx < 85; ++idx) {                     // 85 Schüsse
        if(game.shipFires(ship)) {
            cout << "Der Weltraum ist nach " << idx+1 << " Schuessen leer. ";
            break;
        }
    }
    cout << "Sie haben " << ship.score_ << " Punkte erreicht.\n";
}

Okt 23, 2024

lst-0545-book.cpp

// https://godbolt.org/z/s6sss481E 
const char vimes[13] = "Samuel Vimes"; // const char[13]
const char colon[] = "Fred Colon";     // const char[11]
const char* nobby = "Nobby Nobbs";     // const char[12]

Okt 23, 2024

lst-0541-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MEqcExjrY 
#include <memory>      // unique_ptr
#include <iostream>    // cout
std::unique_ptr<int[]> createData(size_t sz) {
    return std::unique_ptr<int[]>(new int[sz]);
}
void fibonacci(int data[], int* ende) {
    for(int* p = data+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);
    }
}
std::ostream& print(std::ostream &os, int data[], int* ende) {
    for(int const* p= data; p != ende; ++p)
        std::cout << *p << " ";
    return os;
}
int main() {
    std::unique_ptr<int[]> data { createData(10) };
    data[0] = 1; // setzen Sie Werte im Array durch den unique_ptr
    data[1] = 1;
    fibonacci(data.get(), data.get()+10); // holen Sie sich den C-Array-Zeiger mit get()
    print(std::cout, data.get(), data.get()+10) << "\n";
}

Okt 23, 2024

lst-0548-book.cpp

// https://godbolt.org/z/zsqKz76cj 
#include <iostream>   // cout
#include <iterator>   // ostream_iterator
#include <algorithm>  // copy, ranges::copy
int main () {
  int data[6] = { 1, 2, 3, 7, 9, 10 };
  std::ostream_iterator<int> out_it (std::cout,", ");
  std::copy(data, data+6, out_it);           // Zeiger als Iteratoren
  std::cout << "\n";                         // Ausgabe: 1, 2, 3, 7, 9, 10
  std::ranges::copy(data, out_it);           // C-Array-Zeiger als Range
  std::cout << "\n";                         // Ausgabe: 1, 2, 3, 7, 9, 10
}

Okt 23, 2024

lst-0523-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mqrxxs11Y 
struct StereoImage {
    Image* rechts_;        //             (ERR)  roher Zeiger
    Image* links_;         //             (ERR)  roher Zeiger
    StereoImage(const string& nameBase)           // konstruieren
      : rechts_{new Image{nameBase+"rechts.jpg"}} // okay
      , links_{new Image{nameBase+"links.jpg"}}   // gefährlich
      { }
    ~StereoImage() {       // entfernen
        delete rechts_; delete links_;
    }
    StereoImage(const StereoImage&) = delete;     // keine Kopie
    StereoImage& operator=(const StereoImage&) = delete; // keine Zuweisung
};
int main() {
    Image* bild = new Image{"bild.jpg"};          //             (ERR)  einem rohen Zeiger?
    StereoImage stereo{"3d"};
    delete bild;
}

Okt 23, 2024

lst-0546-book.cpp

// https://godbolt.org/z/oKsz7d55T 
#include <string>
#include <iostream>                    // cout
using std::string; using std::cout;
string greet(string name) {
    return name + "!";                 // string operator+(string, const char*)
}
int main() {
    string name{ "Havaloc Vetinari" }; // explizit: string(const char*)
    cout << "Angua";                   // ostream& operator<<(ostream&, const char*)
    cout <<                            // ostream& operator<<(ostream, string)
      greet("Carrot Ironfoundersson"); // implizit: string(const char*)
}

Okt 23, 2024

lst-0557-book.cpp

// https://godbolt.org/z/6coqbhfKM 
// hier Inhalt von <vector>
// hier Inhalt von <iostream>
using container_type = std::vector<int>;
static constexpr unsigned SIZE = 10;
int main() {
  { (std::cout) << "Programmstart" << "\n"; }
  container_type data(SIZE);
  { (std::cout) << "Der Container hat " << data.size() << " Elemente." << "\n";}
  { (std::cout) << "Programmende" << "\n"; }
  { std::cout << "Das ging ja noch mal gut.\n"; }
}

Okt 23, 2024

lst-0510-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4536hxvEK 
int value = 42;
int& valueRef = value; // Referenz; kein Adressoperator & nötig
valueRef = 18;         // kein Dereferenzierungsoperator * nötig
cout << value << "\n"; // Ausgabe: 18

Okt 23, 2024

lst-0537-book.cpp

// https://godbolt.org/z/1qx16Gr61 
#include <iostream>
void fibonacci(int data[], int* ende) {
    for(int* p = data+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);
    }
}
std::ostream& print(std::ostream &os, int data[], int* ende) {
    for(int const * p=data; p != ende; ++p)
        std::cout << *p << " ";
    return os;
}
int main() {
    int carray[10] = { 1,1 }; // initialisiert zu { 1,1,0,0,0,0,0,0,0,0 }
    fibonacci(carray, carray+10);
    print(std::cout, carray, carray+10) << "\n";
}

Okt 23, 2024

lst-0552-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zG91TMEa8 
// Dateiname: makros.cpp
#define AUSGABE_AUF_STANDARD // Umschalten von cerr und cout
#include "meine-makros.hpp"
#include "meine-makros.hpp"  // Ups, aus Versehen doppelt.
int main() {
    MESSAGE("Programmstart");
    container_type data(SIZE);
    MESSAGE("Der Container hat " << data.size() << " Elemente.");
    MESSAGE("Programmende");
    OUT << "Das ging ja noch mal gut.\n";
}

Okt 23, 2024

lst-0504-book.cpp

// https://godbolt.org/z/vxTsveGjT 
#include <vector>
#include <memory> // unique_ptr
#include <iostream> // cout
enum class ShapeTag { CIRC, RECT };
struct Shape { // Data
    ShapeTag tag_;
    double v1_, v2_;
    Shape(double w, double h) : tag_{ShapeTag::RECT}, v1_{w}, v2_{h} {}
    Shape(double r) : tag_{ShapeTag::CIRC}, v1_{r}, v2_{0} {}
};
class AreaCalculator { // Logic
public:
    double area(const std::vector<std::unique_ptr<Shape>> &shapes) const {
        double result = 0;
        for(auto &shape :  shapes) {
            switch(shape->tag_) {
            case ShapeTag::CIRC:
                 result += 3.1415 * shape->v1_ * shape->v1_;
                 break;
            case ShapeTag::RECT:
                 result += shape->v1_*shape->v2_;
                 break;
            }
        }
        return result;
    }
};
int main() {
    std::vector<std::unique_ptr<Shape>> data{};
    data.push_back(std::make_unique<Shape>(10.));     // ein Kreis
    data.push_back(std::make_unique<Shape>(4., 6.));  // ein Rechteck
    // rechnen
    AreaCalculator calc{};
    std::cout  << calc.area( data ) << "\n";
}

Okt 23, 2024

lst-0518-book.cpp

// https://godbolt.org/z/Eh9ox6x9E 
#include <memory>                        // unique_ptr
#include <string>
#include <iostream>
using std::unique_ptr; using std::string;
class Component { };                     // Dummy-Fensterhierarchie
class Label : public Component { };
class Textfield : public Component { };
class Button : public Component {
public:
    int id_; // ID zur Unterscheidung der Buttons
    explicit Button(int id) : id_{id} {}
};
class Window { };
class MyDialog : public Window {
    string title_;
    unique_ptr<Label> lblVorname_{new Label{}};         // lauter Datenfelder
    unique_ptr<Textfield> txtVorname_{new Textfield{}}; // … an die Lebensdauer
    unique_ptr<Label> lblNachname_{new Label{}};        // … der Klasse gebunden
    unique_ptr<Textfield> txtNachname_{new Textfield{}};
    unique_ptr<Button> btnOk_{new Button{1}};
    unique_ptr<Button> btnAbbrechen_{new Button{2}};
public:
    explicit MyDialog(const string& title) : title_{title} {}
    unique_ptr<Button> showModal()
        { return std::move(btnOk_); }    // Platzhaltercode; OK gedrückt
};
unique_ptr<MyDialog> createDialog() {
    return unique_ptr<MyDialog>{ // temporärer Wert
        new MyDialog{"Bitte Namen eingeben"}};
}
int showDialog() {
    unique_ptr<MyDialog> dialog = createDialog();       // lokale Variable
    unique_ptr<Button> gedrueckt = dialog->showModal(); // Rückgabewert
    return gedrueckt->id_;
}
int main() {
    int gedrueckt_id = showDialog();
    if(gedrueckt_id == 1) {
        std::cout << "Danke, dass Sie OK gedrueckt haben\n";
    }
}

Okt 23, 2024

lst-0511-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qTxs8bTdz 
#include <vector>
#include <iostream>
using std::vector; using std::cout; using std::ostream;
ostream& printVector(ostream& os, const vector<int> &arg) { // Hilfsfunktion
    for(int w : arg) os << w << " "; return os;
}
int main() {
    vector<int> werte{ };
    werte.reserve(50);                      // Platz für 50 Werte garantieren
    int *groesstes = nullptr;               // mit besonderem Wert initialisieren
    for(int w : { 20, 2, 30, 15, 81, 104, 70, 2, }) {
        werte.push_back(w);
        if(!groesstes || *groesstes < w ) { // dereferenzieren zum Wert
            groesstes = &(werte.back());    // neue Adresse merken; deshalb nicht '*'
        }
    }
    printVector(cout, werte) << "\n";       // Ausgabe: 20 2 30 15 81 104 70 2
    // groesstes enthält nun die Adresse der 104:
    *groesstes = -999;                // dereferenzieren; also Wert überschreiben
    printVector(cout, werte) << "\n";       // Ausgabe: 20 2 30 15 81 999 70 2
}

Okt 23, 2024

lst-0551-book.cpp

// https://godbolt.org/z/MjcvochqP 
// Dateiname: meine-makros.hpp
#ifndef MEINE_MAKROS_HPP  // Include Guard
#define MEINE_MAKROS_HPP
#include <iostream> // cout, cerr
#include <vector>
#ifdef AUSGABE_AUF_STANDARD
#  define OUT std::cout
#else
#  define OUT std::cerr
#endif
#define MESSAGE(text) { (OUT) << text << "\n"; }
using container_type = std::vector<int>;
static constexpr unsigned SIZE = 10;
#endif

Okt 23, 2024

lst-0507-book.cpp

// https://godbolt.org/z/Gxh4edc8n 
using std::vector;

struct B {};
struct D : public B {};

struct Base1 {
    virtual B& func();
};
struct Derived1 : public Base1 {
    virtual D& func() override;         // D& ist kovariant
};
struct Base2 {
    virtual B& func();
};
struct Derived2 : public Base2 {
    virtual D func() override;          //                     (ERR)  D ist nicht kovariant
};
struct Base3 {
    virtual vector<B> func();
};
struct Derived3 : public Base3 {
    virtual vector<D>& func() override; //                     (ERR)  vector<D>& ist nicht kovariant
};
struct Base4 {
    virtual vector<B*>& func();
};
struct Derived4 : public Base4 {
    virtual vector<D*>& func() override; //                     (ERR)  anderer Typ, nicht kovariant
};

Okt 23, 2024

lst-0551-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MjcvochqP 
// Dateiname: meine-makros.hpp
#ifndef MEINE_MAKROS_HPP  // Include Guard
#define MEINE_MAKROS_HPP
#include <iostream> // cout, cerr
#include <vector>
#ifdef AUSGABE_AUF_STANDARD
#  define OUT std::cout
#else
#  define OUT std::cerr
#endif
#define MESSAGE(text) { (OUT) << text << "\n"; }
using container_type = std::vector<int>;
static constexpr unsigned SIZE = 10;
#endif

Okt 23, 2024

lst-0533-book.cpp

// https://godbolt.org/z/3zrK76zn8 
#include <iostream>
int main() {
    int carray[10] = { 1,1 };               // initialisiert zu { 1,1,0,0,0,0,0,0,0,0 }
    int* ende = carray+10;                  // Zeiger hinter das letzte Element
    for(int* p =carray+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);               // addiert die vorigen beiden Zahlen
    }
    for(int const * p=carray; p != ende; ++p)
        std::cout << *p << " ";
    std::cout << "\n";
}

Okt 23, 2024

lst-0552-book.cpp

// https://godbolt.org/z/zG91TMEa8 
// Dateiname: makros.cpp
#define AUSGABE_AUF_STANDARD // Umschalten von cerr und cout
#include "meine-makros.hpp"
#include "meine-makros.hpp"  // Ups, aus Versehen doppelt.
int main() {
    MESSAGE("Programmstart");
    container_type data(SIZE);
    MESSAGE("Der Container hat " << data.size() << " Elemente.");
    MESSAGE("Programmende");
    OUT << "Das ging ja noch mal gut.\n";
}

Okt 23, 2024

lst-0545-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s6sss481E 
const char vimes[13] = "Samuel Vimes"; // const char[13]
const char colon[] = "Fred Colon";     // const char[11]
const char* nobby = "Nobby Nobbs";     // const char[12]

Okt 23, 2024

lst-0518-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Eh9ox6x9E 
#include <memory>                        // unique_ptr
#include <string>
#include <iostream>
using std::unique_ptr; using std::string;
class Component { };                     // Dummy-Fensterhierarchie
class Label : public Component { };
class Textfield : public Component { };
class Button : public Component {
public:
    int id_; // ID zur Unterscheidung der Buttons
    explicit Button(int id) : id_{id} {}
};
class Window { };
class MyDialog : public Window {
    string title_;
    unique_ptr<Label> lblVorname_{new Label{}};         // lauter Datenfelder
    unique_ptr<Textfield> txtVorname_{new Textfield{}}; //  an die Lebensdauer
    unique_ptr<Label> lblNachname_{new Label{}};        //  der Klasse gebunden
    unique_ptr<Textfield> txtNachname_{new Textfield{}};
    unique_ptr<Button> btnOk_{new Button{1}};
    unique_ptr<Button> btnAbbrechen_{new Button{2}};
public:
    explicit MyDialog(const string& title) : title_{title} {}
    unique_ptr<Button> showModal()
        { return std::move(btnOk_); }    // Platzhaltercode; OK gedrückt
};
unique_ptr<MyDialog> createDialog() {
    return unique_ptr<MyDialog>{ // temporärer Wert
        new MyDialog{"Bitte Namen eingeben"}};
}
int showDialog() {
    unique_ptr<MyDialog> dialog = createDialog();       // lokale Variable
    unique_ptr<Button> gedrueckt = dialog->showModal(); // Rückgabewert
    return gedrueckt->id_;
}
int main() {
    int gedrueckt_id = showDialog();
    if(gedrueckt_id == 1) {
        std::cout << "Danke, dass Sie OK gedrueckt haben\n";
    }
}

Okt 23, 2024

lst-0533-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3zrK76zn8 
#include <iostream>
int main() {
    int carray[10] = { 1,1 };               // initialisiert zu { 1,1,0,0,0,0,0,0,0,0 }
    int* ende = carray+10;                  // Zeiger hinter das letzte Element
    for(int* p =carray+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);               // addiert die vorigen beiden Zahlen
    }
    for(int const * p=carray; p != ende; ++p)
        std::cout << *p << " ";
    std::cout << "\n";
}

Okt 23, 2024

lst-0546-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oKsz7d55T 
#include <string>
#include <iostream>                    // cout
using std::string; using std::cout;
string greet(string name) {
    return name + "!";                 // string operator+(string, const char*)
}
int main() {
    string name{ "Havaloc Vetinari" }; // explizit: string(const char*)
    cout << "Angua";                   // ostream& operator<<(ostream&, const char*)
    cout <<                            // ostream& operator<<(ostream, string)
      greet("Carrot Ironfoundersson"); // implizit: string(const char*)
}

Okt 23, 2024

lst-0565-book.cpp

// https://godbolt.org/z/jzKfabPh3 
#include <cmath> // sin, cos
constexpr double max2(double a, double b) { return a > b ? a : b; }
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    double f = max2(sin(3.141592/2), cos(3.141592/2));
    double e = MAX2(sin(3.141592/2), cos(3.141592/2));
}

Okt 23, 2024

lst-0511-book.cpp

// https://godbolt.org/z/qTxs8bTdz 
#include <vector>
#include <iostream>
using std::vector; using std::cout; using std::ostream;
ostream& printVector(ostream& os, const vector<int> &arg) { // Hilfsfunktion
    for(int w : arg) os << w << " "; return os;
}
int main() {
    vector<int> werte{ };
    werte.reserve(50);                      // Platz für 50 Werte garantieren
    int *groesstes = nullptr;               // mit besonderem Wert initialisieren
    for(int w : { 20, 2, 30, 15, 81, 104, 70, 2, }) {
        werte.push_back(w);
        if(!groesstes || *groesstes < w ) { // dereferenzieren zum Wert
            groesstes = &(werte.back());    // neue Adresse merken; deshalb nicht '*'
        }
    }
    printVector(cout, werte) << "\n";       // Ausgabe: 20 2 30 15 81 104 70 2
    // groesstes enthält nun die Adresse der 104:
    *groesstes = -999;                // dereferenzieren; also Wert überschreiben
    printVector(cout, werte) << "\n";       // Ausgabe: 20 2 30 15 81 –999 70 2
}

Okt 23, 2024

lst-0506-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rc67xWWfT 
#include <iostream>
struct Point { int x, y; };
class Rectangle {
protected:
    Point origin_;  int width_;  int height_;
public:
    Rectangle(Point o, int w, int h) : origin_{o}, width_{w}, height_{h} {}
    virtual void setHeight(int height) { height_ = height; }
    virtual int  getHeight() const { return height_; }
    virtual void setWidth(int width) { width_ = width; }
    virtual int getWidth() const { return width_; }
    virtual int getArea() const { return width_ * height_; }
};
class Square : public Rectangle {
public:
    Square(Point o, int wh) : Rectangle{o, wh, wh} {}
    void setHeight(int wh) override { width_ = height_ = wh; }
    void setWidth(int wh) override { width_ = height_ = wh; }
};
void areaCheck(Rectangle &rect) {
    rect.setWidth(5);
    rect.setHeight(4);
    auto areaValue = rect.getArea();
    if(areaValue != 20) {
        std::cout << "error!\n";
    } else {
        std::cout << "all fine\n";
    }
}
int main() {
    Rectangle rect{ {0,0}, 0,0 };
    areaCheck( rect );          // Ausgabe: all fine
    Square square{ {0,0}, 0 };
    areaCheck( square );        // Ausgabe: error!
}

Okt 23, 2024

lst-0525-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YMe5PY6aT 
#include <vector>
#include <numeric>   // iota
#include <iostream>
using std::vector; using std::cout;
struct Zahl {        // stellvertretend für ein großes, teures Objekt
    unsigned long val_;
    Zahl(unsigned long val) : val_{val} {}
    Zahl() : val_{0} {}
};
/* ermittelt anhand bisheriger Primzahlen, ob z eine Primzahl ist */
bool isPrim(const Zahl& z, const vector<Zahl*> prims) {
    for(Zahl* p : prims) {
        if((p->val_*p->val_) > z.val_) return true;   // zu groß
        if(z.val_ % p->val_ == 0) return false;       // ist Teiler
    }
    return true;
}
int main() {
    vector<Zahl> alleZahlen(98);   // 98 mit null initialisierte Elemente
    std::iota(begin(alleZahlen), end(alleZahlen), 3); // 3..100
    /* alleZahlen enthält jetzt {3..100} */
    vector<Zahl*> prims{};         // bekommt ermittelte Primzahlen
    Zahl zwei{2};
    prims.push_back(&zwei);        // die 2 wird gebraucht
    for(Zahl &z : alleZahlen) {    // über alle Zahlen iterieren
        if(isPrim(z, prims)) {
            prims.push_back( &z ); // speichere Adresse
        }
    }
    /* Rest ausgeben */
    for(Zahl* p : prims)
        cout << p->val_ << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0507-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gxh4edc8n 
using std::vector;

struct B {};
struct D : public B {};

struct Base1 {
    virtual B& func();
};
struct Derived1 : public Base1 {
    virtual D& func() override;         // D& ist kovariant
};
struct Base2 {
    virtual B& func();
};
struct Derived2 : public Base2 {
    virtual D func() override;          //                     (ERR)  D ist nicht kovariant
};
struct Base3 {
    virtual vector<B> func();
};
struct Derived3 : public Base3 {
    virtual vector<D>& func() override; //                     (ERR)  vector<D>& ist nicht kovariant
};
struct Base4 {
    virtual vector<B*>& func();
};
struct Derived4 : public Base4 {
    virtual vector<D*>& func() override; //                     (ERR)  anderer Typ, nicht kovariant
};

Okt 23, 2024

lst-0499-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r1vYc7r5j 
#include <array>
#include <iostream>
#include <type_traits> // is_literal_type
class Value {
    int val_;
public:
    constexpr Value(int val) : val_{val} {};
    constexpr operator int() const { return val_; }
};
namespace lit {
    constexpr Value operator"" _val(const char*, size_t sz) { 
      return Value(sz); }
}
struct Nope {
    constexpr Nope() {};
    virtual ~Nope() {};                // nicht trivialer Destruktor
};
int main() {
    using namespace lit;
    constexpr Value fuenf{5};
    std::array<int,"11111"_val> data;  // benutzerdefiniertes Literal verwenden
    std::cout << data.size() << '\n';                        // Ausgabe: 5
    std::cout << std::boolalpha;
    std::cout << std::is_literal_type<Value>::value << '\n'; // Ausgabe: true
    std::cout << std::is_literal_type<Nope>::value << '\n';  // Ausgabe: false
}

Okt 23, 2024

lst-0485-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a5WxqjxEr 
int main() {
    Clock clock{ 23, 59, 59 };
    std::cout << clock << '\n'; // Ausgabe: 23:59:59
    clock.tick();
    std::cout << clock << '\n'; // Ausgabe: 00:00:00
}

Okt 23, 2024

lst-0489-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/P6nzT7EY4 
int main() {
    CalendarClock cc{ 2024,2,29, 23,59,59 };
    std::cout << cc << '\n'; // Ausgabe: 2024-02-29 23:59:59
    cc.tick();
    std::cout << cc << '\n'; // Ausgabe: 2024-03-01 00:00:00
}

Okt 23, 2024

lst-0476-book.cpp

// https://godbolt.org/z/zMvWxT854 
#include <iostream>
using std::cout; using std::ostream;
class Basis {
    public: int daten = 5;
};
class Mitte : private Basis {
protected: void drucke() {
        cout << daten; // 'daten' ist hier privat geerbt
    }
};
class Letztendlich : public Mitte {
    public: void los() {
        // 'daten' ist nicht sichtbar
        drucke(); // 'drucke' ist geschützt sichtbar
    }
};
int main() {
    Letztendlich l {};
    l.los(); // Ausgabe: 5
}

Okt 23, 2024

lst-0476-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zMvWxT854 
#include <iostream>
using std::cout; using std::ostream;
class Basis {
    public: int daten = 5;
};
class Mitte : private Basis {
protected: void drucke() {
        cout << daten; // 'daten' ist hier privat geerbt
    }
};
class Letztendlich : public Mitte {
    public: void los() {
        // 'daten' ist nicht sichtbar
        drucke(); // 'drucke' ist geschützt sichtbar
    }
};
int main() {
    Letztendlich l {};
    l.los(); // Ausgabe: 5
}

Okt 23, 2024

lst-0493-book.cpp

// https://godbolt.org/z/EnE7Y886M 
#include <iostream>
#include <vector>
using std::cout;
// == Beobachter-Entwurfsmuster ==
struct Observer {
    virtual void update() = 0;
};
class Subject {
    std::vector<Observer*> observers_; // not owning pointers
protected:
    void notify() {
        for (auto o : observers_)
            o->update();
    }
public:
    void addObserver(Observer* o) {
        observers_.push_back(o);
    }
};
// == konkrete Klasse ==
struct MyThing {
    int calc() { return 1+1; }
};
// == zusammenbringen ==
struct MyObservableThing : public MyThing, public Subject {
    int calc() {
        notify();
        return MyThing::calc();
    }
};
// == etwas beobachten ==
struct MyObserver : public Observer {
    void update() override {
        cout << "observed\n";
    }
};
int main() {
    MyObserver myObserver{};
    MyObservableThing myObservableThing{};
    myObservableThing.addObserver(&myObserver);
    auto result = myObservableThing.calc(); // Ausgabe: observed
}

Okt 23, 2024

lst-0487-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xf1xq8Ts3 
int main() {
    Calendar cal{ 2024, 2, 28 };
    std::cout << cal << '\n'; // Ausgabe: 2024-02-28
    cal.advance();
    std::cout << cal << '\n'; // Ausgabe: 2024-02-29
    cal.advance();
    std::cout << cal << '\n'; // Ausgabe: 2024-03-01
}

Okt 23, 2024

lst-0501-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/scqTWvhsv 
class Auto { };
  class VwBulli : public Auto { };
  class Ente : public Auto { };
void lassFahren(Auto wagen) { }   //             (ERR)  Wertparameter kopiert nur Basisklasse
void lassBremsen(Auto &wagen) { } // Referenzparameter
void lassHupen(Auto *wagen) { }   // Übergabe als Zeiger
int main() {
    VwBulli bulli{  };            // automatische Variable
    Auto *ente = new Ente{  };    // dynamisch verwaltet
    lassFahren(bulli);            //             (ERR)  wird zum Auto kopiert
    lassFahren(*ente);            //             (ERR)  wird zum Auto kopiert
    lassBremsen(bulli);           // bleibt VwBulli
    lassBremsen(*ente);           // bleibt Ente
    lassHupen(&bulli);            // bleibt VwBulli
    lassHupen(ente);              // bleibt Ente
}

Okt 23, 2024

lst-0480-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7xf6sxPqG 
#include <iostream>
using std::cout;
struct KeyboardDriver : public Driver {
    void init() override { cout << "Init Keyboard\n"; }
    void done() override { cout << "Done Keyboard\n"; }
    bool send(const char* data, unsigned int len) override {
        cout << "sending " << len << " bytes\n";
        return true;
    }
};
struct Computer {
    Driver &driver_;
    explicit Computer(Driver &driver) : driver_{driver} {
        driver_.init();
    }
    void run() {
        driver_.send("Hello", 5);
    }
    ~Computer() {
        driver_.done();
    }
    Computer(const Computer&) = delete;
};
int main() {
    KeyboardDriver keyboard {};
    Computer computer(keyboard); // Ausgabe: Init Keyboard
    computer.run();              // Ausgabe: sending 5 bytes
}                                // Ausgabe: Done Keyboard

Okt 23, 2024

lst-0492-book.cpp

// https://godbolt.org/z/oc7jsbrEK 
#include <iostream>
using std::cout;
struct Base1 {
    virtual void f1() {}
};
struct Base2 {
    virtual void f2() {}
};
struct Derived : public Base1, public Base2 {
    virtual void g() {};
};
void vergleich(void* a, void* b) {
    cout << (a==b ? "identisch\n" : "unterschiedlich\n");
}
int main() {
    Derived d{};
    auto *pd = &d;
    cout << pd << '\n';       // zum Beispiel 0x1000
    auto pb1 = static_cast<Base1*>(pd);
    cout << pb1 << '\n';      // immer noch 0x1000
    auto pb2 = static_cast<Base2*>(pd);
    cout << pb2 << '\n';      // jetzt 0x1008 !
    cout << (pd==pb1 ? "gleich\n" : "verschieden\n"); // Ausgabe: gleich
    cout << (pd==pb2 ? "gleich\n" : "verschieden\n"); // Ausgabe: gleich
    vergleich(pb1, pd);       // Ausgabe: identisch
    vergleich(pb2, pd);       // Ausgabe: unterschiedlich
}

Okt 23, 2024

lst-0493-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EnE7Y886M 
#include <iostream>
#include <vector>
using std::cout;
// == Beobachter-Entwurfsmuster ==
struct Observer {
    virtual void update() = 0;
};
class Subject {
    std::vector<Observer*> observers_; // not owning pointers
protected:
    void notify() {
        for (auto o : observers_)
            o->update();
    }
public:
    void addObserver(Observer* o) {
        observers_.push_back(o);
    }
};
// == konkrete Klasse ==
struct MyThing {
    int calc() { return 1+1; }
};
// == zusammenbringen ==
struct MyObservableThing : public MyThing, public Subject {
    int calc() {
        notify();
        return MyThing::calc();
    }
};
// == etwas beobachten ==
struct MyObserver : public Observer {
    void update() override {
        cout << "observed\n";
    }
};
int main() {
    MyObserver myObserver{};
    MyObservableThing myObservableThing{};
    myObservableThing.addObserver(&myObserver);
    auto result = myObservableThing.calc(); // Ausgabe: observed
}

Okt 23, 2024

lst-0503-book.cpp

// https://godbolt.org/z/Tq9xbGxs4 
struct Buch {
   auto getTitel() { return Titel{"Das C++ Handbuch"s}; }
   auto getAutor() { return Autor{"Torsten T. Will"s}; }
   auto umblaettern() { return /* Referenz zur nächsten Seite */ 42; }
   auto getSeite() { return "aktueller Seiteninhalt"; }
   auto getStandort() { return /* Regalnummer/Buchnummer */ 73; }
};
struct BuchFinder {
    Katalog katalog;
    auto finde(Buch& buch) { /* Regalnummer/Buchnummer */
        katalog.findeBuchNach(buch.getTitel(), buch.getAutor());
    }
};

Okt 23, 2024

lst-0479-book.cpp

// https://godbolt.org/z/rW4oTPhrG 
struct Driver {
    virtual void init() = 0;
    virtual void done() = 0;
    virtual bool send(const char* data, unsigned len) = 0;
};

Okt 23, 2024

lst-0492-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oc7jsbrEK 
#include <iostream>
using std::cout;
struct Base1 {
    virtual void f1() {}
};
struct Base2 {
    virtual void f2() {}
};
struct Derived : public Base1, public Base2 {
    virtual void g() {};
};
void vergleich(void* a, void* b) {
    cout << (a==b ? "identisch\n" : "unterschiedlich\n");
}
int main() {
    Derived d{};
    auto *pd = &d;
    cout << pd << '\n';       // zum Beispiel 0x1000
    auto pb1 = static_cast<Base1*>(pd);
    cout << pb1 << '\n';      // immer noch 0x1000
    auto pb2 = static_cast<Base2*>(pd);
    cout << pb2 << '\n';      // jetzt 0x1008 !
    cout << (pd==pb1 ? "gleich\n" : "verschieden\n"); // Ausgabe: gleich
    cout << (pd==pb2 ? "gleich\n" : "verschieden\n"); // Ausgabe: gleich
    vergleich(pb1, pd);       // Ausgabe: identisch
    vergleich(pb2, pd);       // Ausgabe: unterschiedlich
}

Okt 23, 2024

lst-0481-book.cpp

// https://godbolt.org/z/G1q964f1M 
#include <iostream>           // cout
#include <memory>             // unique_ptr
using std::cout;
class Driver {                // abstrakte Basisklasse
public:
    virtual void init() = 0;
    virtual void done() = 0;
    virtual void send(const std::string &data) = 0;
};
class ProductionDriver : public Driver {
public:
    void init() override { }
    void done() override { }
    void send(const std::string &data) override { cout << data << "\n"; }
};
class DebuggingDriver : public Driver {
   size_t countSend_ = 0;
public:
    void init() override {
        countSend_= 0; cout << "Ok, bin initialisiert.\n";
    }
    void done() override {
        cout << "send benutzt:" << countSend_ << " mal\n";
    }
    void send(const std::string &data) override {
        cout << "send("<<countSend_<<"):"<< data << "\n";
        ++countSend_;
    }
};
struct DriverWrapper {        // RAII-Wrapper für init() und done()
    Driver &driver_;
    explicit DriverWrapper(Driver& driver) : driver_(driver) { driver_.init(); }
    ~DriverWrapper() { driver_.done(); }
    DriverWrapper(const DriverWrapper&) = delete; // nicht kopieren
};

void doWork(Driver &driver) { // jemand, der flexibel einen beliebigen Driver nutzt
    DriverWrapper wrapper(driver);      // init() und done() aufrufen
    driver.send("Eine unerwartete Reise");
    driver.send("Smaugs Einoede");
}

int main() {
    // gleiche doWork, einmal mit Produktions- und einmal mit Debugging-Treiber
    ProductionDriver production{};
    doWork( production );
    DebuggingDriver debugging{};
    doWork( debugging );

    // üblichere Variante eines dynamisch erzeugten Treibers
    std::unique_ptr<Driver> driver{ new ProductionDriver{} };
    doWork( *driver );
}

Okt 23, 2024

lst-0487-book.cpp

// https://godbolt.org/z/xf1xq8Ts3 
int main() {
    Calendar cal{ 2024, 2, 28 };
    std::cout << cal << '\n'; // Ausgabe: 2024-02-28
    cal.advance();
    std::cout << cal << '\n'; // Ausgabe: 2024-02-29
    cal.advance();
    std::cout << cal << '\n'; // Ausgabe: 2024-03-01
}

Okt 23, 2024

lst-0495-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s9xnn7c5j 
#include <iostream>
using std::cout;
struct Base { // abstrakte Klasse
  virtual void anbieter() = 0;
  virtual void nutzer() = 0;
};
struct Derived1 : public virtual Base { // noch abstrakt
  virtual void nutzer() override { anbieter(); }
};
struct Derived2 : public virtual Base { // noch abstrakt
  virtual void anbieter() override { cout << "Derived2::anbieter!\n"; }
};
struct DerivedDerived : public Derived1, public Derived2 { // konkret
};
int main() {
  DerivedDerived dd{};
  DerivedDerived *pdd = &dd;
  Derived1* pd1 = pdd; // Cast innerhalb der Hierarchie
  Derived2* pd2 = pdd; // Cast innerhalb der Hierarchie
  pdd->nutzer();       // Ausgabe: Derived2::anbieter()!
  pd1->nutzer();       // Ausgabe: Derived2::anbieter()!
  pd2->nutzer();       // Ausgabe: Derived2::anbieter()!
}

Okt 23, 2024

lst-0489-book.cpp

// https://godbolt.org/z/P6nzT7EY4 
int main() {
    CalendarClock cc{ 2024,2,29, 23,59,59 };
    std::cout << cc << '\n'; // Ausgabe: 2024-02-29 23:59:59
    cc.tick();
    std::cout << cc << '\n'; // Ausgabe: 2024-03-01 00:00:00
}

Okt 23, 2024

lst-0475-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xKEo38c4n 
#include <iostream>
using std::cout; using std::ostream;
//  wie zuvor 
struct Normalfall : public DerivedPublic {
    void drucke() {
        cout << xPublic;
        cout << xProtected;
    }
};
struct Spezialfall : public DerivedPrivate {
    void drucke() {
        cout << xPublic;                  //                 (ERR)  kein Zugriff
        cout << xProtected;               //                 (ERR)  kein Zugriff
    }
};
int main() {
    Normalfall n {};
    n.drucke(); // Ausgabe: 12
    Spezialfall s {};
    s.drucke();
}

Okt 23, 2024

lst-0479-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rW4oTPhrG 
struct Driver {
    virtual void init() = 0;
    virtual void done() = 0;
    virtual bool send(const char* data, unsigned len) = 0;
};

Okt 23, 2024

lst-0477-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zzT17q588 
class Motor {
public:
  Motor(int anzZylinder);
  void start();                  // Motor starten
};
class Auto : private Motor {     // Auto hat-einen Motor
public:
  Auto() : Motor{8} { }          // initialisiert ein Auto mit 8 Zylindern
  using Motor::start;            // startet Auto durch Starten des Motors
};

Okt 23, 2024

lst-0478-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8jGWTqh9z 
class Auto {
public:
  Auto() : motor_{8} { }           // initialisiert ein Auto mit 8 Zylindern
  void start() { motor_.start(); } // startet Auto durch Starten des Motors
private:
  Motor motor_;                    // Auto hat-einen Motor
};

Okt 23, 2024

lst-0498-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Kvfx9Yeox 
#include <array>
class Value {
    int val_;
public:
    constexpr Value(int val) : val_{val} {};
    constexpr int get() const { return val_; }
};

constexpr Value fuenf{5}; // geht, Value ist literaler Datentyp

std::array<int,fuenf.get()> data; // geht, get ist constexpr

Okt 23, 2024

lst-0494-book.cpp

// https://godbolt.org/z/8jYeYPs7W 
#include <iostream>
using std::cout;
class Base {
public:
  int data_ = 0;
};
class Derived1 : public virtual Base {
};
class Derived2 : public virtual Base {
};
class DerivedDerived : public Derived1, public Derived2 {
public:
  void method() {
     data_ = 1;  // eindeutig, denn es gibt nur ein data_
  }
};
void ausgabe(const DerivedDerived &dd) {
    cout << dd.data_
        << (((Derived1&)dd).data_)
        << (((Derived2&)dd).data_)
        << (((Base&)dd).data_) << '\n';
}
int main() {
  DerivedDerived dd{};
  ausgabe(dd);   // Ausgabe: 0000
  dd.method();   // setzt data_ auf 1
  ausgabe(dd);   // Ausgabe: 1111
}

Okt 23, 2024

lst-0477-book.cpp

// https://godbolt.org/z/zzT17q588 
class Motor {
public:
  Motor(int anzZylinder);
  void start();                  // Motor starten
};
class Auto : private Motor {     // Auto hat-einen Motor
public:
  Auto() : Motor{8} { }          // initialisiert ein Auto mit 8 Zylindern
  using Motor::start;            // startet Auto durch Starten des Motors
};

Okt 23, 2024

lst-0502-book.cpp

// https://godbolt.org/z/fdh4n5x84 
struct Buch {
   auto getTitel() { return Titel{"Das C++ Handbuch"s}; }
   auto getAutor() { return Autor{"Torsten T. Will"s}; }
   auto umblaettern() { return /* Referenz zur nächsten Seite */ 42; }
   auto getSeite() { return "aktueller Seiteninhalt"; }
   auto getStandort() { return /* Regalnummer/Buchnummer */ 73; }
};

Okt 23, 2024

lst-0488-book.cpp

// https://godbolt.org/z/rh179GW3j 
class CalendarClock : public Clock, public Calendar {
public:
    CalendarClock(int y, int m, int d, int hh, int mm, int ss)
    : Calendar{y,m,d}, Clock{hh,mm,ss} {}
    void tick() {         // +1 Sekunde
        auto prev_h = h_;
        Clock::tick();    // Aufruf Basisklassenmethode
        if(h_ < prev_h) { // falls neuer Tag
            advance();    //  Kalender fortschreiten
        }
    }
    friend ostream& operator<<(ostream&os, const CalendarClock& cc) {
        operator<<(os, (Calendar&)cc) << " "; // Aufruf freie Funktion
        operator<<(os, (Clock&)cc);           // Aufruf freie Funktion
        return os;
    }
};

Okt 23, 2024

lst-0495-book.cpp

// https://godbolt.org/z/s9xnn7c5j 
#include <iostream>
using std::cout;
struct Base { // abstrakte Klasse
  virtual void anbieter() = 0;
  virtual void nutzer() = 0;
};
struct Derived1 : public virtual Base { // noch abstrakt
  virtual void nutzer() override { anbieter(); }
};
struct Derived2 : public virtual Base { // noch abstrakt
  virtual void anbieter() override { cout << "Derived2::anbieter!\n"; }
};
struct DerivedDerived : public Derived1, public Derived2 { // konkret
};
int main() {
  DerivedDerived dd{};
  DerivedDerived *pdd = &dd;
  Derived1* pd1 = pdd; // Cast innerhalb der Hierarchie
  Derived2* pd2 = pdd; // Cast innerhalb der Hierarchie
  pdd->nutzer();       // Ausgabe: Derived2::anbieter()!
  pd1->nutzer();       // Ausgabe: Derived2::anbieter()!
  pd2->nutzer();       // Ausgabe: Derived2::anbieter()!
}

Okt 23, 2024

lst-0486-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oe1hT9McG 
//  includes und usings 
struct Calendar {
    int y_, m_, d_;
    static const std::vector<int> mlens_;
    bool leapyear() const {
        if(y_ % 4 != 0) return false;
        if(y_ % 100 != 0) return true;
        if(y_ % 400 != 0) return false;
        return true;
    }
public:
    Calendar(int year, int month, int day)
    : y_{year}, m_{month}, d_{day} {}
    void setCalendar(int year, int month, int day) {
        y_ = year; m_ = month; d_ = day;
    }
    friend ostream& operator<<(ostream& os, const Calendar& c) {
        return os << format("{:04}-{:02}-{:02}", c.y_, c.m_, c.d_);
    }
    void advance() { // +1 day
        auto maxd = mlens_[m_-1]; // 0-basierter vector
        if(m_==2 && leapyear())
            maxd += 1;            // Februar im Schaltjahr
        if(d_ >= maxd) {
            d_ = 1;
            if(m_ >= 12) { m_ = 1; y_ += 1; }
            else { m_ += 1; }
        } else { d_ += 1; }
    }
};
const std::vector<int> Calendar::mlens_ = {31,28,31,30,31,30,31,31,30,31,30,31};

Okt 23, 2024

lst-0503-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Tq9xbGxs4 
struct Buch {
   auto getTitel() { return Titel{"Das C++ Handbuch"s}; }
   auto getAutor() { return Autor{"Torsten T. Will"s}; }
   auto umblaettern() { return /* Referenz zur nächsten Seite */ 42; }
   auto getSeite() { return "aktueller Seiteninhalt"; }
   auto getStandort() { return /* Regalnummer/Buchnummer */ 73; }
};
struct BuchFinder {
    Katalog katalog;
    auto finde(Buch& buch) { /* Regalnummer/Buchnummer */
        katalog.findeBuchNach(buch.getTitel(), buch.getAutor());
    }
};

Okt 23, 2024

lst-0483-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MPaYW1v5j 
#include <iostream>
using std::cout;
class Saeugetier {
public:
    void gebaere() { cout << "Geburt!\n"; }
};
class Fliegend {
public:
    void fliege() { cout << "Flug!\n"; }
};
class Fledermaus: public Saeugetier, public Fliegend {
public:
    void rufe() { cout << "Ultraschall!\n"; }
};
int main() {
    Fledermaus bruce{};
    bruce.gebaere();       // Ausgabe: Geburt!
    bruce.fliege();        // Ausgabe: Flug!
    bruce.rufe();          // Ausgabe: Ultraschall!
}

Okt 23, 2024

lst-0494-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8jYeYPs7W 
#include <iostream>
using std::cout;
class Base {
public:
  int data_ = 0;
};
class Derived1 : public virtual Base {
};
class Derived2 : public virtual Base {
};
class DerivedDerived : public Derived1, public Derived2 {
public:
  void method() {
     data_ = 1;  // eindeutig, denn es gibt nur ein data_
  }
};
void ausgabe(const DerivedDerived &dd) {
    cout << dd.data_
        << (((Derived1&)dd).data_)
        << (((Derived2&)dd).data_)
        << (((Base&)dd).data_) << '\n';
}
int main() {
  DerivedDerived dd{};
  ausgabe(dd);   // Ausgabe: 0000
  dd.method();   // setzt data_ auf 1
  ausgabe(dd);   // Ausgabe: 1111
}

Okt 23, 2024

lst-0502-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fdh4n5x84 
struct Buch {
   auto getTitel() { return Titel{"Das C++ Handbuch"s}; }
   auto getAutor() { return Autor{"Torsten T. Will"s}; }
   auto umblaettern() { return /* Referenz zur nächsten Seite */ 42; }
   auto getSeite() { return "aktueller Seiteninhalt"; }
   auto getStandort() { return /* Regalnummer/Buchnummer */ 73; }
};

Okt 23, 2024

lst-0484-book.cpp

// https://godbolt.org/z/M7TTvaPxx 
// Parameter müssen gültige Werte der jeweiligen Einheit sein.
#include <iostream> // ostream
#include <iomanip>  // setw, setfill
#include <format>
using std::ostream; using std::format;
class Clock {
protected:
    int h_, m_, s_;
public:
    Clock(int hours, int minutes, int seconds)
    : h_{hours}, m_{minutes}, s_{seconds} {}
    void setClock(int hours, int minutes, int seconds) {
        h_ = hours; m_ = minutes; s_ = seconds;
    }
    friend ostream& operator<<(ostream&os, const Clock& c) {
        return os << format("{:02}:{:02}:{:02}", c.h_, c.m_, c.s_);
    }
    void tick() { // +1 Sekunde
        if(s_ >= 59) {
            s_ = 0;
            if(m_ >= 59) {
                m_ = 0;
                if(h_ >= 23) h_ = 0;
                else { h_ += 1; }
            } else { m_ += 1; }
        } else { s_ += 1; }
    }
};

Okt 23, 2024

lst-0501-book.cpp

// https://godbolt.org/z/scqTWvhsv 
class Auto { };
  class VwBulli : public Auto { };
  class Ente : public Auto { };
void lassFahren(Auto wagen) { }   //             (ERR)  Wertparameter kopiert nur Basisklasse
void lassBremsen(Auto &wagen) { } // Referenzparameter
void lassHupen(Auto *wagen) { }   // Übergabe als Zeiger
int main() {
    VwBulli bulli{  };            // automatische Variable
    Auto *ente = new Ente{  };    // dynamisch verwaltet
    lassFahren(bulli);            //             (ERR)  wird zum Auto kopiert
    lassFahren(*ente);            //             (ERR)  wird zum Auto kopiert
    lassBremsen(bulli);           // bleibt VwBulli
    lassBremsen(*ente);           // bleibt Ente
    lassHupen(&bulli);            // bleibt VwBulli
    lassHupen(ente);              // bleibt Ente
}

Okt 23, 2024

lst-0483-book.cpp

// https://godbolt.org/z/MPaYW1v5j 
#include <iostream>
using std::cout;
class Saeugetier {
public:
    void gebaere() { cout << "Geburt!\n"; }
};
class Fliegend {
public:
    void fliege() { cout << "Flug!\n"; }
};
class Fledermaus: public Saeugetier, public Fliegend {
public:
    void rufe() { cout << "Ultraschall!\n"; }
};
int main() {
    Fledermaus bruce{};
    bruce.gebaere();       // Ausgabe: Geburt!
    bruce.fliege();        // Ausgabe: Flug!
    bruce.rufe();          // Ausgabe: Ultraschall!
}

Okt 23, 2024

lst-0484-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M7TTvaPxx 
// Parameter müssen gültige Werte der jeweiligen Einheit sein.
#include <iostream> // ostream
#include <iomanip>  // setw, setfill
#include <format>
using std::ostream; using std::format;
class Clock {
protected:
    int h_, m_, s_;
public:
    Clock(int hours, int minutes, int seconds)
    : h_{hours}, m_{minutes}, s_{seconds} {}
    void setClock(int hours, int minutes, int seconds) {
        h_ = hours; m_ = minutes; s_ = seconds;
    }
    friend ostream& operator<<(ostream&os, const Clock& c) {
        return os << format("{:02}:{:02}:{:02}", c.h_, c.m_, c.s_);
    }
    void tick() { // +1 Sekunde
        if(s_ >= 59) {
            s_ = 0;
            if(m_ >= 59) {
                m_ = 0;
                if(h_ >= 23) h_ = 0;
                else { h_ += 1; }
            } else { m_ += 1; }
        } else { s_ += 1; }
    }
};

Okt 23, 2024

lst-0488-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rh179GW3j 
class CalendarClock : public Clock, public Calendar {
public:
    CalendarClock(int y, int m, int d, int hh, int mm, int ss)
    : Calendar{y,m,d}, Clock{hh,mm,ss} {}
    void tick() {         // +1 Sekunde
        auto prev_h = h_;
        Clock::tick();    // Aufruf Basisklassenmethode
        if(h_ < prev_h) { // falls neuer Tag
            advance();    //  Kalender fortschreiten
        }
    }
    friend ostream& operator<<(ostream&os, const CalendarClock& cc) {
        operator<<(os, (Calendar&)cc) << " "; // Aufruf freie Funktion
        operator<<(os, (Clock&)cc);           // Aufruf freie Funktion
        return os;
    }
};

Okt 23, 2024

lst-0486-book.cpp

// https://godbolt.org/z/oe1hT9McG 
//  includes und usings 
struct Calendar {
    int y_, m_, d_;
    static const std::vector<int> mlens_;
    bool leapyear() const {
        if(y_ % 4 != 0) return false;
        if(y_ % 100 != 0) return true;
        if(y_ % 400 != 0) return false;
        return true;
    }
public:
    Calendar(int year, int month, int day)
    : y_{year}, m_{month}, d_{day} {}
    void setCalendar(int year, int month, int day) {
        y_ = year; m_ = month; d_ = day;
    }
    friend ostream& operator<<(ostream& os, const Calendar& c) {
        return os << format("{:04}-{:02}-{:02}", c.y_, c.m_, c.d_);
    }
    void advance() { // +1 day
        auto maxd = mlens_[m_-1]; // 0-basierter vector
        if(m_==2 && leapyear())
            maxd += 1;            // Februar im Schaltjahr
        if(d_ >= maxd) {
            d_ = 1;
            if(m_ >= 12) { m_ = 1; y_ += 1; }
            else { m_ += 1; }
        } else { d_ += 1; }
    }
};
const std::vector<int> Calendar::mlens_ = {31,28,31,30,31,30,31,31,30,31,30,31};

Okt 23, 2024

lst-0478-book.cpp

// https://godbolt.org/z/8jGWTqh9z 
class Auto {
public:
  Auto() : motor_{8} { }           // initialisiert ein Auto mit 8 Zylindern
  void start() { motor_.start(); } // startet Auto durch Starten des Motors
private:
  Motor motor_;                    // Auto hat-einen Motor
};

Okt 23, 2024

lst-0485-book.cpp

// https://godbolt.org/z/a5WxqjxEr 
int main() {
    Clock clock{ 23, 59, 59 };
    std::cout << clock << '\n'; // Ausgabe: 23:59:59
    clock.tick();
    std::cout << clock << '\n'; // Ausgabe: 00:00:00
}

Okt 23, 2024

lst-0498-book.cpp

// https://godbolt.org/z/Kvfx9Yeox 
#include <array>
class Value {
    int val_;
public:
    constexpr Value(int val) : val_{val} {};
    constexpr int get() const { return val_; }
};

constexpr Value fuenf{5}; // geht, Value ist literaler Datentyp

std::array<int,fuenf.get()> data; // geht, get ist constexpr

Okt 23, 2024

lst-0481-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/G1q964f1M 
#include <iostream>           // cout
#include <memory>             // unique_ptr
using std::cout;
class Driver {                // abstrakte Basisklasse
public:
    virtual void init() = 0;
    virtual void done() = 0;
    virtual void send(const std::string &data) = 0;
};
class ProductionDriver : public Driver {
public:
    void init() override { }
    void done() override { }
    void send(const std::string &data) override { cout << data << "\n"; }
};
class DebuggingDriver : public Driver {
   size_t countSend_ = 0;
public:
    void init() override {
        countSend_= 0; cout << "Ok, bin initialisiert.\n";
    }
    void done() override {
        cout << "send benutzt:" << countSend_ << " mal\n";
    }
    void send(const std::string &data) override {
        cout << "send("<<countSend_<<"):"<< data << "\n";
        ++countSend_;
    }
};
struct DriverWrapper {        // RAII-Wrapper für init() und done()
    Driver &driver_;
    explicit DriverWrapper(Driver& driver) : driver_(driver) { driver_.init(); }
    ~DriverWrapper() { driver_.done(); }
    DriverWrapper(const DriverWrapper&) = delete; // nicht kopieren
};

void doWork(Driver &driver) { // jemand, der flexibel einen beliebigen Driver nutzt
    DriverWrapper wrapper(driver);      // init() und done() aufrufen
    driver.send("Eine unerwartete Reise");
    driver.send("Smaugs Einoede");
}

int main() {
    // gleiche doWork, einmal mit Produktions- und einmal mit Debugging-Treiber
    ProductionDriver production{};
    doWork( production );
    DebuggingDriver debugging{};
    doWork( debugging );

    // üblichere Variante eines dynamisch erzeugten Treibers
    std::unique_ptr<Driver> driver{ new ProductionDriver{} };
    doWork( *driver );
}

Okt 23, 2024

lst-0475-book.cpp

// https://godbolt.org/z/xKEo38c4n 
#include <iostream>
using std::cout; using std::ostream;
// … wie zuvor …
struct Normalfall : public DerivedPublic {
    void drucke() {
        cout << xPublic;
        cout << xProtected;
    }
};
struct Spezialfall : public DerivedPrivate {
    void drucke() {
        cout << xPublic;                  //                 (ERR)  kein Zugriff
        cout << xProtected;               //                 (ERR)  kein Zugriff
    }
};
int main() {
    Normalfall n {};
    n.drucke(); // Ausgabe: 12
    Spezialfall s {};
    s.drucke();
}

Okt 23, 2024

lst-0499-book.cpp

// https://godbolt.org/z/r1vYc7r5j 
#include <array>
#include <iostream>
#include <type_traits> // is_literal_type
class Value {
    int val_;
public:
    constexpr Value(int val) : val_{val} {};
    constexpr operator int() const { return val_; }
};
namespace lit {
    constexpr Value operator"" _val(const char*, size_t sz) { 
      return Value(sz); }
}
struct Nope {
    constexpr Nope() {};
    virtual ~Nope() {};                // nicht trivialer Destruktor
};
int main() {
    using namespace lit;
    constexpr Value fuenf{5};
    std::array<int,"11111"_val> data;  // benutzerdefiniertes Literal verwenden
    std::cout << data.size() << '\n';                        // Ausgabe: 5
    std::cout << std::boolalpha;
    std::cout << std::is_literal_type<Value>::value << '\n'; // Ausgabe: true
    std::cout << std::is_literal_type<Nope>::value << '\n';  // Ausgabe: false
}

Okt 23, 2024

lst-0480-book.cpp

// https://godbolt.org/z/7xf6sxPqG 
#include <iostream>
using std::cout;
struct KeyboardDriver : public Driver {
    void init() override { cout << "Init Keyboard\n"; }
    void done() override { cout << "Done Keyboard\n"; }
    bool send(const char* data, unsigned int len) override {
        cout << "sending " << len << " bytes\n";
        return true;
    }
};
struct Computer {
    Driver &driver_;
    explicit Computer(Driver &driver) : driver_{driver} {
        driver_.init();
    }
    void run() {
        driver_.send("Hello", 5);
    }
    ~Computer() {
        driver_.done();
    }
    Computer(const Computer&) = delete;
};
int main() {
    KeyboardDriver keyboard {};
    Computer computer(keyboard); // Ausgabe: Init Keyboard
    computer.run();              // Ausgabe: sending 5 bytes
}                                // Ausgabe: Done Keyboard

Okt 23, 2024

lst-0433-book.cpp

// https://godbolt.org/z/MT3MPs3rE 
#include <vector>
class Image {
    std::vector<std::byte> data_;
public:
    explicit Image(const char *fn) { /*...*/ }
    // Compiler generiert (u. a.): 
    // Kopierkonstruktor, Zuweisung, aber auch Verschiebungen
};
std::vector<Image> loadCollection(bool empty) {
    if(empty) return std::vector<Image>{};
    std::vector<Image> result {};                // für Rückgabe; zunächst leer
    // drei Bilder in die Sammlung  kopieren?
    result.push_back( Image{"MonaLisa.png"} );
    result.push_back( Image{"DerSchrei.png"} );
    result.push_back( Image{"JungeMitPfeife.png"} );
    return result; // Sammlung als Wert zurückgeben
}
int main() {
    // Rückgabe in Variable speichern
    std::vector<Image> sammlung = loadCollection(false);
}

Okt 23, 2024

lst-0471-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dTnxobz6v 
#include <memory> // unique_ptr
#include <string>
using std::unique_ptr; using std::cout;
template <typename K, typename D> class Tree; // Vorwärtsdeklaration
template <typename K, typename D>
class Node {
    friend class Tree<K,D>; // Zugriff auf Privates erlauben
    K key;
    D data;
    unique_ptr<Node> left, right;
public:
    Node(const K& k, const D& d) : key(k), data(d) { }
};
template <typename K, typename D>
class Tree {
public:
    void insert(const K &key, const D& data);
    D* find(const K &key) { return findRec(key, root); }
private:
    D* findRec(const K &key, unique_ptr<Node<K,D>> &wo);
    unique_ptr<Node<K,D>> root;
};
template <typename K, typename D>
void Tree<K,D>::insert(const K& key, const D& data) {
    auto *current = &root;
    while(*current) { // solange unique_ptr was enthält
        auto &node = *(current->get());
        if (key < node.key) {
            current = &node.left;
        } else if (node.key < key) {
            current = &node.right;
        }
    }
    *current = std::make_unique<Node<K,D>>(key,data);
};
template <typename K, typename D>
D* Tree<K,D>::findRec(const K& key, unique_ptr<Node<K,D>> &wo) {
    if(!wo)
        return nullptr;
    auto &node = *(wo.get());
    if(key < node.key)
        return findRec(key, node.left);
    if(node.key < key)
        return findRec(key, node.right);
    return &node.data; // key == node.key
};
int main() {
    Tree<int,std::string> bt {};
    bt.insert(3, "drei");
    bt.insert(2, "zwei");
    bt.insert(4, "vier");
    auto wo = bt.find(7);
    if(wo==nullptr) cout<<"keine 7\n"; // Ausgabe: keine 7
    wo = bt.find(3);
    if(wo!=nullptr) cout<<*wo<<"\n";   // Ausgabe: drei
}

Okt 23, 2024

lst-0457-book.cpp

// https://godbolt.org/z/esevnfEM3 
enum class Wochentag {
    MO=1, DI, MI, DO, FR, SA, SO         // DI wird 2, MI wird 3 etc.
};
enum class Level {
   TRACE=1, DEBUG, INFO=10, ERROR, FATAL // auch mit Lücken möglich
};
void log(Level level) {
   int intLevel = (int)level;            // explizit in einen int umwandeln
   if(intLevel > 10) { /* ... */ }
}

Okt 23, 2024

lst-0441-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Wvr3aK75G 
#include <compare>              // für <=>
class Value {
    // Wenn Sie class verwenden, geht es mit Privatem los.
    int value_; 
public:
    explicit Value(int value) : value_{value} {}

    // freie Funktionen, aber als friend deklariert
    friend Value operator+(const Value& li, const Value& re);
    friend Value operator-(const Value& li, const Value& re)
        { return Value{li.value_ - re.value_};  // innerhalb auch definiert
    }
    // operator<=> braucht nicht friend zu sein.
    // für alle Vergleiche: <, >, <=, >= sowie == und !=
    auto operator<=>(const Value& re) const = default; 
};

// Definition der zuvor deklarierten friend-Funktion:
Value operator+(const Value& li, const Value& re) {
    return Value{li.value_ + re.value_}; // Zugriff auf Privates erlaubt
}

int main() {
    Value sieben{7}; Value drei{3}; Value zwei{2};
    if((drei+zwei) < sieben) {    // operator+, dann operarator< via <=>
        return 0;                 // okay
    } else {
        return 1;                 // etwas ist falsch gelaufen
    }
}

Okt 23, 2024

lst-0449-book.cpp

// https://godbolt.org/z/f458s99Ga 
#include <string>
#include <iostream>
using std::string; using std::ostream;
class Shape {
    string color_;
public:
    virtual double calcArea() const = 0; // pur virtuelle Methode
    string getColor() const { return color_; }
    void setColor(const string& color) { color_ = color; }
    virtual ~Shape() {}
};
class Square : public Shape {
    double len_;
public:
    explicit Square(double len) : len_{len} {}
    double calcArea() const override { return len_*len_; }
};
class Circle : public Shape {
    double rad_;
public:
    explicit Circle(double rad) : rad_{rad} {}
    double calcArea() const override { return 3.1415*rad_*rad_; }
};
struct Calculator {
    Shape& shape_;
    Calculator(Shape& shape) : shape_{shape} { }
    void run(ostream& os) const {
        os << "The area of the shape is " << shape_.calcArea() << "\n";
    }
};
int main() {
    Square quadrat {5.0};
    Calculator ti { quadrat };
    ti.run(std::cout); // Ausgabe: The area of the shape is 25
}

Okt 23, 2024

lst-0459-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xMbG771En 
#include <vector>
#include <memory>           // unique_ptr, shared_ptr
struct Typ1 {               // automatische komplette Kopie der Ressource
    std::vector<char> data_;
    Typ1(int n) : data_(n) {}
};
struct Typ2 {               // Kopie untersagt, Verschieben möglich
    std::unique_ptr<int[]> data_;
    Typ2(int n) : data_(new int[n]) {}
};
struct Typ3 {               // Kopie erlaubt, Ressource wird dann sauber geteilt
    std::shared_ptr<Typ1> data_;
    Typ3(int n) : data_(std::make_shared<Typ1>(n)) {}
};

Okt 23, 2024

lst-0458-book.cpp

// https://godbolt.org/z/1Ke5W5Pj5 
struct Typ {
    char* data_;            // roher Zeiger kann für unklare Besitzverhältnisse sorgen
    Typ(int n) : data_(new char[n]) {}
    ~Typ() { delete[] data_; }           // den Destruktor benötigen Sie

    Typ(const Typ&) = delete;            // keine Kopie zulassen
    Typ& operator=(const Typ&) = delete; // keine Zuweisung bitte
    Typ(Typ&&) = delete;                 // kein Verschieben
    Typ& operator=(Typ&&) = delete;      // kein Verschiebeoperator
};

Okt 23, 2024

lst-0449-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/f458s99Ga 
#include <string>
#include <iostream>
using std::string; using std::ostream;
class Shape {
    string color_;
public:
    virtual double calcArea() const = 0; // pur virtuelle Methode
    string getColor() const { return color_; }
    void setColor(const string& color) { color_ = color; }
    virtual ~Shape() {}
};
class Square : public Shape {
    double len_;
public:
    explicit Square(double len) : len_{len} {}
    double calcArea() const override { return len_*len_; }
};
class Circle : public Shape {
    double rad_;
public:
    explicit Circle(double rad) : rad_{rad} {}
    double calcArea() const override { return 3.1415*rad_*rad_; }
};
struct Calculator {
    Shape& shape_;
    Calculator(Shape& shape) : shape_{shape} { }
    void run(ostream& os) const {
        os << "The area of the shape is " << shape_.calcArea() << "\n";
    }
};
int main() {
    Square quadrat {5.0};
    Calculator ti { quadrat };
    ti.run(std::cout); // Ausgabe: The area of the shape is 25
}

Okt 23, 2024

lst-0470-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WqfMGaP71 
#include <iostream>
class Schrauber;
class Ding {
    int value_; // privat
public:
    explicit Ding(int value) : value_{value} {}
    void inc() { ++value_; }
    std::ostream& print(std::ostream& os) const { return os<<value_; }
    friend class Schrauber;
};
class Schrauber {
    const Ding &ding_;
public:
    explicit Schrauber(const Ding &ding) : ding_{ding} {}
    auto dingWert() const {
        return ding_.value_;                   // Zugriff auf Privates aus Ding
    }
};
int main() {
    Ding ding{45};
    ding.print(std::cout) << '\n';             // Ausgabe: 45
    Schrauber schrauber{ding};
    ding.inc(); // internen Wert verändern
    std::cout << schrauber.dingWert() << '\n'; // Ausgabe: 46
}

Okt 23, 2024

lst-0459-book.cpp

// https://godbolt.org/z/xMbG771En 
#include <vector>
#include <memory>           // unique_ptr, shared_ptr
struct Typ1 {               // automatische komplette Kopie der Ressource
    std::vector<char> data_;
    Typ1(int n) : data_(n) {}
};
struct Typ2 {               // Kopie untersagt, Verschieben möglich
    std::unique_ptr<int[]> data_;
    Typ2(int n) : data_(new int[n]) {}
};
struct Typ3 {               // Kopie erlaubt, Ressource wird dann sauber geteilt
    std::shared_ptr<Typ1> data_;
    Typ3(int n) : data_(std::make_shared<Typ1>(n)) {}
};

Okt 23, 2024

lst-0434-book.cpp

// https://godbolt.org/z/6xjeYWe7c 
#include <vector>
class Image {
    std::vector<std::byte> data_;              // byte gibt es seit C++17
public:
    explicit Image(const char *fn) { /*...*/ }
    Image(Image&& other) noexcept              // Verschiebekonstruktor
        : data_{} // leer erzeugen
    {
        using std::swap;
        swap(data_, other.data_);
    }
    Image& operator=(Image&& other) noexcept { // Verschiebeoperator
        using std::swap;
        swap(data_, other.data_);
        return *this;
    }
};

Okt 23, 2024

lst-0454-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xhd7s1YhE 
#include <string>
using std::string;
enum class Ampelfarbe {
    ROT, GELB, ROTGELB, GRUEN
};
struct Ampel {
    Ampelfarbe farbe_;
    Ampel(Ampelfarbe farbe, string name) : farbe_{farbe} {}
};

Ampel erzeugeAmpel(Ampelfarbe farbe, string ampelName) {
    return Ampel{farbe, ampelName};
}

int main() {
    Ampel ampel = erzeugeAmpel(Ampelfarbe::ROT, "AX-001");
}

Okt 23, 2024

lst-0446-book.cpp

// https://godbolt.org/z/KxWb4q8q9 
#include <compare>  // partial_ordering etc
#include <set>
#include <iostream>
using namespace std;
struct Bruch {
  int z, n;  // zaehler / nenner
  partial_ordering operator<=>(const Bruch& re) const {
    if(n==0 || re.n==0) return partial_ordering::unordered;
    return (double)z / n <=> (double)re.z / re.n;
  }
};
int main() {
  set<Bruch> brueche{ {1,2}, {2,4}, {1,3}, {2,3}, {1,4}, {2,5}, {3,8}, {99,0} };
  for(auto b : brueche)
    cout << b.z << "/" << b.n << " ";
  cout << "\n"; // Ausgabe: 1/4 1/3 3/8 2/5 1/2 2/3
}

Okt 23, 2024

lst-0474-book.cpp

// https://godbolt.org/z/Pxqrjjqs8 
#include <iostream>
using std::cout; using std::ostream;
// … wie zuvor …
int main() {
    // öffentlich erben
    DerivedPublic dpu{};
    cout << dpu.xPublic << '\n';    // Ausgabe: 1
    cout << dpu.xProtected << '\n'; // kein Zugriff von außen
    // geschützt erben
    DerivedProtected dpt{};
    cout << dpt.xPublic << '\n';    // kein Zugriff von außen
    cout << dpt.xProtected << '\n'; // kein Zugriff von außen
    // private erben
    DerivedPrivate dpv{};
    cout << dpv.xPublic << '\n';    // kein Zugriff von außen
    cout << dpv.xProtected << '\n'; // kein Zugriff von außen
}

Okt 23, 2024

lst-0464-book.cpp

// https://godbolt.org/z/TK3vTv1EM 
struct StereoImage {
  Image *left, *right;
  StereoImage()
  : left(new Image)
  , right(new Image) // Gefahr!
  { }
  ~StereoImage() {
      delete left;
      delete right;
  }
};

Okt 23, 2024

lst-0460-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xcqon7dM 
struct Base {
    virtual ~Base() {}; // definieren Sie den Destruktor, machen Sie ihn virtual
    virtual void other();
};

struct Derived : public Base {
    void other() override;
};

int main() {
    Base *obj = new Derived{};
    /* ... mehr Programmzeilen hier ... */
    delete obj;     // klappt, weil Base::~Base virtual ist
}

Okt 23, 2024

lst-0473-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eKbK39nG1 
class Base {
public:
    int xPublic = 1;
protected:
    int xProtected = 2;
private:
    int xPrivate = 3;
};
class DerivedPublic : public Base {
    // xPublic wird 'public'
    // xProtected wird 'protected'
    // xPrivate ist hier nicht sichtbar
};
class DerivedProtected : protected Base {
    // xPublic wird 'protected'
    // xProtected wird 'protected'
    // xPrivate ist hier nicht sichtbar
};
class DerivedPrivate : private Base { // oder wenn nichts angegeben
    // xPublic wird 'private'
    // xProtected wird 'private'
    // xPrivate ist hier nicht sichtbar
};

Okt 23, 2024

lst-0469-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s8KoE4ETs 
#include <new> // nothrow
std::string *ps = new(std::nothrow) std::string{};
if(ps == nullptr) {
   std::cerr << "Die Speicheranforderung ging schief\n";
   return SOME_ERROR;
}

Okt 23, 2024

lst-0440-book.cpp

// https://godbolt.org/z/fefP5d343 
#include <iostream>
using std::cout; using std::ostream;
struct Widget {
    bool operator<(const Widget&) const {      // Methodenschreibweise
        return true;                           // immer true
    }
};
bool operator<(const Widget&, const Widget&) { // Funktionsschreibweise
    return false;                              // immer false
}
int main() {
    Widget x{};
    Widget y{};
    cout << (operator<(x, y)      // ruft Funktionsschreibweise auf
        ? "Methode1\n" : "Funktion1\n");
    cout << (y.operator<(x)       // ruft Methodenschreibweise auf
        ? "Methode2\n" : "Funktion2\n");
    cout << (x < y                // Infix-Schreibweise, lässt die Wahl, hier Methode
        ? "Methode3\n" : "Funktion3\n");
}

Okt 23, 2024

lst-0465-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cs4eEEGrf 
#include <memory> // unique_ptr
struct Image {
    /* ... */
};
struct StereoImage {
  std::unique_ptr<Image> left, right;
  StereoImage()
  : left(new Image)
  , right(new Image)
  { }
};

Okt 23, 2024

lst-0460-book.cpp

// https://godbolt.org/z/1xcqon7dM 
struct Base {
    virtual ~Base() {}; // definieren Sie den Destruktor, machen Sie ihn virtual
    virtual void other();
};

struct Derived : public Base {
    void other() override;
};

int main() {
    Base *obj = new Derived{};
    /* ... mehr Programmzeilen hier ... */
    delete obj;     // klappt, weil Base::~Base virtual ist
}

Okt 23, 2024

lst-0468-book.cpp

// https://godbolt.org/z/5bW9Evorc 
#include <string>
#include <sqlite3.h>
class DbWrapper {
  sqlite3 *db_;
public:
  DbWrapper(const std::string& dbname)
    : db_{nullptr}
  {
    const int errCode = sqlite3_open(dbname.c_str(), &db_);
    if(errCode) db_ = nullptr;  // als 'nicht erfolgreich' markieren
  }
  explicit operator bool() const {
    return db_ != nullptr;      // Markierung auswerten
  }
  ~DbWrapper() {
    if(db_) sqlite3_close(db_);
  }
  // ... Rest wie zuvor ...
};
bool dbExec(const std::string &dbname, const std::string &sql) {
  DbWrapper db { dbname };
  if(db) {                 // prüfe auf erfolgreiche Initialisierung
    const int errCode = sqlite3_exec(*db,sql.c_str(),nullptr,nullptr,nullptr);
    if(errCode)
      return false; // immer noch korrektes RAII
  }
  return (bool)db;
}

Okt 23, 2024

lst-0470-book.cpp

// https://godbolt.org/z/WqfMGaP71 
#include <iostream>
class Schrauber;
class Ding {
    int value_; // privat
public:
    explicit Ding(int value) : value_{value} {}
    void inc() { ++value_; }
    std::ostream& print(std::ostream& os) const { return os<<value_; }
    friend class Schrauber;
};
class Schrauber {
    const Ding &ding_;
public:
    explicit Schrauber(const Ding &ding) : ding_{ding} {}
    auto dingWert() const {
        return ding_.value_;                   // Zugriff auf Privates aus Ding
    }
};
int main() {
    Ding ding{45};
    ding.print(std::cout) << '\n';             // Ausgabe: 45
    Schrauber schrauber{ding};
    ding.inc(); // internen Wert verändern
    std::cout << schrauber.dingWert() << '\n'; // Ausgabe: 46
}

Okt 23, 2024

lst-0458-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1Ke5W5Pj5 
struct Typ {
    char* data_;            // roher Zeiger kann für unklare Besitzverhältnisse sorgen
    Typ(int n) : data_(new char[n]) {}
    ~Typ() { delete[] data_; }           // den Destruktor benötigen Sie

    Typ(const Typ&) = delete;            // keine Kopie zulassen
    Typ& operator=(const Typ&) = delete; // keine Zuweisung bitte
    Typ(Typ&&) = delete;                 // kein Verschieben
    Typ& operator=(Typ&&) = delete;      // kein Verschiebeoperator
};

Okt 23, 2024

lst-0433-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MT3MPs3rE 
#include <vector>
class Image {
    std::vector<std::byte> data_;
public:
    explicit Image(const char *fn) { /*...*/ }
    // Compiler generiert (u. a.): 
    // Kopierkonstruktor, Zuweisung, aber auch Verschiebungen
};
std::vector<Image> loadCollection(bool empty) {
    if(empty) return std::vector<Image>{};
    std::vector<Image> result {};                // für Rückgabe; zunächst leer
    // drei Bilder in die Sammlung  kopieren?
    result.push_back( Image{"MonaLisa.png"} );
    result.push_back( Image{"DerSchrei.png"} );
    result.push_back( Image{"JungeMitPfeife.png"} );
    return result; // Sammlung als Wert zurückgeben
}
int main() {
    // Rückgabe in Variable speichern
    std::vector<Image> sammlung = loadCollection(false);
}

Okt 23, 2024

lst-0441-book.cpp

// https://godbolt.org/z/Wvr3aK75G 
#include <compare>              // für <=>
class Value {
    // Wenn Sie class verwenden, geht es mit Privatem los.
    int value_; 
public:
    explicit Value(int value) : value_{value} {}

    // freie Funktionen, aber als friend deklariert
    friend Value operator+(const Value& li, const Value& re);
    friend Value operator-(const Value& li, const Value& re)
        { return Value{li.value_ - re.value_};  // innerhalb auch definiert
    }
    // operator<=> braucht nicht friend zu sein.
    // für alle Vergleiche: <, >, <=, >= sowie == und !=
    auto operator<=>(const Value& re) const = default; 
};

// Definition der zuvor deklarierten friend-Funktion:
Value operator+(const Value& li, const Value& re) {
    return Value{li.value_ + re.value_}; // Zugriff auf Privates erlaubt
}

int main() {
    Value sieben{7}; Value drei{3}; Value zwei{2};
    if((drei+zwei) < sieben) {    // operator+, dann operarator< via <=>
        return 0;                 // okay
    } else {
        return 1;                 // etwas ist falsch gelaufen
    }
}

Okt 23, 2024

lst-0454-book.cpp

// https://godbolt.org/z/xhd7s1YhE 
#include <string>
using std::string;
enum class Ampelfarbe {
    ROT, GELB, ROTGELB, GRUEN
};
struct Ampel {
    Ampelfarbe farbe_;
    Ampel(Ampelfarbe farbe, string name) : farbe_{farbe} {}
};

Ampel erzeugeAmpel(Ampelfarbe farbe, string ampelName) {
    return Ampel{farbe, ampelName};
}

int main() {
    Ampel ampel = erzeugeAmpel(Ampelfarbe::ROT, "AX-001");
}

Okt 23, 2024

lst-0473-book.cpp

// https://godbolt.org/z/eKbK39nG1 
class Base {
public:
    int xPublic = 1;
protected:
    int xProtected = 2;
private:
    int xPrivate = 3;
};
class DerivedPublic : public Base {
    // xPublic wird 'public'
    // xProtected wird 'protected'
    // xPrivate ist hier nicht sichtbar
};
class DerivedProtected : protected Base {
    // xPublic wird 'protected'
    // xProtected wird 'protected'
    // xPrivate ist hier nicht sichtbar
};
class DerivedPrivate : private Base { // oder wenn nichts angegeben
    // xPublic wird 'private'
    // xProtected wird 'private'
    // xPrivate ist hier nicht sichtbar
};

Okt 23, 2024

lst-0442-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gf38nTa1q 
#include <iostream>  // istream, ostream, cout
class Num {
  int val_ = 0;
public:
  int& operator*();  // Dereferenzieren: Zugriff auf den Wert direkt erhalten
  const int& operator*() const; // Dereferenzieren: Lesezugriff auf den Wert
  Num() {}
  explicit Num(int value) : val_{value} {}
  // einstellige Operatoren
  Num& operator++(); // Pre-Inkrement
  Num& operator--(); // Pre-Dekrement
  Num operator+();   // Positiv
  Num operator-();   // Negieren
  Num operator~();   // bitweises Invertieren
  // zweistellige Operatoren
  // - zusammengesetzte Zuweisungen, arithmetisch
  Num& operator+=(const Num& re) { val_ += *re; return *this; }
  Num& operator-=(const Num& re) { val_ -= *re; return *this; }
  Num& operator*=(const Num& re) { val_ *= *re; return *this; }
  Num& operator/=(const Num& re) { val_ /= *re; return *this; }
  Num& operator%=(const Num& re) { val_ %= *re; return *this; }
  // - zusammengesetzte Zuweisungen, bitweise
  Num& operator|=(const Num& re) { val_ |= *re; return *this; }
  Num& operator&=(const Num& re) { val_ &= *re; return *this; }
  Num& operator^=(const Num& re) { val_ ^= *re; return *this; }
  Num& operator<<=(int n) { val_ <<= n; return *this; }
  Num& operator>>=(int n) { val_ >>= n; return *this; }
  // - Variation zusammengesetzter Zuweisungen, für einfachere Bedienung
  Num& operator+=(int re) { val_ += re; return *this; }
  Num& operator-=(int re) { val_ -= re; return *this; }
  // zweistellige Operatoren, mit Call-by-Value für den ersten Parameter
  // und die die zusammengesetzte Zuweisung zu Hilfe nehmen
  // - Arithmetik
  friend Num operator+(Num li, const Num& re) { return li += re; }
  friend Num operator-(Num li, const Num& re) { return li -= re; }
  friend Num operator*(Num li, const Num& re) { return li *= re; }
  friend Num operator/(Num li, const Num& re) { return li /= re; }
  friend Num operator%(Num li, const Num& re) { return li %= re; }
  // - bitweise
  friend Num operator|(Num li, const Num& re) { return li |= re; }
  friend Num operator&(Num li, const Num& re) { return li &= re; }
  friend Num operator^(Num li, const Num& re) { return li ^= re; }
  // - Vergleiche
  // -  fundamental für Standardcontainer und -algorithmen
  friend bool operator==(const Num& li, const Num& re) { return *li == *re; }
  auto operator<=>(const Num& re) const {return val_ <=> *re; } // C++20
  // - Ein- und Ausgabe
  friend std::ostream& operator<<(std::ostream& os, const Num& arg);
  friend std::istream& operator>>(std::istream& is,  Num& arg);
};
// einstellige Operatoren
Num& Num::operator++() { ++val_; return *this; }
Num& Num::operator--() { --val_; return *this; }
Num Num::operator+() { return Num{val_}; }
Num Num::operator-() { return Num{-val_}; }
Num Num::operator~() { return Num{~val_}; }
int& Num::operator*() { return val_; }
const int& Num::operator*() const { return val_; }
// Ein- und Ausgabe
std::ostream& operator<<(std::ostream&os, const Num& arg) { return os<<*arg; }
std::istream& operator>>(std::istream&is, Num& arg) { return is>>*arg; }

Okt 23, 2024

lst-0468-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5bW9Evorc 
#include <string>
#include <sqlite3.h>
class DbWrapper {
  sqlite3 *db_;
public:
  DbWrapper(const std::string& dbname)
    : db_{nullptr}
  {
    const int errCode = sqlite3_open(dbname.c_str(), &db_);
    if(errCode) db_ = nullptr;  // als 'nicht erfolgreich' markieren
  }
  explicit operator bool() const {
    return db_ != nullptr;      // Markierung auswerten
  }
  ~DbWrapper() {
    if(db_) sqlite3_close(db_);
  }
  // ... Rest wie zuvor ...
};
bool dbExec(const std::string &dbname, const std::string &sql) {
  DbWrapper db { dbname };
  if(db) {                 // prüfe auf erfolgreiche Initialisierung
    const int errCode = sqlite3_exec(*db,sql.c_str(),nullptr,nullptr,nullptr);
    if(errCode)
      return false; // immer noch korrektes RAII
  }
  return (bool)db;
}

Okt 23, 2024

lst-0466-book.cpp

// https://godbolt.org/z/GK4W1nKd4 
#include <string>
#include <stdexcept>
#include <sqlite3.h>
using std::string; using std::runtime_error;

void dbExec(const string &dbname, const string &sql) {
  sqlite3 *db;
  int errCode = sqlite3_open(dbname.c_str(), &db);  // Acquire
  if(errCode) {
    throw runtime_error("Fehler beim Öffnen der DB.");
  }
  errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
  if(errCode) {
    throw runtime_error("Fehler SQL-Exec.");        //                 (ERR)  Nicht gut!
  }
  errCode = sqlite3_close(db);                      // Release
}

Okt 23, 2024

lst-0466-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GK4W1nKd4 
#include <string>
#include <stdexcept>
#include <sqlite3.h>
using std::string; using std::runtime_error;

void dbExec(const string &dbname, const string &sql) {
  sqlite3 *db;
  int errCode = sqlite3_open(dbname.c_str(), &db);  // Acquire
  if(errCode) {
    throw runtime_error("Fehler beim Öffnen der DB.");
  }
  errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
  if(errCode) {
    throw runtime_error("Fehler SQL-Exec.");        //                 (ERR)  Nicht gut!
  }
  errCode = sqlite3_close(db);                      // Release
}

Okt 23, 2024

lst-0465-book.cpp

// https://godbolt.org/z/cs4eEEGrf 
#include <memory> // unique_ptr
struct Image {
    /* ... */
};
struct StereoImage {
  std::unique_ptr<Image> left, right;
  StereoImage()
  : left(new Image)
  , right(new Image)
  { }
};

Okt 23, 2024

lst-0463-book.cpp

// https://godbolt.org/z/9eeG575Wz 
struct Puffer {
  const char *data;
  explicit Puffer(unsigned sz): data(new char[sz]) {}
  ~Puffer() { delete[] data; }
  Puffer(const Puffer&) = delete;
  Puffer& operator=(const Puffer&) = delete;
};

Okt 23, 2024

lst-0434-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6xjeYWe7c 
#include <vector>
class Image {
    std::vector<std::byte> data_;              // byte gibt es seit C++17
public:
    explicit Image(const char *fn) { /*...*/ }
    Image(Image&& other) noexcept              // Verschiebekonstruktor
        : data_{} // leer erzeugen
    {
        using std::swap;
        swap(data_, other.data_);
    }
    Image& operator=(Image&& other) noexcept { // Verschiebeoperator
        using std::swap;
        swap(data_, other.data_);
        return *this;
    }
};

Okt 23, 2024

lst-0444-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ojeh8Gzcx 
#include <iostream>               // istream, ostream, cout
class Bool {
    bool val_ = false;
    bool& operator*()             // dereferenzieren; veränderbar
        { return val_; };
    const bool& operator*() const // dereferenzieren; nur lesen
        { return val_; }
public:
    constexpr Bool() {}
    explicit constexpr Bool(bool value)
        : val_{value} {}
    // einstellige Operatoren
    Bool operator!() const        // Nicht-Operator
        { return Bool{!val_}; };
    // zweistellige Operatoren
    friend Bool operator&&(const Bool &re, const Bool &li)
        { return Bool{*re && *li}; }
    friend Bool operator||(const Bool &re, const Bool &li)
        { return Bool{*re || *li}; }
    // Ein- und Ausgabe
    friend std::ostream& operator<<(std::ostream& os, const Bool& arg);
    friend std::istream& operator>>(std::istream& is,  Bool& arg);
};
std::ostream& operator<<(std::ostream& os, const Bool& arg)
    { return os << *arg; }
std::istream& operator>>(std::istream& is, Bool& arg)
    { return is >> *arg; }
// Konstanten
static constexpr Bool False{false};
static constexpr Bool True{true};
int main() {
    Bool jein = True && ( Bool{false} || !Bool{} ); // verwendet &&, || und !
    std::cout << jein << "\n"; // Ausgabe: 1
}

Okt 23, 2024

lst-0442-book.cpp

// https://godbolt.org/z/Gf38nTa1q 
#include <iostream>  // istream, ostream, cout
class Num {
  int val_ = 0;
public:
  int& operator*();  // Dereferenzieren: Zugriff auf den Wert direkt erhalten
  const int& operator*() const; // Dereferenzieren: Lesezugriff auf den Wert
  Num() {}
  explicit Num(int value) : val_{value} {}
  // einstellige Operatoren
  Num& operator++(); // Pre-Inkrement
  Num& operator--(); // Pre-Dekrement
  Num operator+();   // Positiv
  Num operator-();   // Negieren
  Num operator~();   // bitweises Invertieren
  // zweistellige Operatoren
  // - zusammengesetzte Zuweisungen, arithmetisch
  Num& operator+=(const Num& re) { val_ += *re; return *this; }
  Num& operator-=(const Num& re) { val_ -= *re; return *this; }
  Num& operator*=(const Num& re) { val_ *= *re; return *this; }
  Num& operator/=(const Num& re) { val_ /= *re; return *this; }
  Num& operator%=(const Num& re) { val_ %= *re; return *this; }
  // - zusammengesetzte Zuweisungen, bitweise
  Num& operator|=(const Num& re) { val_ |= *re; return *this; }
  Num& operator&=(const Num& re) { val_ &= *re; return *this; }
  Num& operator^=(const Num& re) { val_ ^= *re; return *this; }
  Num& operator<<=(int n) { val_ <<= n; return *this; }
  Num& operator>>=(int n) { val_ >>= n; return *this; }
  // - Variation zusammengesetzter Zuweisungen, für einfachere Bedienung
  Num& operator+=(int re) { val_ += re; return *this; }
  Num& operator-=(int re) { val_ -= re; return *this; }
  // zweistellige Operatoren, mit Call-by-Value für den ersten Parameter
  // und die die zusammengesetzte Zuweisung zu Hilfe nehmen
  // - Arithmetik
  friend Num operator+(Num li, const Num& re) { return li += re; }
  friend Num operator-(Num li, const Num& re) { return li -= re; }
  friend Num operator*(Num li, const Num& re) { return li *= re; }
  friend Num operator/(Num li, const Num& re) { return li /= re; }
  friend Num operator%(Num li, const Num& re) { return li %= re; }
  // - bitweise
  friend Num operator|(Num li, const Num& re) { return li |= re; }
  friend Num operator&(Num li, const Num& re) { return li &= re; }
  friend Num operator^(Num li, const Num& re) { return li ^= re; }
  // - Vergleiche
  // - … fundamental für Standardcontainer und -algorithmen
  friend bool operator==(const Num& li, const Num& re) { return *li == *re; }
  auto operator<=>(const Num& re) const {return val_ <=> *re; } // C++20
  // - Ein- und Ausgabe
  friend std::ostream& operator<<(std::ostream& os, const Num& arg);
  friend std::istream& operator>>(std::istream& is,  Num& arg);
};
// einstellige Operatoren
Num& Num::operator++() { ++val_; return *this; }
Num& Num::operator--() { --val_; return *this; }
Num Num::operator+() { return Num{val_}; }
Num Num::operator-() { return Num{-val_}; }
Num Num::operator~() { return Num{~val_}; }
int& Num::operator*() { return val_; }
const int& Num::operator*() const { return val_; }
// Ein- und Ausgabe
std::ostream& operator<<(std::ostream&os, const Num& arg) { return os<<*arg; }
std::istream& operator>>(std::istream&is, Num& arg) { return is>>*arg; }

Okt 23, 2024

lst-0464-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TK3vTv1EM 
struct StereoImage {
  Image *left, *right;
  StereoImage()
  : left(new Image)
  , right(new Image) // Gefahr!
  { }
  ~StereoImage() {
      delete left;
      delete right;
  }
};

Okt 23, 2024

lst-0440-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fefP5d343 
#include <iostream>
using std::cout; using std::ostream;
struct Widget {
    bool operator<(const Widget&) const {      // Methodenschreibweise
        return true;                           // immer true
    }
};
bool operator<(const Widget&, const Widget&) { // Funktionsschreibweise
    return false;                              // immer false
}
int main() {
    Widget x{};
    Widget y{};
    cout << (operator<(x, y)      // ruft Funktionsschreibweise auf
        ? "Methode1\n" : "Funktion1\n");
    cout << (y.operator<(x)       // ruft Methodenschreibweise auf
        ? "Methode2\n" : "Funktion2\n");
    cout << (x < y                // Infix-Schreibweise, lässt die Wahl, hier Methode
        ? "Methode3\n" : "Funktion3\n");
}

Okt 23, 2024

lst-0463-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9eeG575Wz 
struct Puffer {
  const char *data;
  explicit Puffer(unsigned sz): data(new char[sz]) {}
  ~Puffer() { delete[] data; }
  Puffer(const Puffer&) = delete;
  Puffer& operator=(const Puffer&) = delete;
};

Okt 23, 2024

lst-0469-book.cpp

// https://godbolt.org/z/s8KoE4ETs 
#include <new> // nothrow
std::string *ps = new(std::nothrow) std::string{};
if(ps == nullptr) {
   std::cerr << "Die Speicheranforderung ging schief\n";
   return SOME_ERROR;
}

Okt 23, 2024

lst-0471-book.cpp

// https://godbolt.org/z/dTnxobz6v 
#include <memory> // unique_ptr
#include <string>
using std::unique_ptr; using std::cout;
template <typename K, typename D> class Tree; // Vorwärtsdeklaration
template <typename K, typename D>
class Node {
    friend class Tree<K,D>; // Zugriff auf Privates erlauben
    K key;
    D data;
    unique_ptr<Node> left, right;
public:
    Node(const K& k, const D& d) : key(k), data(d) { }
};
template <typename K, typename D>
class Tree {
public:
    void insert(const K &key, const D& data);
    D* find(const K &key) { return findRec(key, root); }
private:
    D* findRec(const K &key, unique_ptr<Node<K,D>> &wo);
    unique_ptr<Node<K,D>> root;
};
template <typename K, typename D>
void Tree<K,D>::insert(const K& key, const D& data) {
    auto *current = &root;
    while(*current) { // solange unique_ptr was enthält
        auto &node = *(current->get());
        if (key < node.key) {
            current = &node.left;
        } else if (node.key < key) {
            current = &node.right;
        }
    }
    *current = std::make_unique<Node<K,D>>(key,data);
};
template <typename K, typename D>
D* Tree<K,D>::findRec(const K& key, unique_ptr<Node<K,D>> &wo) {
    if(!wo)
        return nullptr;
    auto &node = *(wo.get());
    if(key < node.key)
        return findRec(key, node.left);
    if(node.key < key)
        return findRec(key, node.right);
    return &node.data; // key == node.key
};
int main() {
    Tree<int,std::string> bt {};
    bt.insert(3, "drei");
    bt.insert(2, "zwei");
    bt.insert(4, "vier");
    auto wo = bt.find(7);
    if(wo==nullptr) cout<<"keine 7\n"; // Ausgabe: keine 7
    wo = bt.find(3);
    if(wo!=nullptr) cout<<*wo<<"\n";   // Ausgabe: drei
}

Okt 23, 2024

lst-0474-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Pxqrjjqs8 
#include <iostream>
using std::cout; using std::ostream;
//  wie zuvor 
int main() {
    // öffentlich erben
    DerivedPublic dpu{};
    cout << dpu.xPublic << '\n';    // Ausgabe: 1
    cout << dpu.xProtected << '\n'; // kein Zugriff von außen
    // geschützt erben
    DerivedProtected dpt{};
    cout << dpt.xPublic << '\n';    // kein Zugriff von außen
    cout << dpt.xProtected << '\n'; // kein Zugriff von außen
    // private erben
    DerivedPrivate dpv{};
    cout << dpv.xPublic << '\n';    // kein Zugriff von außen
    cout << dpv.xProtected << '\n'; // kein Zugriff von außen
}

Okt 23, 2024

lst-0444-book.cpp

// https://godbolt.org/z/ojeh8Gzcx 
#include <iostream>               // istream, ostream, cout
class Bool {
    bool val_ = false;
    bool& operator*()             // dereferenzieren; veränderbar
        { return val_; };
    const bool& operator*() const // dereferenzieren; nur lesen
        { return val_; }
public:
    constexpr Bool() {}
    explicit constexpr Bool(bool value)
        : val_{value} {}
    // einstellige Operatoren
    Bool operator!() const        // Nicht-Operator
        { return Bool{!val_}; };
    // zweistellige Operatoren
    friend Bool operator&&(const Bool &re, const Bool &li)
        { return Bool{*re && *li}; }
    friend Bool operator||(const Bool &re, const Bool &li)
        { return Bool{*re || *li}; }
    // Ein- und Ausgabe
    friend std::ostream& operator<<(std::ostream& os, const Bool& arg);
    friend std::istream& operator>>(std::istream& is,  Bool& arg);
};
std::ostream& operator<<(std::ostream& os, const Bool& arg)
    { return os << *arg; }
std::istream& operator>>(std::istream& is, Bool& arg)
    { return is >> *arg; }
// Konstanten
static constexpr Bool False{false};
static constexpr Bool True{true};
int main() {
    Bool jein = True && ( Bool{false} || !Bool{} ); // verwendet &&, || und !
    std::cout << jein << "\n"; // Ausgabe: 1
}

Okt 23, 2024

lst-0443-book.cpp

// https://godbolt.org/z/asaYr3ox6 
#include <iostream>                      // cout
int main() {
    using std::cout;
    Num a{1};
    *a = 7;                              // operator* liefert auch int&
    a += Num{3};                         // Inkrement mit Num
    cout << ( ++( ++a ) ) << "\n";       // Ausgabe: 12
    a -= 2;                              // Variation mit int
    cout << --(--a) << "\n";             // Ausgabe: 8
    Num b{99};
    cout << (a<b ? "ja\n" : "xxx\n");    // Ausgabe: ja
    cout << (a>b ? "xxx\n" : "nein\n");  // Ausgabe: nein
    b /= Num{3};          // b: 33
    b %= Num{10};         // b: 3
    b <<= 4;              // b: 48
    b >>= 2;              // b: 12
    Num c = b / Num{3} + a * Num{2}; // c: 20
}

Okt 23, 2024

lst-0467-book.cpp

// https://godbolt.org/z/hqrPjGjnK 
#include <sqlite3.h>
class DbWrapper {
  sqlite3 *db_;
public:
  // acquire resource
  DbWrapper(const string& dbname)
    : db_{nullptr}
  {
    const int errCode = sqlite3_open(dbname.c_str(), &db_);
    if(errCode)
      throw runtime_error("Fehler beim Öffnen"); // verhindert sqlite3_close
  }

  // release resource
  ~DbWrapper() {
    sqlite3_close(db_);  // Release
  }
  // access Resource
  sqlite3* operator*() { return db_; }
  // Keine Kopie und Zuweisung
  DbWrapper(const DbWrapper&) = delete;
  DbWrapper& operator=(const DbWrapper&) = delete;
};
void dbExec(const string &dbname, const string &sql) {
  DbWrapper db { dbname };
  const int errCode = sqlite3_exec(*db, sql.c_str(), nullptr, 
    nullptr, nullptr);
  if(errCode)
    throw runtime_error("Fehler SQL-Exec."); // Jetzt geht es!
}

Okt 23, 2024

lst-0467-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hqrPjGjnK 
#include <sqlite3.h>
class DbWrapper {
  sqlite3 *db_;
public:
  // acquire resource
  DbWrapper(const string& dbname)
    : db_{nullptr}
  {
    const int errCode = sqlite3_open(dbname.c_str(), &db_);
    if(errCode)
      throw runtime_error("Fehler beim Öffnen"); // verhindert sqlite3_close
  }

  // release resource
  ~DbWrapper() {
    sqlite3_close(db_);  // Release
  }
  // access Resource
  sqlite3* operator*() { return db_; }
  // Keine Kopie und Zuweisung
  DbWrapper(const DbWrapper&) = delete;
  DbWrapper& operator=(const DbWrapper&) = delete;
};
void dbExec(const string &dbname, const string &sql) {
  DbWrapper db { dbname };
  const int errCode = sqlite3_exec(*db, sql.c_str(), nullptr, 
    nullptr, nullptr);
  if(errCode)
    throw runtime_error("Fehler SQL-Exec."); // Jetzt geht es!
}

Okt 23, 2024

lst-0457-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/esevnfEM3 
enum class Wochentag {
    MO=1, DI, MI, DO, FR, SA, SO         // DI wird 2, MI wird 3 etc.
};
enum class Level {
   TRACE=1, DEBUG, INFO=10, ERROR, FATAL // auch mit Lücken möglich
};
void log(Level level) {
   int intLevel = (int)level;            // explizit in einen int umwandeln
   if(intLevel > 10) { /* ... */ }
}

Okt 23, 2024

lst-0443-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/asaYr3ox6 
#include <iostream>                      // cout
int main() {
    using std::cout;
    Num a{1};
    *a = 7;                              // operator* liefert auch int&
    a += Num{3};                         // Inkrement mit Num
    cout << ( ++( ++a ) ) << "\n";       // Ausgabe: 12
    a -= 2;                              // Variation mit int
    cout << --(--a) << "\n";             // Ausgabe: 8
    Num b{99};
    cout << (a<b ? "ja\n" : "xxx\n");    // Ausgabe: ja
    cout << (a>b ? "xxx\n" : "nein\n");  // Ausgabe: nein
    b /= Num{3};          // b: 33
    b %= Num{10};         // b: 3
    b <<= 4;              // b: 48
    b >>= 2;              // b: 12
    Num c = b / Num{3} + a * Num{2}; // c: 20
}

Okt 23, 2024

lst-0446-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KxWb4q8q9 
#include <compare>  // partial_ordering etc
#include <set>
#include <iostream>
using namespace std;
struct Bruch {
  int z, n;  // zaehler / nenner
  partial_ordering operator<=>(const Bruch& re) const {
    if(n==0 || re.n==0) return partial_ordering::unordered;
    return (double)z / n <=> (double)re.z / re.n;
  }
};
int main() {
  set<Bruch> brueche{ {1,2}, {2,4}, {1,3}, {2,3}, {1,4}, {2,5}, {3,8}, {99,0} };
  for(auto b : brueche)
    cout << b.z << "/" << b.n << " ";
  cout << "\n"; // Ausgabe: 1/4 1/3 3/8 2/5 1/2 2/3
}

Okt 23, 2024

lst-0421-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/c3695v4r8 
#include "mein_string.hpp"
static const mein_string ZEBRA { "zebra" };
int main() {
    mein_string tier{ "pferd" };
    if(ZEBRA.equals(tier)) return 0;
    else return 1;
}

Okt 23, 2024

lst-0424-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KGEe7hj1b 
void funktion(MeinWert paramWert) {
    std::cout << "(funktion)\n";
    MeinWert lokalWert{"lokal"};
}
int main() {
    MeinWert mwert1{"mwert1"};
    funktion( MeinWert{"temp"} );
    funktion( mwert1 );
    {
        MeinWert mwert2{"mwert2"};
    }
}

Okt 23, 2024

lst-0399-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eYY1js4Te 
class Year : public Value {               // von Klasse Value ableiten
public:
    explicit Year(int v) : Value{v, 4} {} // Basisklasse initialisieren
};
class Month : public Value {
public:
    explicit Month(int v) : Value{v, 2} {}
};
struct Day : public Value {               // class-public entspricht struct
    explicit Day(int v) : Value{v, 2} {}
};

Okt 23, 2024

lst-0411-book.cpp

// https://godbolt.org/z/K7TqWrjbo 
struct MeinWert { /* irgendwas */ };
MeinWert globalWert{};                    // globale Klasseninstanz

void funktion(const MeinWert &paramRef) {
    if( /*...*/ ) funktion( /*x1?*/ );        // irgendeine Funktion aufrufen
    MeinWert lokalWert{};                 // lokale Klasseninstanz
}                                         // Ende der Funktion

int main() {
    MeinWert mwert1{};
    funktion( /*x2?*/ );
    funktion( MeinWert{} );               // temporärer Wert
    {
        MeinWert mwert2{};
        funktion( /*x3?*/ );
        MeinWert mwert3{};
    }                                     // Ende des inneren Blocks
    funktion( /*x4?*/ );
    MeinWert mwert4{};
    funktion( /*x5?*/ );
}                                         // Ende der main-Funktion

Okt 23, 2024

lst-0392-book.cpp

// https://godbolt.org/z/q8E6WMano 
#include <boost/test/parameterized_test.hpp>
struct Param {
    string input;
    vector<string> expected;
};
const vector<Param> params {
    // { Eingabe, erwartetes Ergebnis }
    {""s,     {"^^$"s, "^$$"s} },
    {"A"s,    {"^^A"s, "^A$"s, "A$$"s} },
    {"AB"s,   {"^^A"s, "^AB"s, "AB$"s, "B$$"s} },
    {"ACB"s,  {"^^A"s, "^AC"s, "ACB"s, "CB$"s, "B$$"s} },
    {"AAA"s,  {"^^A"s, "^AA"s, "AAA"s, "AA$"s, "A$$"s} },
};
void testQgramify(const Param& param) {
    /* arrange */
    UnderTest inst{};
    /* act */
    auto result = inst._qgramify(param.input);
    /* assert */
    BOOST_CHECK_EQUAL_COLLECTIONS(
        param.expected.begin(), param.expected.end(),
        result.begin(), result.end());
}

Okt 23, 2024

lst-0417-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/93PT8W9hY 
#include <iostream>              // cout
#include "database.hpp"          // Einbinden der fremden Programmierschnittstelle
class Database {
    db_handle_t db_;             // eingepackte Ressource
public:
    Database(const char* filename);
    ~Database();
    int execute(const char* query);
};
Database::Database(const char* filename)
    : db_{db_open(filename)}     // Anfordern der Ressource
    { }
Database::~Database() {
    db_close(db_);               // Freigeben der Ressource
}
int Database::execute(const char* query) {
    return db_execute(db_, query); // Nutzen der Ressource
}
int main() {
    Database db{ "kunden.dat" };   // Erzeugen des Wrappers
    std::cout << "Anzahl: "<< db.execute("select * from kunden") << "\n";
}                                  // automatisches Entfernen des Wrappers

Okt 23, 2024

lst-0432-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PfW8oKPK4 
#include <iostream>              // cout
#include "database.hpp"          // Einbinden der fremden Programmierschnittstelle

class Database {
    const db_handle_t db_;                         // konstant machen
public:
    Database(const char* filename);
    ~Database();
    int execute(const char* query);
    Database(const Database&) = delete;            // Kopieren verbieten
    Database& operator=(const Database&) = delete; // Zuweisung verbieten
};
//  Implementierungen wie gehabt 
int main() {
    Database db{ "kunden.dat" };
    std::cout << "Anzahl: "<< db.execute("select * from kunden") << "\n";
    Database db2{ db }; //                 (ERR)               Compiler verhindert gefährliche Kopie
    db = db2;           //                 (ERR)               Compiler verhindert gefährliche Zuweisung
}

Okt 23, 2024

lst-0398-book.cpp

// https://godbolt.org/z/hhGo46z5a 
#include <iostream>  // ostream
#include <format>    // format, vformat, make_format_args
using std::ostream;
class Value {
protected: // nicht öffentlich, nur für den eigenen und abgeleiteten Gebrauch
    int value_;
    const std::string fmt_;  // z. B. "{:02}" oder "{:04}"
    Value(int v, unsigned w) // Konstruktor mit zwei Argumenten
      : value_{v}, fmt_{std::format("{{:0{}}}", w)} {}
public:
    ostream& print(ostream& os) const;
};
ostream& operator<<(ostream& os, const Value& rechts) {
    return rechts.print(os);
}
ostream& Value::print(ostream& os) const {
    return os << std::vformat(fmt_, std::make_format_args(value_));
}

Okt 23, 2024

lst-0406-book.cpp

// https://godbolt.org/z/57vexTPnn 
class Base {
public:
    Base() {}                 // null-Argument-Konstruktor
    explicit Base(int i) {}   // ein Argument
    Base(int i, int j) {}     // zwei Argumente
    void func() {};           // Methode
};

class Derived : public Base { // kein eigener Konstruktor
};

int main() {
    Base b0{};                // okay, null-Argument-Konstruktor
    Base b1{12};              // okay, ein Argument
    Base b2{6,18};            // okay, zwei Argumente
    Derived d0{};             // okay, Compiler generiert Defaultkonstruktor
    d0.func();                // okay, Methode wird geerbt
    Derived d1{7};            //                 (ERR)                 Fehler: kein Konstruktor für ein Argument
    Derived d2{3,13};         //                 (ERR)                 Fehler: kein Konstruktor für zwei Argumente
}

Okt 23, 2024

lst-0401-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Wjsvv6Gdv 
class Date;  // Vorwärtsdeklaration
class Year : public Value {
public:
    explicit Year(int v) : Value{v, 4} {}
    Date ostern() const;            // neue Methode deklarieren
};
// Hier Month, Day und Date deklarieren. Dann:
Date Year::ostern() const {         // neue Methode definieren
    const int y = value_;
    int a = value_/100*1483 - value_/400*2225 + 2613;
    int b = (value_%19*3510 + a/25*319)/330%29;
    b = 148 - b - (value_*5/4 + a - b)%7;
    return Date{Year{value_}, Month{b/31}, Day{b%31 + 1}};
}
int main() {
    using std::cout;
    Year year{2014};
    cout << year.ostern() << "\n";  // Ausgabe: 2014-04-20
}

Okt 23, 2024

lst-0398-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hhGo46z5a 
#include <iostream>  // ostream
#include <format>    // format, vformat, make_format_args
using std::ostream;
class Value {
protected: // nicht öffentlich, nur für den eigenen und abgeleiteten Gebrauch
    int value_;
    const std::string fmt_;  // z. B. "{:02}" oder "{:04}"
    Value(int v, unsigned w) // Konstruktor mit zwei Argumenten
      : value_{v}, fmt_{std::format("{{:0{}}}", w)} {}
public:
    ostream& print(ostream& os) const;
};
ostream& operator<<(ostream& os, const Value& rechts) {
    return rechts.print(os);
}
ostream& Value::print(ostream& os) const {
    return os << std::vformat(fmt_, std::make_format_args(value_));
}

Okt 23, 2024

lst-0424-book.cpp

// https://godbolt.org/z/KGEe7hj1b 
void funktion(MeinWert paramWert) {
    std::cout << "(funktion)\n";
    MeinWert lokalWert{"lokal"};
}
int main() {
    MeinWert mwert1{"mwert1"};
    funktion( MeinWert{"temp"} );
    funktion( mwert1 );
    {
        MeinWert mwert2{"mwert2"};
    }
}

Okt 23, 2024

lst-0409-book.cpp

// https://godbolt.org/z/j9Er3s1xo 
//… Basis2 und Wert2 wie gehabt …
void ausgabe(Wert2 x) {         // abgeleitete Klasse als Wert
    x.print(cout);
}
int main() {
    Basis2 ba2{}; ausgabe(ba2); //                 (ERR)  ba2 kann nicht in Wert2 umgewandelt werden
    Wert2 we2{}; ausgabe(we2);  // gibt 10 aus
}

Okt 23, 2024

lst-0417-book.cpp

// https://godbolt.org/z/93PT8W9hY 
#include <iostream>              // cout
#include "database.hpp"          // Einbinden der fremden Programmierschnittstelle
class Database {
    db_handle_t db_;             // eingepackte Ressource
public:
    Database(const char* filename);
    ~Database();
    int execute(const char* query);
};
Database::Database(const char* filename)
    : db_{db_open(filename)}     // Anfordern der Ressource
    { }
Database::~Database() {
    db_close(db_);               // Freigeben der Ressource
}
int Database::execute(const char* query) {
    return db_execute(db_, query); // Nutzen der Ressource
}
int main() {
    Database db{ "kunden.dat" };   // Erzeugen des Wrappers
    std::cout << "Anzahl: "<< db.execute("select * from kunden") << "\n";
}                                  // automatisches Entfernen des Wrappers

Okt 23, 2024

lst-0412-book.cpp

// https://godbolt.org/z/TvKP7Ghvh 
#include <string>
#include <iostream>                      // cout
using std::string; using std::cout;

struct Value {
    int wert_;
    Value(int wert)                      // 1-Arg-Konstruktor = Typumwandlung
        : wert_{wert} {}
};

size_t laenge(string arg) {
    return arg.size();
}
Value doppel(Value v) {
    return Value{ v.wert_*2 };
}
int main() {
    cout << laenge("Hipphopp") << "\n";  // const char* in string
    cout << doppel(10).wert_ << "\n";    // int in Value
    string name {"Gandalf"};
    cout << ( name + " der Graue" ) << "\n"; // string + const char*
}

Okt 23, 2024

lst-0422-book.cpp

// https://godbolt.org/z/vaP4bdvns 
#include <iostream> // cout
#include <stdexcept> // runtime_error
struct KannWerfen {
    KannWerfen(int wasSollPassieren) {
        std::cout << "Konstruktor " << wasSollPassieren << "...\n";
        if(wasSollPassieren == 666)
            throw std::runtime_error("Testfehler");
        std::cout << "...Konstruktor fertig\n";
    }
    ~KannWerfen() {
        std::cout << "Destruktor.\n";
    }
};
int main() {
    try {
        KannWerfen kw1{0};               // okay, löst keine Ausnahme aus
    } catch(std::runtime_error &exc) {
        std::cout << "Gefangen-1: " << exc.what() << "\n";
    }
    try {
        KannWerfen kw2{666};             // löst aus, kw2 wird nicht erzeugt
    } catch(std::runtime_error &exc) {
        std::cout << "Gefangen-2: " << exc.what() << "\n";
    }
}

Okt 23, 2024

lst-0425-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/j67W4zPWE 
struct MeinWert {
   static int zaehler;
   int nummer_;
   string name_;
   explicit MeinWert(string name) // wie zuvor
      : nummer_{++zaehler} , name_{name}
      { cout << setw(nummer_) << '_'  << "Konstruktor " << name_ << "\n"; }
   MeinWert(const MeinWert &orig) // neuer Kopierkonstruktor
      : nummer_{++zaehler} , name_{orig.name_ + "-Kopie"}
      { cout << setw(nummer_)<<" " << "Kopierkonstruktor " << name_ << "\n"; }
   ~MeinWert() { // wie zuvor
      cout << setw(nummer_)<<" " << "Destruktor " << name_ << "\n";
   }
};
int MeinWert::zaehler = 0;

Okt 23, 2024

lst-0404-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/aj8cnox4f 
#include <iostream>

using std::ostream; using std::cout;
struct Basis2 {
    int acht_ = 8;
    virtual int wert() const          // virtuelle Methode
        { return acht_; }
    void print(ostream& os) const
        { os << wert() << "\n"; }
};
struct Wert2 : public Basis2 {
    int zehn_ = 10;
    virtual int wert() const override // überschreiben
        { return zehn_; }
};
int main() {
    Wert2 we2{}; we2.print(cout);     // verwenden
}

Okt 23, 2024

lst-0387-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TfMnK1Tnn 
/* private Header aus lib-Verzeichnis: */
#include "impl_multimap.hpp"                  // zu testen
// wir definieren  init_unit_test_suite() selbst, also NICHT setzen:
/* #define BOOST_TEST_MODULE qgram */
#include <boost/test/included/unit_test.hpp>
#include <memory>                             // shared ptr
#include <vector>
#include <string>
using namespace boost::unit_test;
using namespace std::literals::string_literals;
using std::string; using std::vector;
/* === Eine Testklasse für die zu testende Klasse === */
using UnderTest = qw::impl_multimap::index_impl;
class ImplMultimapTest {                      // Klasse mit Testmethoden
public:
    /* === Konstanten === */
    void testConstants() {
        BOOST_REQUIRE_EQUAL(UnderTest::_prefix().length(), UnderTest::_q()-1);
        BOOST_REQUIRE_EQUAL(UnderTest::_suffix().length(), UnderTest::_q()-1);
        for(size_t i = 0; i < UnderTest::_q()-1; ++i) {
            BOOST_CHECK_EQUAL(UnderTest::_prefix()[i], '^');
            BOOST_CHECK_EQUAL(UnderTest::_suffix()[i], '$');
        }
        // oder konkreter:
        BOOST_TEST(UnderTest::_q() == 3u);
        BOOST_TEST(UnderTest::_prefix() == "^^"s);
        BOOST_TEST(UnderTest::_suffix() == "$$"s);
    }
    /* === qgramify === */
    void testQgramifyEmpty() {
        UnderTest inst{};
        auto result = inst._qgramify(""s);
        vector<string> expected{"^^$"s, "^$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify1() {
        UnderTest inst{};
        auto result = inst._qgramify("a"s);
        vector<string> expected{"^^a"s, "^a$"s, "a$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify2() {
        UnderTest inst{};
        auto result = inst._qgramify("ab"s);
        vector<string> expected{"^^a"s, "^ab"s, "ab$"s, "b$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify3() {
        UnderTest inst{};
        auto result = inst._qgramify("abc"s);
        vector<string> expected{"^^a"s, "^ab"s, "abc"s, "bc$"s, "c$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    /* === add === */
    void testAdd_nodups() {
        UnderTest inst{};                     /* arrange */
        BOOST_REQUIRE_EQUAL(inst.size(), 0u); /* assert */
        inst.add("", "");                     /* act */
        BOOST_CHECK_EQUAL(inst.size(), 1u);   /* assert */
        inst.add("ENTRY", "entry");           /* act */
        BOOST_CHECK_EQUAL(inst.size(), 2u);   /* assert */
        inst.add("OTHER", "other");           /* act */
        BOOST_CHECK_EQUAL(inst.size(), 3u);   /* assert */
    }
    /* === add === */
    void test_getBestMatch_empty() {
        UnderTest inst{};
        auto result = inst.getBestMatch("any");
        BOOST_CHECK_EQUAL(result, ""s);
    }
    void test_getBestMatch_one() {
        /* arrange */
        UnderTest inst{};
        inst.add("HOLSDERTEUFEL", "holsderteufel");
        /* act */
        auto result = inst.getBestMatch("ROBERT");
        BOOST_CHECK_EQUAL(result, "holsderteufel"s);
    }
    void test_getBestMatch_exact() {
        /* arrange */
        UnderTest inst{};
        inst.add("BERLIN", "Berlin");
        inst.add("HAMBURG", "Hamburg");
        inst.add("DORTMUND", "Dortmund");
        inst.add("STUTTGART", "Stuttgart");
        inst.add("WYK", "Wyk");
        /* act and assert */
        BOOST_CHECK_EQUAL(inst.getBestMatch("BERLIN"), "Berlin"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("HAMBURG"), "Hamburg"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("DORTMUND"), "Dortmund"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("STUTTGART"), "Stuttgart"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("WYK"), "Wyk"s);
    }
    void test_getBestMatch_close() {
        /* arrange */
        UnderTest inst{};
        inst.add("BERLIN", "Berlin");
        inst.add("HAMBURG", "Hamburg");
        inst.add("DORTMUND", "Dortmund");
        inst.add("STUTTGART", "Stuttgart");
        inst.add("WYK", "Wyk");
        /* act and assert */
        BOOST_CHECK_EQUAL(inst.getBestMatch("BRLIN"), "Berlin"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("BURG"), "Hamburg"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("DORTDORT"), "Dortmund"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("STUTGURT"), "Stuttgart"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("WIK"), "Wyk"s);
    }
/* Bei neuen Testmethoden: Hinzufügen zu init_unit_test_suite() nicht vergessen */
};
/* === Suite === */
test_suite* init_unit_test_suite( int argc, char* argv[] ) {
    auto tester = std::make_shared<ImplMultimapTest>();
    auto &ts = framework::master_test_suite();
    ts.add( BOOST_TEST_CASE( [=](){ tester->testConstants(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramifyEmpty(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify1(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify2(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify3(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify3(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testAdd_nodups(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_empty(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_one(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_exact(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_close(); } ));
    return nullptr;
}

Okt 23, 2024

lst-0392-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/q8E6WMano 
#include <boost/test/parameterized_test.hpp>
struct Param {
    string input;
    vector<string> expected;
};
const vector<Param> params {
    // { Eingabe, erwartetes Ergebnis }
    {""s,     {"^^$"s, "^$$"s} },
    {"A"s,    {"^^A"s, "^A$"s, "A$$"s} },
    {"AB"s,   {"^^A"s, "^AB"s, "AB$"s, "B$$"s} },
    {"ACB"s,  {"^^A"s, "^AC"s, "ACB"s, "CB$"s, "B$$"s} },
    {"AAA"s,  {"^^A"s, "^AA"s, "AAA"s, "AA$"s, "A$$"s} },
};
void testQgramify(const Param& param) {
    /* arrange */
    UnderTest inst{};
    /* act */
    auto result = inst._qgramify(param.input);
    /* assert */
    BOOST_CHECK_EQUAL_COLLECTIONS(
        param.expected.begin(), param.expected.end(),
        result.begin(), result.end());
}

Okt 23, 2024

lst-0413-book.cpp

// https://godbolt.org/z/qzbnK9v1o 
#include <string>
#include <iostream>
#include <iomanip>   // setw
using std::cout; using std::setw; using std::string;
struct MeinWert {
    static int zaehler;              // static: existiert nur einmal für alle Instanzen
    int nummer_;                     // Einrücktiefe dieser Instanz für die Ausgabe
    string name_;                    // Name dieser Instanz für die Ausgabe
    explicit MeinWert(string name)
        : nummer_{++zaehler}         // Zähler für Einrücktiefe pro Instanz hochzählen
        , name_{name}               // Name des Objekts für Ausgabe merken
    {
        cout << setw(nummer_) << " " // nummer_ verwenden für Einrücktiefe
             << "Konstruktor " << name_ << "\n"; // Instanzname ausgeben        }
    ~MeinWert() {                    // Destruktor
        cout << setw(nummer_) << " " << "Destruktor " << name_ << "\n";
    }
};
int MeinWert::zaehler = 0;           // Initialisierung der statischen Klassenvariablen

Okt 23, 2024

lst-0408-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jfocr7qf1 
//… Basis2 und Wert2 wie gehabt 
void ausgabe(Basis2 x) {        // Übergabe als Wert
    x.print(cout);
}
int main() {
    Basis2 ba2{}; ausgabe(ba2); // gibt 8 aus
    Wert2 we2{}; ausgabe(we2);  // gibt auch 8 aus
}

Okt 23, 2024

lst-0400-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9rY7qhK89 
class Date {
    Year year_;
    Month month_ {1};
    Day day_ {1};
public:
    explicit Date(int y) : year_{y} {} // year-01-01
    Date(Year y, Month m, Day d) : year_{y}, month_{m}, day_{d} {}
    ostream& print(ostream& os) const;
};
ostream& Date::print(ostream& os) const {
    return os << year_ << "-" << month_ << "-"  << day_;
}
ostream& operator<<(ostream& os, const Date& rechts) {
    return rechts.print(os);
}
int main() {
    Date d1 { Year{2013}, Month{15}, Day{19} };
    std::cout << d1 << "\n"; // Ausgabe: 2013-15-19
}

Okt 23, 2024

lst-0414-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oY953arPj 
void funktion(const MeinWert &paramRef) {
    MeinWert lokalWert{"lokal"};
}

int main() {
    MeinWert mwert1{"mwert1"};
    funktion( MeinWert{"temp"} );
    funktion( mwert1 );
    {
        MeinWert mwert2{"mwert2"};
    }
}

Okt 23, 2024

lst-0377-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y98jq1eGx 
#include "qwort/qwort.hpp" // under test
#define BOOST_TEST_MODULE qwort
#include <boost/test/included/unit_test.hpp>
using namespace boost::unit_test;
BOOST_AUTO_TEST_CASE( version_is_1 ) {
    BOOST_TEST(qw::version() == 1);
    // der folgende Vergleich soll fehlschlagen, aber nur eine Warnung erzeugen:
    BOOST_WARN_EQUAL(qw::version(), 2);   //                 (ERR)  ungleich, aber macht weiter
}
BOOST_AUTO_TEST_CASE( init_size_0 ) {
    qw::index inst{};                     // arrange
    auto sz = inst.size();                // act
    BOOST_TEST(sz == 0u);                 // assert
}
BOOST_AUTO_TEST_CASE( add_size_1 ) {
    using namespace std::literals::string_literals;
    qw::index inst{};                     // arrange
    inst.add(""s);                        // act
    BOOST_REQUIRE_EQUAL(inst.size(), 1u); // assert
}
BOOST_AUTO_TEST_CASE( normalize ) {
    using namespace std::literals::string_literals;
    qw::index inst{}; // arrange
    // acts und asserts; könnte auch in getrennten Funktionen sein
    BOOST_CHECK_EQUAL(inst.normalize("a"s), "A"s);
    BOOST_CHECK_EQUAL(inst.normalize("Stadt"s), "STADT"s);
    BOOST_CHECK_EQUAL(inst.normalize("Leer Zeichen"s), "LEER#ZEICHEN"s);
    BOOST_CHECK_EQUAL(inst.normalize("!Sym-bol."s), "#SYM#BOL#"s);
}
BOOST_AUTO_TEST_CASE( move ) {
    qw::index inst{};
    qw::index other = std::move( inst );
    BOOST_CHECK_EQUAL(other.size(), 0u); // pimpl erfolgreich verschoben?
}

Okt 23, 2024

lst-0410-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3nvrvrrYW 
//… Basis2 und Wert2 wie gehabt 
void ausgabe(Basis2& x) {       // Übergabe als Referenz
    x.print(cout);
}

int main() {
    Basis2 ba2{}; ausgabe(ba2); // gibt 8 aus
    Wert2 we2{}; ausgabe(we2);  // gibt 10 aus, denn das Objekt wird nicht kopiert
}

Okt 23, 2024

lst-0407-book.cpp

// https://godbolt.org/z/8b3Yvnjh4 
class Base {
public:
    Base() {}
    explicit Base(int i) {}
    Base(int i, int j) {}
    void func() {};           // Methode
};

class Derived : public Base {
public:
    using Base::Base;         // Importieren aller Konstruktoren der Elternklasse
};

int main() {
    Derived d0{};             // okay, importiert, nicht mehr generiert
    Derived d1{7};            // okay, wurde importiert
    Derived d2{3,13};         // okay, wurde importiert
}

Okt 23, 2024

lst-0412-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TvKP7Ghvh 
#include <string>
#include <iostream>                      // cout
using std::string; using std::cout;

struct Value {
    int wert_;
    Value(int wert)                      // 1-Arg-Konstruktor = Typumwandlung
        : wert_{wert} {}
};

size_t laenge(string arg) {
    return arg.size();
}
Value doppel(Value v) {
    return Value{ v.wert_*2 };
}
int main() {
    cout << laenge("Hipphopp") << "\n";  // const char* in string
    cout << doppel(10).wert_ << "\n";    // int in Value
    string name {"Gandalf"};
    cout << ( name + " der Graue" ) << "\n"; // string + const char*
}

Okt 23, 2024

lst-0377-book.cpp

// https://godbolt.org/z/Y98jq1eGx 
#include "qwort/qwort.hpp" // under test
#define BOOST_TEST_MODULE qwort
#include <boost/test/included/unit_test.hpp>
using namespace boost::unit_test;
BOOST_AUTO_TEST_CASE( version_is_1 ) {
    BOOST_TEST(qw::version() == 1);
    // der folgende Vergleich soll fehlschlagen, aber nur eine Warnung erzeugen:
    BOOST_WARN_EQUAL(qw::version(), 2);   //                 (ERR)  ungleich, aber macht weiter
}
BOOST_AUTO_TEST_CASE( init_size_0 ) {
    qw::index inst{};                     // arrange
    auto sz = inst.size();                // act
    BOOST_TEST(sz == 0u);                 // assert
}
BOOST_AUTO_TEST_CASE( add_size_1 ) {
    using namespace std::literals::string_literals;
    qw::index inst{};                     // arrange
    inst.add(""s);                        // act
    BOOST_REQUIRE_EQUAL(inst.size(), 1u); // assert
}
BOOST_AUTO_TEST_CASE( normalize ) {
    using namespace std::literals::string_literals;
    qw::index inst{}; // arrange
    // acts und asserts; könnte auch in getrennten Funktionen sein
    BOOST_CHECK_EQUAL(inst.normalize("a"s), "A"s);
    BOOST_CHECK_EQUAL(inst.normalize("Stadt"s), "STADT"s);
    BOOST_CHECK_EQUAL(inst.normalize("Leer Zeichen"s), "LEER#ZEICHEN"s);
    BOOST_CHECK_EQUAL(inst.normalize("!Sym-bol."s), "#SYM#BOL#"s);
}
BOOST_AUTO_TEST_CASE( move ) {
    qw::index inst{};
    qw::index other = std::move( inst );
    BOOST_CHECK_EQUAL(other.size(), 0u); // pimpl erfolgreich verschoben?
}

Okt 23, 2024

lst-0416-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/54dzsb31z 
#ifndef DATABASE_HPP
#define DATABASE_HPP

typedef void* db_handle_t;

db_handle_t db_open(const char* filename);
void db_close(db_handle_t db);
int db_execute(db_handle_t db, const char* query);

#endif

Okt 23, 2024

lst-0432-book.cpp

// https://godbolt.org/z/PfW8oKPK4 
#include <iostream>              // cout
#include "database.hpp"          // Einbinden der fremden Programmierschnittstelle

class Database {
    const db_handle_t db_;                         // konstant machen
public:
    Database(const char* filename);
    ~Database();
    int execute(const char* query);
    Database(const Database&) = delete;            // Kopieren verbieten
    Database& operator=(const Database&) = delete; // Zuweisung verbieten
};
// … Implementierungen wie gehabt …
int main() {
    Database db{ "kunden.dat" };
    std::cout << "Anzahl: "<< db.execute("select * from kunden") << "\n";
    Database db2{ db }; //                 (ERR)               Compiler verhindert gefährliche Kopie
    db = db2;           //                 (ERR)               Compiler verhindert gefährliche Zuweisung
}

Okt 23, 2024

lst-0416-book.cpp

// https://godbolt.org/z/54dzsb31z 
#ifndef DATABASE_HPP
#define DATABASE_HPP

typedef void* db_handle_t;

db_handle_t db_open(const char* filename);
void db_close(db_handle_t db);
int db_execute(db_handle_t db, const char* query);

#endif

Okt 23, 2024

lst-0414-book.cpp

// https://godbolt.org/z/oY953arPj 
void funktion(const MeinWert &paramRef) {
    MeinWert lokalWert{"lokal"};
}

int main() {
    MeinWert mwert1{"mwert1"};
    funktion( MeinWert{"temp"} );
    funktion( mwert1 );
    {
        MeinWert mwert2{"mwert2"};
    }
}

Okt 23, 2024

lst-0411-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/K7TqWrjbo 
struct MeinWert { /* irgendwas */ };
MeinWert globalWert{};                    // globale Klasseninstanz

void funktion(const MeinWert &paramRef) {
    if( /*...*/ ) funktion( /*x1?*/ );        // irgendeine Funktion aufrufen
    MeinWert lokalWert{};                 // lokale Klasseninstanz
}                                         // Ende der Funktion

int main() {
    MeinWert mwert1{};
    funktion( /*x2?*/ );
    funktion( MeinWert{} );               // temporärer Wert
    {
        MeinWert mwert2{};
        funktion( /*x3?*/ );
        MeinWert mwert3{};
    }                                     // Ende des inneren Blocks
    funktion( /*x4?*/ );
    MeinWert mwert4{};
    funktion( /*x5?*/ );
}                                         // Ende der main-Funktion

Okt 23, 2024

lst-0403-book.cpp

// https://godbolt.org/z/476G1xzKr 
#include <iostream>
struct Basis {
    int acht_ = 8;
    int wert() const { return acht_; }
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
struct Print : public Basis {
    int neun_ = 9;
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
struct Wert : public Basis {
    int zehn_ = 10;
    int wert() const { return zehn_; }
};
struct Beides : public Basis {
    int elf_ = 11;
    int wert() const { return elf_; }
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
int main() {
    Basis ba{}; ba.print(std::cout);   // Basisaufruf
    Print pr{}; pr.print(std::cout);   // print überschrieben
    Wert we{}; we.print(std::cout);    // print aus Basis
    Beides be{}; be.print(std::cout);  // alles überschrieben
}

Okt 23, 2024

lst-0431-book.cpp

// https://godbolt.org/z/acWjozE15 
struct MeineNummer {
    int nummer_; // variables Datenfeld

    explicit MeineNummer(int v)
        : nummer_{v} {}
    MeineNummer& operator=(const MeineNummer&) = delete; // Zuweisung streichen
    MeineNummer(const MeineNummer&) = delete;            // Kopie streichen
};
int main() {
    MeineNummer c1{4};
    MeineNummer c2{7};
    c1 = c2;            //             (ERR)  Fehler  Zuweisung vom Programmierer gestrichen
    MeineNummer c3{c1}; //             (ERR)  Fehler  Kopie vom Programmierer gestrichen
}

Okt 23, 2024

lst-0409-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/j9Er3s1xo 
//… Basis2 und Wert2 wie gehabt 
void ausgabe(Wert2 x) {         // abgeleitete Klasse als Wert
    x.print(cout);
}
int main() {
    Basis2 ba2{}; ausgabe(ba2); //                 (ERR)  ba2 kann nicht in Wert2 umgewandelt werden
    Wert2 we2{}; ausgabe(we2);  // gibt 10 aus
}

Okt 23, 2024

lst-0413-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qzbnK9v1o 
#include <string>
#include <iostream>
#include <iomanip>   // setw
using std::cout; using std::setw; using std::string;
struct MeinWert {
    static int zaehler;              // static: existiert nur einmal für alle Instanzen
    int nummer_;                     // Einrücktiefe dieser Instanz für die Ausgabe
    string name_;                    // Name dieser Instanz für die Ausgabe
    explicit MeinWert(string name)
        : nummer_{++zaehler}         // Zähler für Einrücktiefe pro Instanz hochzählen
        , name_{name}               // Name des Objekts für Ausgabe merken
    {
        cout << setw(nummer_) << " " // nummer_ verwenden für Einrücktiefe
             << "Konstruktor " << name_ << "\n"; // Instanzname ausgeben        }
    ~MeinWert() {                    // Destruktor
        cout << setw(nummer_) << " " << "Destruktor " << name_ << "\n";
    }
};
int MeinWert::zaehler = 0;           // Initialisierung der statischen Klassenvariablen

Okt 23, 2024

lst-0406-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/57vexTPnn 
class Base {
public:
    Base() {}                 // null-Argument-Konstruktor
    explicit Base(int i) {}   // ein Argument
    Base(int i, int j) {}     // zwei Argumente
    void func() {};           // Methode
};

class Derived : public Base { // kein eigener Konstruktor
};

int main() {
    Base b0{};                // okay, null-Argument-Konstruktor
    Base b1{12};              // okay, ein Argument
    Base b2{6,18};            // okay, zwei Argumente
    Derived d0{};             // okay, Compiler generiert Defaultkonstruktor
    d0.func();                // okay, Methode wird geerbt
    Derived d1{7};            //                 (ERR)                 Fehler: kein Konstruktor für ein Argument
    Derived d2{3,13};         //                 (ERR)                 Fehler: kein Konstruktor für zwei Argumente
}

Okt 23, 2024

lst-0387-book.cpp

// https://godbolt.org/z/TfMnK1Tnn 
/* private Header aus lib-Verzeichnis: */
#include "impl_multimap.hpp"                  // zu testen
// wir definieren  init_unit_test_suite() selbst, also NICHT setzen:
/* #define BOOST_TEST_MODULE qgram */
#include <boost/test/included/unit_test.hpp>
#include <memory>                             // shared ptr
#include <vector>
#include <string>
using namespace boost::unit_test;
using namespace std::literals::string_literals;
using std::string; using std::vector;
/* === Eine Testklasse für die zu testende Klasse === */
using UnderTest = qw::impl_multimap::index_impl;
class ImplMultimapTest {                      // Klasse mit Testmethoden
public:
    /* === Konstanten === */
    void testConstants() {
        BOOST_REQUIRE_EQUAL(UnderTest::_prefix().length(), UnderTest::_q()-1);
        BOOST_REQUIRE_EQUAL(UnderTest::_suffix().length(), UnderTest::_q()-1);
        for(size_t i = 0; i < UnderTest::_q()-1; ++i) {
            BOOST_CHECK_EQUAL(UnderTest::_prefix()[i], '^');
            BOOST_CHECK_EQUAL(UnderTest::_suffix()[i], '$');
        }
        // oder konkreter:
        BOOST_TEST(UnderTest::_q() == 3u);
        BOOST_TEST(UnderTest::_prefix() == "^^"s);
        BOOST_TEST(UnderTest::_suffix() == "$$"s);
    }
    /* === qgramify === */
    void testQgramifyEmpty() {
        UnderTest inst{};
        auto result = inst._qgramify(""s);
        vector<string> expected{"^^$"s, "^$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify1() {
        UnderTest inst{};
        auto result = inst._qgramify("a"s);
        vector<string> expected{"^^a"s, "^a$"s, "a$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify2() {
        UnderTest inst{};
        auto result = inst._qgramify("ab"s);
        vector<string> expected{"^^a"s, "^ab"s, "ab$"s, "b$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify3() {
        UnderTest inst{};
        auto result = inst._qgramify("abc"s);
        vector<string> expected{"^^a"s, "^ab"s, "abc"s, "bc$"s, "c$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    /* === add === */
    void testAdd_nodups() {
        UnderTest inst{};                     /* arrange */
        BOOST_REQUIRE_EQUAL(inst.size(), 0u); /* assert */
        inst.add("", "");                     /* act */
        BOOST_CHECK_EQUAL(inst.size(), 1u);   /* assert */
        inst.add("ENTRY", "entry");           /* act */
        BOOST_CHECK_EQUAL(inst.size(), 2u);   /* assert */
        inst.add("OTHER", "other");           /* act */
        BOOST_CHECK_EQUAL(inst.size(), 3u);   /* assert */
    }
    /* === add === */
    void test_getBestMatch_empty() {
        UnderTest inst{};
        auto result = inst.getBestMatch("any");
        BOOST_CHECK_EQUAL(result, ""s);
    }
    void test_getBestMatch_one() {
        /* arrange */
        UnderTest inst{};
        inst.add("HOLSDERTEUFEL", "holsderteufel");
        /* act */
        auto result = inst.getBestMatch("ROBERT");
        BOOST_CHECK_EQUAL(result, "holsderteufel"s);
    }
    void test_getBestMatch_exact() {
        /* arrange */
        UnderTest inst{};
        inst.add("BERLIN", "Berlin");
        inst.add("HAMBURG", "Hamburg");
        inst.add("DORTMUND", "Dortmund");
        inst.add("STUTTGART", "Stuttgart");
        inst.add("WYK", "Wyk");
        /* act and assert */
        BOOST_CHECK_EQUAL(inst.getBestMatch("BERLIN"), "Berlin"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("HAMBURG"), "Hamburg"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("DORTMUND"), "Dortmund"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("STUTTGART"), "Stuttgart"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("WYK"), "Wyk"s);
    }
    void test_getBestMatch_close() {
        /* arrange */
        UnderTest inst{};
        inst.add("BERLIN", "Berlin");
        inst.add("HAMBURG", "Hamburg");
        inst.add("DORTMUND", "Dortmund");
        inst.add("STUTTGART", "Stuttgart");
        inst.add("WYK", "Wyk");
        /* act and assert */
        BOOST_CHECK_EQUAL(inst.getBestMatch("BRLIN"), "Berlin"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("BURG"), "Hamburg"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("DORTDORT"), "Dortmund"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("STUTGURT"), "Stuttgart"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("WIK"), "Wyk"s);
    }
/* Bei neuen Testmethoden: Hinzufügen zu init_unit_test_suite() nicht vergessen */
};
/* === Suite === */
test_suite* init_unit_test_suite( int argc, char* argv[] ) {
    auto tester = std::make_shared<ImplMultimapTest>();
    auto &ts = framework::master_test_suite();
    ts.add( BOOST_TEST_CASE( [=](){ tester->testConstants(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramifyEmpty(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify1(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify2(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify3(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify3(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testAdd_nodups(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_empty(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_one(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_exact(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_close(); } ));
    return nullptr;
}

Okt 23, 2024

lst-0403-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/476G1xzKr 
#include <iostream>
struct Basis {
    int acht_ = 8;
    int wert() const { return acht_; }
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
struct Print : public Basis {
    int neun_ = 9;
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
struct Wert : public Basis {
    int zehn_ = 10;
    int wert() const { return zehn_; }
};
struct Beides : public Basis {
    int elf_ = 11;
    int wert() const { return elf_; }
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
int main() {
    Basis ba{}; ba.print(std::cout);   // Basisaufruf
    Print pr{}; pr.print(std::cout);   // print überschrieben
    Wert we{}; we.print(std::cout);    // print aus Basis
    Beides be{}; be.print(std::cout);  // alles überschrieben
}

Okt 23, 2024

lst-0431-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/acWjozE15 
struct MeineNummer {
    int nummer_; // variables Datenfeld

    explicit MeineNummer(int v)
        : nummer_{v} {}
    MeineNummer& operator=(const MeineNummer&) = delete; // Zuweisung streichen
    MeineNummer(const MeineNummer&) = delete;            // Kopie streichen
};
int main() {
    MeineNummer c1{4};
    MeineNummer c2{7};
    c1 = c2;            //             (ERR)  Fehler  Zuweisung vom Programmierer gestrichen
    MeineNummer c3{c1}; //             (ERR)  Fehler  Kopie vom Programmierer gestrichen
}

Okt 23, 2024

lst-0425-book.cpp

// https://godbolt.org/z/j67W4zPWE 
struct MeinWert {
   static int zaehler;
   int nummer_;
   string name_;
   explicit MeinWert(string name) // wie zuvor
      : nummer_{++zaehler} , name_{name}
      { cout << setw(nummer_) << '_'  << "Konstruktor " << name_ << "\n"; }
   MeinWert(const MeinWert &orig) // neuer Kopierkonstruktor
      : nummer_{++zaehler} , name_{orig.name_ + "-Kopie"}
      { cout << setw(nummer_)<<" " << "Kopierkonstruktor " << name_ << "\n"; }
   ~MeinWert() { // wie zuvor
      cout << setw(nummer_)<<" " << "Destruktor " << name_ << "\n";
   }
};
int MeinWert::zaehler = 0;

Okt 23, 2024

lst-0400-book.cpp

// https://godbolt.org/z/9rY7qhK89 
class Date {
    Year year_;
    Month month_ {1};
    Day day_ {1};
public:
    explicit Date(int y) : year_{y} {} // year-01-01
    Date(Year y, Month m, Day d) : year_{y}, month_{m}, day_{d} {}
    ostream& print(ostream& os) const;
};
ostream& Date::print(ostream& os) const {
    return os << year_ << "-" << month_ << "-"  << day_;
}
ostream& operator<<(ostream& os, const Date& rechts) {
    return rechts.print(os);
}
int main() {
    Date d1 { Year{2013}, Month{15}, Day{19} };
    std::cout << d1 << "\n"; // Ausgabe: 2013-15-19
}

Okt 23, 2024

lst-0399-book.cpp

// https://godbolt.org/z/eYY1js4Te 
class Year : public Value {               // von Klasse Value ableiten
public:
    explicit Year(int v) : Value{v, 4} {} // Basisklasse initialisieren
};
class Month : public Value {
public:
    explicit Month(int v) : Value{v, 2} {}
};
struct Day : public Value {               // class-public entspricht struct
    explicit Day(int v) : Value{v, 2} {}
};

Okt 23, 2024

lst-0404-book.cpp

// https://godbolt.org/z/aj8cnox4f 
#include <iostream>

using std::ostream; using std::cout;
struct Basis2 {
    int acht_ = 8;
    virtual int wert() const          // virtuelle Methode
        { return acht_; }
    void print(ostream& os) const
        { os << wert() << "\n"; }
};
struct Wert2 : public Basis2 {
    int zehn_ = 10;
    virtual int wert() const override // überschreiben
        { return zehn_; }
};
int main() {
    Wert2 we2{}; we2.print(cout);     // verwenden
}

Okt 23, 2024

lst-0401-book.cpp

// https://godbolt.org/z/Wjsvv6Gdv 
class Date;  // Vorwärtsdeklaration
class Year : public Value {
public:
    explicit Year(int v) : Value{v, 4} {}
    Date ostern() const;            // neue Methode deklarieren
};
// Hier Month, Day und Date deklarieren. Dann:
Date Year::ostern() const {         // neue Methode definieren
    const int y = value_;
    int a = value_/100*1483 - value_/400*2225 + 2613;
    int b = (value_%19*3510 + a/25*319)/330%29;
    b = 148 - b - (value_*5/4 + a - b)%7;
    return Date{Year{value_}, Month{b/31}, Day{b%31 + 1}};
}
int main() {
    using std::cout;
    Year year{2014};
    cout << year.ostern() << "\n";  // Ausgabe: 2014-04-20
}

Okt 23, 2024

lst-0407-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8b3Yvnjh4 
class Base {
public:
    Base() {}
    explicit Base(int i) {}
    Base(int i, int j) {}
    void func() {};           // Methode
};

class Derived : public Base {
public:
    using Base::Base;         // Importieren aller Konstruktoren der Elternklasse
};

int main() {
    Derived d0{};             // okay, importiert, nicht mehr generiert
    Derived d1{7};            // okay, wurde importiert
    Derived d2{3,13};         // okay, wurde importiert
}

Okt 23, 2024

lst-0422-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vaP4bdvns 
#include <iostream> // cout
#include <stdexcept> // runtime_error
struct KannWerfen {
    KannWerfen(int wasSollPassieren) {
        std::cout << "Konstruktor " << wasSollPassieren << "...\n";
        if(wasSollPassieren == 666)
            throw std::runtime_error("Testfehler");
        std::cout << "...Konstruktor fertig\n";
    }
    ~KannWerfen() {
        std::cout << "Destruktor.\n";
    }
};
int main() {
    try {
        KannWerfen kw1{0};               // okay, löst keine Ausnahme aus
    } catch(std::runtime_error &exc) {
        std::cout << "Gefangen-1: " << exc.what() << "\n";
    }
    try {
        KannWerfen kw2{666};             // löst aus, kw2 wird nicht erzeugt
    } catch(std::runtime_error &exc) {
        std::cout << "Gefangen-2: " << exc.what() << "\n";
    }
}

Okt 23, 2024

lst-0410-book.cpp

// https://godbolt.org/z/3nvrvrrYW 
//… Basis2 und Wert2 wie gehabt …
void ausgabe(Basis2& x) {       // Übergabe als Referenz
    x.print(cout);
}

int main() {
    Basis2 ba2{}; ausgabe(ba2); // gibt 8 aus
    Wert2 we2{}; ausgabe(we2);  // gibt 10 aus, denn das Objekt wird nicht kopiert
}

Okt 23, 2024

lst-0408-book.cpp

// https://godbolt.org/z/jfocr7qf1 
//… Basis2 und Wert2 wie gehabt …
void ausgabe(Basis2 x) {        // Übergabe als Wert
    x.print(cout);
}
int main() {
    Basis2 ba2{}; ausgabe(ba2); // gibt 8 aus
    Wert2 we2{}; ausgabe(we2);  // gibt auch 8 aus
}

Okt 23, 2024

lst-0375-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5ajrvGvcW 
#ifndef QWORT_H   // Header-Guard
#define QWORT_H
#include <string>
#include <string_view>
#include <memory> // unique_ptr
namespace qw {    // Namensraum der Bibliothek

    int version();

    namespace impl_multimap {
        class index_impl;
    }

    class index {
        using index_impl = impl_multimap::index_impl;
    public:
        index();
        ~index() noexcept; // wird für pimpl benötigt
        index(const index&) = delete;
        index(index&&) noexcept;
        index& operator=(const index&) = delete;
        index& operator=(index&&) = delete;
    public:
        void add(std::string_view arg);
        size_t size() const;
        std::string getBestMatch(std::string_view query) const;
    public:          // public für Tests
        std::string normalize(std::string arg) const;
    private:
        std::unique_ptr<index_impl> pimpl;
    };
} // namespace qw
#endif // Header-Guard

Okt 23, 2024

lst-0421-book.cpp

// https://godbolt.org/z/c3695v4r8 
#include "mein_string.hpp"
static const mein_string ZEBRA { "zebra" };
int main() {
    mein_string tier{ "pferd" };
    if(ZEBRA.equals(tier)) return 0;
    else return 1;
}

Okt 23, 2024

lst-0342-book.cpp

// https://godbolt.org/z/v1TP6aYxT 
#include <string>
#include <string_view>
using std::string; using std::string_view;
class Widget {
    string name_ = "";
public:
    void setName(string_view newName) {
        name_ = newName;
    }
    const string& getName() const {    // const&-Rückgabe
        return name_;
    }
};
int main() {
    Widget w{};
    w.setName("Titel");
    string name1 = w.getName();        // neuer String, also Kopie
    name1.clear();                     // die Kopie dürfen Sie wieder verändern
    const string& name2 = w.getName(); // const-Referenz auf inneren string name_
    /* name2.clear(); */                   // name2 ist const, geht also nicht
    string& name3 = w.getName();       //                 (ERR)  Funktion gibt const& zurück, nicht &.
    auto name4 = w.getName();          // identisch mit name1
    const auto& name5 = w.getName();   // identisch mit name2
}

Okt 23, 2024

lst-0369-book.cpp

// https://godbolt.org/z/ba7e7s8qK 
#define BOOST_TEST_MAIN test_main            // generiert main() in diesem Modul
#include <boost/test/included/unit_test.hpp> // Framework
#include <boost/test/test_tools.hpp>         // BOOST_CHECK etc
unsigned fib(unsigned n);                    // zu testen
namespace {
using namespace boost::unit_test;
BOOST_AUTO_TEST_CASE( test_fib_low )         // beliebiger Name des Testcases
{
    BOOST_CHECK( fib(0) == 0 );              // einzelne Assertions
    BOOST_CHECK( fib(1) == 1 );
    BOOST_CHECK( fib(2) == 1 );
    BOOST_CHECK( fib(3) == 2 );
    BOOST_CHECK( fib(4) == 3 );
    BOOST_CHECK( fib(5) == 5 );
    BOOST_CHECK( fib(6) == 8 );
}
}

Okt 23, 2024

lst-0368-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ex6Mv6xcz 
unsigned fib(unsigned n) {
    if(n==0) { return 0; }
    if(n==1) { return 1; }
    unsigned a = 0;
    unsigned b = 1;
    unsigned sum = 1;
    while(n>1) {
        sum += a;
        a = b;
        b = sum;
        n -= 1;
    }
    return sum;
}

Okt 23, 2024

lst-0354-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zMbnYzo17 
template<typename T>
auto deref(T t) {
    if constexpr (std::is_pointer_v<T>) {
        return *t;
    } else {
        return t;
    }
}
int main() {
    int i = 42;
    std::cout << deref(i) << '\n';         // direkt der Wert
    auto p = std::make_unique<int>(73);
    std::cout << deref(p.get()) << '\n';   // dereferenzierter Pointer
}

Okt 23, 2024

lst-0343-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rMrKbrdWe 
#include <string>
#include <iostream>
using std::string; using std::cout;

class Widget {
    string name_{};
public:
    const string& readName() const;        // const&-Rückgabe, const-Methode
    string& getName();                     // &-Rückgabe
};

const string& Widget::readName() const { return name_; }
string& Widget::getName() { return name_; }

int main() {
    Widget w{};
    const string& readonly = w.readName(); // const&, unveränderbar
    cout << "Name: " << readonly << "\n";  // noch "" leer.
    string& readwrite = w.getName();       // &, veränderbar
    readwrite.append("dran");       // verändert auch name_ und readonly
    cout << "Name per readwrite: " << readwrite << "\n"; // "dran"
    cout << "Name per readonly: " << readonly << "\n";   // auch "dran"
}

Okt 23, 2024

lst-0365-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fsroE4seh 
#include <iostream>

// Produktionscode:
struct DatabaseInterface {
    virtual int getData() const = 0;
};
struct RealDatabase : public DatabaseInterface {
    int getData() const override { return 999; }
};
struct Programm {
    DatabaseInterface &db_;
    void run() {
        std:: cout << db_.getData() << "\n";
    }
};

// main als Test:
int main() {
    RealDatabase db;
    Programm prog { db }; // echte DB wird  mitgetestet
    prog.run();           // Erwartete Ausgabe: 999
}

Okt 23, 2024

lst-0355-book.cpp

// https://godbolt.org/z/eo468MvMo 
#include <iostream>
#include <string>
struct S {
   int n;
   std::string s;
   float d;
};
template <std::size_t N> auto& get(S& s) {
    if constexpr (N == 0) return s.n;
    else if constexpr (N == 1) return s.s;
    else if constexpr (N == 2) return s.d;
}
int main() {
    S obj { 0, "hello", 10.0f };
    std::cout << get<0>(obj) << ", " << get<1>(obj) << "\n"; // Ausgabe: 0, hello
}

Okt 23, 2024

lst-0365-book.cpp

// https://godbolt.org/z/fsroE4seh 
#include <iostream>

// Produktionscode:
struct DatabaseInterface {
    virtual int getData() const = 0;
};
struct RealDatabase : public DatabaseInterface {
    int getData() const override { return 999; }
};
struct Programm {
    DatabaseInterface &db_;
    void run() {
        std:: cout << db_.getData() << "\n";
    }
};

// main als Test:
int main() {
    RealDatabase db;
    Programm prog { db }; // echte DB wird  mitgetestet
    prog.run();           // Erwartete Ausgabe: 999
}

Okt 23, 2024

lst-0369-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ba7e7s8qK 
#define BOOST_TEST_MAIN test_main            // generiert main() in diesem Modul
#include <boost/test/included/unit_test.hpp> // Framework
#include <boost/test/test_tools.hpp>         // BOOST_CHECK etc
unsigned fib(unsigned n);                    // zu testen
namespace {
using namespace boost::unit_test;
BOOST_AUTO_TEST_CASE( test_fib_low )         // beliebiger Name des Testcases
{
    BOOST_CHECK( fib(0) == 0 );              // einzelne Assertions
    BOOST_CHECK( fib(1) == 1 );
    BOOST_CHECK( fib(2) == 1 );
    BOOST_CHECK( fib(3) == 2 );
    BOOST_CHECK( fib(4) == 3 );
    BOOST_CHECK( fib(5) == 5 );
    BOOST_CHECK( fib(6) == 8 );
}
}

Okt 23, 2024

lst-0341-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/erv34b67c 
const Widget createWidget() {  // Rückgabe als const-Wert
    Widget result{};
    return result;
}
int main() {
    Widget w = createWidget(); // kopiert in neues nicht-const w
    w.setNumber(100);          // w ist nicht-const, verändern ist okay
}

Okt 23, 2024

lst-0348-book.cpp

// https://godbolt.org/z/MEGfeanPP 
#include <array>
struct Data {
    static const size_t SPAET;            // Konstante deklarieren
    static const size_t FRUEH;            // Konstante deklarieren
};

void func() {
    int x = Data::SPAET;                  // Konstante verwenden
}

const size_t Data::FRUEH = 10;            // Konstante definieren

std::array<int, Data::FRUEH> arrFRUEH {}; // Konstante verwenden
std::array<int, Data::SPAET> arrSPAET {}; //                 (ERR)  Konstante verwenden
const size_t Data::SPAET = 10;            // Konstante definieren

int main() {
    func();
}

Okt 23, 2024

lst-0347-book.cpp

// https://godbolt.org/z/5b3bvKd9r 
#include <array>
int main() {

    std::array<int, 5> arr5{};     // Literal und somit ein konstanter Ausdruck
    std::array<int, 2+3> arr23{};  // 2+3 kann der Compiler auswerten

    const size_t SIZE = 5;         // definiert eine Konstante
    std::array<int, SIZE> arrSC{}; // kann der Compiler verwenden — oft
    size_t size = 7;

    std::array<int,size> arrVar{}; // eine Variable können Sie nicht verwenden
}

Okt 23, 2024

lst-0367-book.cpp

// https://godbolt.org/z/Y9exe7rqT 
void testVerdopple() {
    assertTrue( verdopple(0) == 0 );
    assertTrue( verdopple(-1) == -2 );
    assertTrue( verdopple(1) == 2 );
    assertTrue( verdopple(5) == 10 );
}

Okt 23, 2024

lst-0358-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KGn9ob8on 
#include <iostream>
#include <array>
constexpr bool isPrime(int n) { // zur Übersetzungszeit berechenbar
  if(n < 2) return false; // 0, 1 sind nicht prim
  for (int i = 2; i*i <= n; i += i>2 ? 2 : 1) { // 2,3,5,7,9,11,13,15…
    if (n % i == 0) return false;
  }
  return n > 1; // für 0 und 1
}
template<int Num>
consteval std::array<int, Num> primeNumbers() { // nur zur Übersetzungszeit
  std::array<int, Num> primes{};
  int idx = 0;
  for (int val = 1; idx < Num; ++val) {
    if (isPrime(val)) primes[idx++] = val;
  }
  return primes;
}
int main() {
  // Initialisiere mit Primzahlen
  auto primes = primeNumbers<100>();  // 1000000 geht nicht
  for (auto v : primes) {
    std::cout << v << ' ';
  }
  std::cout << '\n';
}

Okt 23, 2024

lst-0341-book.cpp

// https://godbolt.org/z/erv34b67c 
const Widget createWidget() {  // Rückgabe als const-Wert
    Widget result{};
    return result;
}
int main() {
    Widget w = createWidget(); // kopiert in neues nicht-const w
    w.setNumber(100);          // w ist nicht-const, verändern ist okay
}

Okt 23, 2024

lst-0361-book.cpp

// https://godbolt.org/z/sPorKnEbd 
#include <iostream>
class Data {
    int value_;
    mutable size_t getCount_{0};
  public:
    explicit Data(int v) : value_{v} { }
    ~Data() {
        std::cout << "get wurde " << getCount_ << "-mal benutzt\n";
    }
    int get() const {
        ++getCount_;
        return value_;
    }
};
int main() {
    Data d{42};
    for(int i=0; i<10; ++i) { d.get(); }
} // Ausgabe: get wurde 10-mal benutzt

Okt 23, 2024

lst-0351-book.cpp

// https://godbolt.org/z/Krjh8M3aP 
constexpr size_t verdoppleWennZuKlein1(size_t wert) {
   return wert < 100 ? wert*2 : wert; // liefert das Doppelte zurück, wenn kleiner 100
}
std::array<int, verdoppleWennZuKlein1(50)> arr {};

Okt 23, 2024

lst-0348-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MEGfeanPP 
#include <array>
struct Data {
    static const size_t SPAET;            // Konstante deklarieren
    static const size_t FRUEH;            // Konstante deklarieren
};

void func() {
    int x = Data::SPAET;                  // Konstante verwenden
}

const size_t Data::FRUEH = 10;            // Konstante definieren

std::array<int, Data::FRUEH> arrFRUEH {}; // Konstante verwenden
std::array<int, Data::SPAET> arrSPAET {}; //                 (ERR)  Konstante verwenden
const size_t Data::SPAET = 10;            // Konstante definieren

int main() {
    func();
}

Okt 23, 2024

lst-0350-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ba9rv6P51 
struct Data {
    static constexpr size_t SPAET; //                 (ERR)  klappt nicht ohne direkte Initialisierung
    static constexpr size_t FRUEH = 10;
};
constexpr size_t Data::SPAET = 10; //                 (ERR)  bei constexpr geht Definition nicht wie bei const

Okt 23, 2024

lst-0347-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5b3bvKd9r 
#include <array>
int main() {

    std::array<int, 5> arr5{};     // Literal und somit ein konstanter Ausdruck
    std::array<int, 2+3> arr23{};  // 2+3 kann der Compiler auswerten

    const size_t SIZE = 5;         // definiert eine Konstante
    std::array<int, SIZE> arrSC{}; // kann der Compiler verwenden  oft
    size_t size = 7;

    std::array<int,size> arrVar{}; // eine Variable können Sie nicht verwenden
}

Okt 23, 2024

lst-0355-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eo468MvMo 
#include <iostream>
#include <string>
struct S {
   int n;
   std::string s;
   float d;
};
template <std::size_t N> auto& get(S& s) {
    if constexpr (N == 0) return s.n;
    else if constexpr (N == 1) return s.s;
    else if constexpr (N == 2) return s.d;
}
int main() {
    S obj { 0, "hello", 10.0f };
    std::cout << get<0>(obj) << ", " << get<1>(obj) << "\n"; // Ausgabe: 0, hello
}

Okt 23, 2024

lst-0350-book.cpp

// https://godbolt.org/z/ba9rv6P51 
struct Data {
    static constexpr size_t SPAET; //                 (ERR)  klappt nicht ohne direkte Initialisierung
    static constexpr size_t FRUEH = 10;
};
constexpr size_t Data::SPAET = 10; //                 (ERR)  bei constexpr geht Definition nicht wie bei const

Okt 23, 2024

lst-0367-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y9exe7rqT 
void testVerdopple() {
    assertTrue( verdopple(0) == 0 );
    assertTrue( verdopple(-1) == -2 );
    assertTrue( verdopple(1) == 2 );
    assertTrue( verdopple(5) == 10 );
}

Okt 23, 2024

lst-0343-book.cpp

// https://godbolt.org/z/rMrKbrdWe 
#include <string>
#include <iostream>
using std::string; using std::cout;

class Widget {
    string name_{};
public:
    const string& readName() const;        // const&-Rückgabe, const-Methode
    string& getName();                     // &-Rückgabe
};

const string& Widget::readName() const { return name_; }
string& Widget::getName() { return name_; }

int main() {
    Widget w{};
    const string& readonly = w.readName(); // const&, unveränderbar
    cout << "Name: " << readonly << "\n";  // noch "" leer.
    string& readwrite = w.getName();       // &, veränderbar
    readwrite.append("dran");       // verändert auch name_ und readonly
    cout << "Name per readwrite: " << readwrite << "\n"; // "dran"
    cout << "Name per readonly: " << readonly << "\n";   // auch "dran"
}

Okt 23, 2024

lst-0364-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a83sf9h8E 
#include <iostream>
// Produktionscode:
struct DatabaseInterface {
    virtual int getData() const = 0;
};
struct Programm {
    DatabaseInterface &db_;
    void run() {
        std:: cout << db_.getData() << "\n";
    }
};
// Testhelfer:
struct MockDatabase : public DatabaseInterface {
    int getData() const override { return 5; }
};
// main als Test:
int main() {
    MockDatabase mockDb;
    Programm prog { mockDb }; // echte DB wird nicht mitgetestet
    prog.run();               // Erwartete Ausgabe: 5
}

Okt 23, 2024

lst-0366-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4PeYrc8jo 
void testVerdopple5() {
    // vorbereiten
    auto param = 5;
    // ausführen
    auto result = verdopple(param);
    // überprüfen
    assertTrue(result == 10);
}

Okt 23, 2024

lst-0352-book.cpp

// https://godbolt.org/z/KPc6ExMaY 
const size_t verdoppleWennZuKlein2(size_t wert) {
    return wert < 100 ? wert*2 : wert;
}
std::array<int, verdoppleWennZuKlein2(50)> arr {}; //                     (ERR)  nicht konstant genug

Okt 23, 2024

lst-0346-book.cpp

// https://godbolt.org/z/hsWrnaEea 
namespace {
    const int MAX_A = 12;       // das Gleiche wie MAX_B, aber kein static nötig
}
static const int MAX_B = 10;    // im globalen Namensraum
struct Data {
    static const int SIZE = 14; // als Datenfeld in einer Klasse
}

void func() {
    static const int LIMIT =16; // als lokale Konstante
}

Okt 23, 2024

lst-0346-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hsWrnaEea 
namespace {
    const int MAX_A = 12;       // das Gleiche wie MAX_B, aber kein static nötig
}
static const int MAX_B = 10;    // im globalen Namensraum
struct Data {
    static const int SIZE = 14; // als Datenfeld in einer Klasse
}

void func() {
    static const int LIMIT =16; // als lokale Konstante
}

Okt 23, 2024

lst-0375-book.cpp

// https://godbolt.org/z/5ajrvGvcW 
#ifndef QWORT_H   // Header-Guard
#define QWORT_H
#include <string>
#include <string_view>
#include <memory> // unique_ptr
namespace qw {    // Namensraum der Bibliothek

    int version();

    namespace impl_multimap {
        class index_impl;
    }

    class index {
        using index_impl = impl_multimap::index_impl;
    public:
        index();
        ~index() noexcept; // wird für pimpl benötigt
        index(const index&) = delete;
        index(index&&) noexcept;
        index& operator=(const index&) = delete;
        index& operator=(index&&) = delete;
    public:
        void add(std::string_view arg);
        size_t size() const;
        std::string getBestMatch(std::string_view query) const;
    public:          // public für Tests
        std::string normalize(std::string arg) const;
    private:
        std::unique_ptr<index_impl> pimpl;
    };
} // namespace qw
#endif // Header-Guard

Okt 23, 2024

lst-0352-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KPc6ExMaY 
const size_t verdoppleWennZuKlein2(size_t wert) {
    return wert < 100 ? wert*2 : wert;
}
std::array<int, verdoppleWennZuKlein2(50)> arr {}; //                     (ERR)  nicht konstant genug

Okt 23, 2024

lst-0340-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9Esx13h9r 
struct Widget {
    int num_ = 0;
    void setNumber(int x) {    // eine Nicht-const-Methode
        num_=x;
    }
};
Widget createWidget() {        // Rückgabe als Wert
    Widget result{};           // Erzeugen
    return result;
}
int main() {
    Widget w = createWidget(); // Rückgabe als Wert erzeugt Kopie
    w.setNumber(100);          // verändern, natürlich okay, w ist nicht-const
}

Okt 23, 2024

lst-0362-book.cpp

// https://godbolt.org/z/GE5v6Ea8x 
#include <map>
#include <string>
using std::map; using std::string;
struct MyClass {
  bool isFound(const map<int,string> &dict,  // unveränderbarer Eingabeparam.
               const int &key,               // ebenso
               string &result                // Ausgabeparameter: kein const
               ) const                       // Instanz von MyClass const
  {
    const map<int,string>::const_iterator where  // Verweis und Wert fest
      = dict.find(key);
    if(where == end(dict)) {
      return false;
    } else {
      result = where->second;
      return true;
    }
  }
};

Okt 23, 2024

lst-0368-book.cpp

// https://godbolt.org/z/Ex6Mv6xcz 
unsigned fib(unsigned n) {
    if(n==0) { return 0; }
    if(n==1) { return 1; }
    unsigned a = 0;
    unsigned b = 1;
    unsigned sum = 1;
    while(n>1) {
        sum += a;
        a = b;
        b = sum;
        n -= 1;
    }
    return sum;
}

Okt 23, 2024

lst-0359-book.cpp

// https://godbolt.org/z/7KWqTPo1K 
#include <iostream> // cout
constexpr int hole_wert() {
    if consteval {
       return 42;
    } else {
       return 668;
    }
}
int main() {
  auto a = hole_wert();
  std::cout << a << '\n';       // Ausgabe: 668
  constexpr auto b = hole_wert();
  std::cout << b << '\n';       // Ausgabe: 42
}

Okt 23, 2024

lst-0364-book.cpp

// https://godbolt.org/z/a83sf9h8E 
#include <iostream>
// Produktionscode:
struct DatabaseInterface {
    virtual int getData() const = 0;
};
struct Programm {
    DatabaseInterface &db_;
    void run() {
        std:: cout << db_.getData() << "\n";
    }
};
// Testhelfer:
struct MockDatabase : public DatabaseInterface {
    int getData() const override { return 5; }
};
// main als Test:
int main() {
    MockDatabase mockDb;
    Programm prog { mockDb }; // echte DB wird nicht mitgetestet
    prog.run();               // Erwartete Ausgabe: 5
}

Okt 23, 2024

lst-0356-book.cpp

// https://godbolt.org/z/44KMf1fWr 
template<auto N>
constexpr auto fibonacci()    {
    if constexpr (N>=2) {
        return fibonacci<N-1>() + fibonacci<N-2>();
    } else {
        return N;
    }
}

int main() {
    std::cout << fibonacci<10>() << '\n';  // Ausgabe: 55
    std::cout << fibonacci<20>() << '\n';  // Ausgabe: 6765
}

Okt 23, 2024

lst-0356-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/44KMf1fWr 
template<auto N>
constexpr auto fibonacci()    {
    if constexpr (N>=2) {
        return fibonacci<N-1>() + fibonacci<N-2>();
    } else {
        return N;
    }
}

int main() {
    std::cout << fibonacci<10>() << '\n';  // Ausgabe: 55
    std::cout << fibonacci<20>() << '\n';  // Ausgabe: 6765
}

Okt 23, 2024

lst-0366-book.cpp

// https://godbolt.org/z/4PeYrc8jo 
void testVerdopple5() {
    // vorbereiten
    auto param = 5;
    // ausführen
    auto result = verdopple(param);
    // überprüfen
    assertTrue(result == 10);
}

Okt 23, 2024

lst-0359-godb.cpp

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/7KWqTPo1K 
#include <iostream> // cout
constexpr int hole_wert() {
    if consteval {
       return 42;
    } else {
       return 668;
    }
}
int main() {
  auto a = hole_wert();
  std::cout << a << '\n';       // Ausgabe: 668
  constexpr auto b = hole_wert();
  std::cout << b << '\n';       // Ausgabe: 42
}

Okt 23, 2024

lst-0361-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sPorKnEbd 
#include <iostream>
class Data {
    int value_;
    mutable size_t getCount_{0};
  public:
    explicit Data(int v) : value_{v} { }
    ~Data() {
        std::cout << "get wurde " << getCount_ << "-mal benutzt\n";
    }
    int get() const {
        ++getCount_;
        return value_;
    }
};
int main() {
    Data d{42};
    for(int i=0; i<10; ++i) { d.get(); }
} // Ausgabe: get wurde 10-mal benutzt

Okt 23, 2024

lst-0357-book.cpp

// https://godbolt.org/z/8rr4WKo8d 
int hole_eingabe() {
    return 50; // oder lese was aus einer Datei oder so
}
constexpr auto berechne_1(int eingabe) {
    return eingabe * 2;
}
consteval auto berechne_2(int eingabe) {
    return eingabe * 2;
}
int main() {
    int eingabe = hole_eingabe();
    auto a = berechne_1(77);      // zur Übersetzungszeit ... vielleicht berechenbar
    auto b = berechne_1(eingabe); //  berechenbar, aber gültig
    auto c = berechne_2(77);      //  berechenbar
    auto d = berechne_2(eingabe); //                 (ERR)   nicht berechenbar, ungültig
}

Okt 23, 2024

lst-0357-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8rr4WKo8d 
int hole_eingabe() {
    return 50; // oder lese was aus einer Datei oder so
}
constexpr auto berechne_1(int eingabe) {
    return eingabe * 2;
}
consteval auto berechne_2(int eingabe) {
    return eingabe * 2;
}
int main() {
    int eingabe = hole_eingabe();
    auto a = berechne_1(77);      // zur Übersetzungszeit ... vielleicht berechenbar
    auto b = berechne_1(eingabe); //  berechenbar, aber gültig
    auto c = berechne_2(77);      //  berechenbar
    auto d = berechne_2(eingabe); //                 (ERR)   nicht berechenbar, ungültig
}

Okt 23, 2024

lst-0358-book.cpp

// https://godbolt.org/z/KGn9ob8on 
#include <iostream>
#include <array>
constexpr bool isPrime(int n) { // zur Übersetzungszeit berechenbar
  if(n < 2) return false; // 0, 1 sind nicht prim
  for (int i = 2; i*i <= n; i += i>2 ? 2 : 1) { // 2,3,5,7,9,11,13,15…
    if (n % i == 0) return false;
  }
  return n > 1; // für 0 und 1
}
template<int Num>
consteval std::array<int, Num> primeNumbers() { // nur zur Übersetzungszeit
  std::array<int, Num> primes{};
  int idx = 0;
  for (int val = 1; idx < Num; ++val) {
    if (isPrime(val)) primes[idx++] = val;
  }
  return primes;
}
int main() {
  // Initialisiere mit Primzahlen
  auto primes = primeNumbers<100>();  // 1000000 geht nicht
  for (auto v : primes) {
    std::cout << v << ' ';
  }
  std::cout << '\n';
}

Okt 23, 2024

lst-0351-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Krjh8M3aP 
constexpr size_t verdoppleWennZuKlein1(size_t wert) {
   return wert < 100 ? wert*2 : wert; // liefert das Doppelte zurück, wenn kleiner 100
}
std::array<int, verdoppleWennZuKlein1(50)> arr {};

Okt 23, 2024

lst-0342-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/v1TP6aYxT 
#include <string>
#include <string_view>
using std::string; using std::string_view;
class Widget {
    string name_ = "";
public:
    void setName(string_view newName) {
        name_ = newName;
    }
    const string& getName() const {    // const&-Rückgabe
        return name_;
    }
};
int main() {
    Widget w{};
    w.setName("Titel");
    string name1 = w.getName();        // neuer String, also Kopie
    name1.clear();                     // die Kopie dürfen Sie wieder verändern
    const string& name2 = w.getName(); // const-Referenz auf inneren string name_
    /* name2.clear(); */                   // name2 ist const, geht also nicht
    string& name3 = w.getName();       //                 (ERR)  Funktion gibt const& zurück, nicht &.
    auto name4 = w.getName();          // identisch mit name1
    const auto& name5 = w.getName();   // identisch mit name2
}

Okt 23, 2024

lst-0354-book.cpp

// https://godbolt.org/z/zMbnYzo17 
template<typename T>
auto deref(T t) {
    if constexpr (std::is_pointer_v<T>) {
        return *t;
    } else {
        return t;
    }
}
int main() {
    int i = 42;
    std::cout << deref(i) << '\n';         // direkt der Wert
    auto p = std::make_unique<int>(73);
    std::cout << deref(p.get()) << '\n';   // dereferenzierter Pointer
}

Okt 23, 2024

lst-0362-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GE5v6Ea8x 
#include <map>
#include <string>
using std::map; using std::string;
struct MyClass {
  bool isFound(const map<int,string> &dict,  // unveränderbarer Eingabeparam.
               const int &key,               // ebenso
               string &result                // Ausgabeparameter: kein const
               ) const                       // Instanz von MyClass const
  {
    const map<int,string>::const_iterator where  // Verweis und Wert fest
      = dict.find(key);
    if(where == end(dict)) {
      return false;
    } else {
      result = where->second;
      return true;
    }
  }
};

Okt 23, 2024

lst-0296-book.cpp

// https://godbolt.org/z/vjTWjfKKz 
#include <vector>
#include <set>
#include <iostream>
using std::vector; using std::set; using std::cout;
using vector_t = vector<unsigned long long>; // Ihr eigener Typalias
int main() {
    vector_t huge{ 12ULL, 10'000'000'000ULL, 9ULL, 0ULL,  };
    vector_t::size_type sz = huge.size();
    vector_t::value_type uiuiui = huge[1];
    for(vector_t::iterator it = huge.begin(); it != huge.end(); ++it)
        *it *= 2; // verdoppeln
    /* sortieren per set */
    set<vector_t::value_type> sortiert{huge.begin(), huge.end()};
    for(vector_t::value_type val : sortiert)
        cout << val << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0260-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/e6rqbq3bE 
#include <string>
#include <string_view>
using std::string; using std::string_view;

class Person { // eine Klasse beginnt mit privater Sichtbarkeit
    string name_;
    int alter_;
    string ort_;
public:  // alles ab hier darf von außen verwendet werden
    Person(string_view n, int a, string_view o)
      : name_{n}, alter_{a}, ort_{o} { }
    void drucke();
};

Okt 23, 2024

lst-0340-book.cpp

// https://godbolt.org/z/9Esx13h9r 
struct Widget {
    int num_ = 0;
    void setNumber(int x) {    // eine Nicht-const-Methode
        num_=x;
    }
};
Widget createWidget() {        // Rückgabe als Wert
    Widget result{};           // Erzeugen
    return result;
}
int main() {
    Widget w = createWidget(); // Rückgabe als Wert erzeugt Kopie
    w.setNumber(100);          // verändern, natürlich okay, w ist nicht-const
}

Okt 23, 2024

lst-0291-book.cpp

// https://godbolt.org/z/EPz4Kd6jP 
class Year {
    int value_;
public:
    explicit Year(int v) : value_{v} {}
    std::ostream& print(std::ostream& os) const;
    Year& advance(const Year& other);
    bool equals(const Year& other) const;
    bool less_than(const Year& other) const;
};
std::ostream& Year::print(std::ostream& os) const {
    return os << value_;
}
std::ostream& operator<<(std::ostream& os, const Year& year) {
    return year.print(os);
}
Year& Year::advance(const Year& other) {
    value_ += other.value_;
    return *this;
}
bool Year::equals(const Year& other) const {
    return value_ == other.value_;
}
bool Year::less_than(const Year& other) const {
    return value_ < other.value_;
}

Okt 23, 2024

lst-0308-book.cpp

// https://godbolt.org/z/M81MjePh5 
#include <map>

struct Zahl {
    int wert_ = 0;
    explicit Zahl(int w) : wert_{w} {}
};

bool operator<(const Zahl& links, const Zahl& rechts) {
    return links.wert_ < rechts.wert_;
}

int main() {
    std::map<Zahl,int> zahlen{};                  // okay
    zahlen.insert( std::make_pair(Zahl{4},100) ); // braucht operator<
    zahlen[Zahl{5}] = 200;                        // hier ebenfalls
}

Okt 23, 2024

lst-0295-book.cpp

// https://godbolt.org/z/r3xaPv5Mr 
class Year {
public:
    using value_type = int;             // Typalias einführen
    value_type value_;                  // eigentlich intern verwendeter Typ
public:
    explicit Year(value_type v) : value_{v} {}
    value_type value() { return value_; }
};
int main() {
   Year year{ 2024 };                   // hier auf Compilerkonvertierung zählen
   Year::value_type val = year.value(); // verwenden Sie ::
}

Okt 23, 2024

lst-0300-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Wh71cf7j1 
#include <vector>
#include <set>
#include <iostream> // cout
using std::vector; using std::set; using std::cout;
using vector_t = vector<unsigned long long>; // Ihr eigener Typalias
int main() {
    vector_t huge{ 12ULL, 10000000000ULL, 9ULL, 0ULL,  };
    auto sz = huge.size();
    auto uiuiui = huge[1];
    for(auto it = huge.begin(); it != huge.end(); ++it)
        *it *= 2; // verdoppeln
    /* sortieren per set */
    set sortiert(huge.begin(), huge.end());  // set<vector_t::value_type>
    for(auto val : sortiert)
        cout << val << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0262-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PaG9nTs7s 
class Rect {
    int area_;         // private Daten

public:
    int x_, y_;
    void set(int x, int y) { x_=x; y_=y; area_=x_*y_; }
    int calc() { return area_; }
    Rect() = default;  // den Compiler einen Konstruktor generieren lassen
};
class Pow {
    int result_;       // private Daten; hält 'base' hoch 'exp'
public:
    int base_, exp_;
    void set(int b, int e) { /* ... */ }
    int calc() { return result_; }
    Pow() : result_{1},base_{1},exp_{1} {} // sinnvoll initialisieren
};

Okt 23, 2024

lst-0259-book.cpp

// https://godbolt.org/z/zrE55vWq3 
#include <string>
#include <string_view>
using std::string; using std::string_view;

struct Person {
private: // alles ab hier kann von außen nicht benutzt werden
    string name_;
    int alter_;
    string ort_;
public:  // alles ab hier darf von außen verwendet werden
    Person(string_view n, int a, string_view o)
      : name_{n}, alter_{a}, ort_{o} { }
    void drucke();
};

Okt 23, 2024

lst-0307-book.cpp

// https://godbolt.org/z/vrdKPvh7f 
#include <set>
struct Zahl {
    int wert_ = 0;
    explicit Zahl(int w) : wert_{w} {}
};
bool operator<(const Zahl& links, const Zahl& rechts) {
    return links.wert_ < rechts.wert_;
}
int main() {
    std::set<Zahl> zahlen{};  // okay
    zahlen.insert( Zahl{3} ); // hier wird operator< gebraucht
}

Okt 23, 2024

lst-0300-book.cpp

// https://godbolt.org/z/Wh71cf7j1 
#include <vector>
#include <set>
#include <iostream> // cout
using std::vector; using std::set; using std::cout;
using vector_t = vector<unsigned long long>; // Ihr eigener Typalias
int main() {
    vector_t huge{ 12ULL, 10000000000ULL, 9ULL, 0ULL,  };
    auto sz = huge.size();
    auto uiuiui = huge[1];
    for(auto it = huge.begin(); it != huge.end(); ++it)
        *it *= 2; // verdoppeln
    /* sortieren per set */
    set sortiert(huge.begin(), huge.end());  // set<vector_t::value_type>
    for(auto val : sortiert)
        cout << val << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0316-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M6EnPT3Gr 
// modul.hpp
#include <string>
#include <iostream>
namespace plant {
    class Baum {
        std::string name_;
    public:
        explicit Baum(const std::string_view name);
        void print(std::ostream& os) const;
    };
    std::ostream& operator<<(std::ostream& os, const Baum& arg);
}
// modul.cpp
#include "modul.hpp"
namespace {  // anonymer Namensraum
    std::string PREFIX = "BAUM:";
    void printInfo(std::ostream& os) {
        os << "Autor: Torsten T. Will\n";
    }
}
bool debug = false;  // global, kein Namensraum
namespace plant {
    Baum::Baum(const std::string_view name)
        : name_{name} {}
    void Baum::print(std::ostream& os) const {
        os << PREFIX << name_;
    }
    std::ostream& operator<<(std::ostream& os, const Baum& arg) {
        if(debug) printInfo(os);
        arg.print(os); return os;
    }
}
// main.cpp
#include "modul.hpp"
int main() {
    plant::Baum x{"x"};
    x.print(std::cout); std::cout << "\n";
}

Okt 23, 2024

lst-0322-book.cpp

// https://godbolt.org/z/h5qond6db 
#include <iostream>                     // cout
class Keyboard {
    Keyboard(const Keyboard&) = delete; // keine Kopie
    const size_t nr_;                   // aktuelle Nummer
public:
    static inline size_t count_ = 0;    // zählt erzeugte Instanzen
    explicit Keyboard() : nr_{count_++} {
        std::cout << "  Keyboard().nr:"<<nr_<<"\n";
    }
};
Keyboard& getKeyboard() {
    std::cout << "  getKeyboard()\n";
    static Keyboard keyboard{};         // statische lokale Variable
    return keyboard;
}
void func() {
    std::cout << "kbFunc...\n";
    Keyboard& kbFunc = getKeyboard();
}
int main() {
    std::cout << "kbA...\n";
    Keyboard& kbA = getKeyboard();
    func();
    std::cout << "kbB...\n";
    Keyboard& kbB = getKeyboard();
    std::cout << "count:" << Keyboard::count_ << "\n";
}

Okt 23, 2024

lst-0319-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n4e8xdEGj 
#include <iostream> // cout
#include <string>
using std::string;
class Tree {
    static size_t countConstructed_;
    static size_t countDestructed_;
    string kind_;
    Tree(string kind) : kind_{kind}      // privater Konstruktor
        { ++countConstructed_; }
public:
    Tree(const Tree& o) : kind_{o.kind_}
        { ++countConstructed_; }
    string getKind() const { return kind_; }
    ~Tree() { ++countDestructed_; }
    static Tree create(string kind) { return Tree{kind}; }
    static void stats(std::ostream& os) {
        os << "Constructed:+" << countConstructed_
           << " Destructed:-" << countDestructed_ << "\n";
    }
};
size_t Tree::countConstructed_ = 0;
size_t Tree::countDestructed_ = 0;
int main() {
    Tree birke = Tree::create("Birke");
    for(auto kind : {"Esche", "Eibe", "Eiche"}) {
        Tree temp = Tree::create(kind);
        std::cout << temp.getKind() << "\n";
    }
    Tree::stats(std::cout);
}

Okt 23, 2024

lst-0308-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M81MjePh5 
#include <map>

struct Zahl {
    int wert_ = 0;
    explicit Zahl(int w) : wert_{w} {}
};

bool operator<(const Zahl& links, const Zahl& rechts) {
    return links.wert_ < rechts.wert_;
}

int main() {
    std::map<Zahl,int> zahlen{};                  // okay
    zahlen.insert( std::make_pair(Zahl{4},100) ); // braucht operator<
    zahlen[Zahl{5}] = 200;                        // hier ebenfalls
}

Okt 23, 2024

lst-0263-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r5EsnnsEG 
#include <string>       // string, stoi
#include <iostream>     // cin, cout, ostream
#include <format>
using std::ostream; using std::format;
class Year {  /* Hilfstypen für sicheres Datum */
    int value_; // z. B. 2024
public:
    Year(int v) : value_{v} {}
    int value() { return value_; }
};
class Month {
    int value_; // 1..12
public:
    Month(int v) : value_{v} {}
    int value() { return value_; }
};
class Day {
    int value_; // 1..31
public:
    Day(int v) : value_{v} {}
    int value() { return value_; }
};
/* typsicher konstruierendes Datum */
class Date {
    Year year_;
    Month month_ = 1;
    Day day_ = 1;
public:
    Date(int y) : year_{y}           // 1-Argument-Konstruktor
        {}                           // setzt 1. Januar des angegebenen Jahres
    Date(Year y, Month m, Day d)     // 3-Argument-Konstruktor
        : year_{y}, month_{m}, day_{d}
        {}
    ostream& print(ostream& os);     // z. B. 2024-04-20
};
ostream& Date::print(ostream& os) {  // z. B. 2024-04-20
    return os << format("{}-{:02}-{:02}",
        year_.value(), month_.value(), day_.value());
}
ostream& operator<<(ostream& os, Date d) {
    return d.print(os);
}
// http://codegolf.stackexchange.com/a/11146/1405, user Fors, 2014-02-25
Date ostern(Year year) {
    const int y = year.value();
    int a = y/100*1483 - y/400*2225 + 2613;
    int b = (y%19*3510 + a/25*319)/330%29;
    b = 148 - b - (y*5/4 + a - b)%7;
    return Date{Year{y}, Month{b/31}, Day{b%31 + 1}}; // Datum erzeugen
}
int main(int argc, const char *argv[] ) {
    /* Eingabe */
    int zahl {};
    if(argc > 1) {
        zahl = std::stoi(argv[1]);
    } else {
        std::cout << "Jahr? "; std::cin >> zahl;
    }
    /* Berechnung */
    Date date = ostern(zahl);  // implizite Konvertierung nach Year
    /* Ausgabe */
    std::cout << "Ostern: " << date << "\n";
}

Okt 23, 2024

lst-0272-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/T7afh4vxz 
#include <vector>
std::vector<int> createData(unsigned size) {
    std::vector<int> result{};
    for(int idx=0; idx<size; ++idx) {
        result.push_back(idx);
    }
    return result;
}

Okt 23, 2024

lst-0324-book.cpp

// https://godbolt.org/z/115M1csEE 
#include <iostream>
namespace mylib {
    namespace v1 {
        int version() { return 1; }
    }
    inline namespace v2 { // aktuelle Version
        int version() { return 2; }
    }
}

int main() {
    std::cout << "Version " << mylib::version() << "\n";     // Ausgabe: 2
    std::cout << "Version " << mylib::v1::version() << "\n"; // Ausgabe: 1
    std::cout << "Version " << mylib::v2::version() << "\n"; // Ausgabe: 2
}

Okt 23, 2024

lst-0272-book.cpp

// https://godbolt.org/z/T7afh4vxz 
#include <vector>
std::vector<int> createData(unsigned size) {
    std::vector<int> result{};
    for(int idx=0; idx<size; ++idx) {
        result.push_back(idx);
    }
    return result;
}

Okt 23, 2024

lst-0319-book.cpp

// https://godbolt.org/z/n4e8xdEGj 
#include <iostream> // cout
#include <string>
using std::string;
class Tree {
    static size_t countConstructed_;
    static size_t countDestructed_;
    string kind_;
    Tree(string kind) : kind_{kind}      // privater Konstruktor
        { ++countConstructed_; }
public:
    Tree(const Tree& o) : kind_{o.kind_}
        { ++countConstructed_; }
    string getKind() const { return kind_; }
    ~Tree() { ++countDestructed_; }
    static Tree create(string kind) { return Tree{kind}; }
    static void stats(std::ostream& os) {
        os << "Constructed:+" << countConstructed_
           << " Destructed:-" << countDestructed_ << "\n";
    }
};
size_t Tree::countConstructed_ = 0;
size_t Tree::countDestructed_ = 0;
int main() {
    Tree birke = Tree::create("Birke");
    for(auto kind : {"Esche", "Eibe", "Eiche"}) {
        Tree temp = Tree::create(kind);
        std::cout << temp.getKind() << "\n";
    }
    Tree::stats(std::cout);
}

Okt 23, 2024

lst-0302-book.cpp

// https://godbolt.org/z/ro6fdsvT9 
#include <vector>
#include <iostream> // cout
using std::vector; using std::cout;
int main() {
    vector data{ 12, 100, -1, 0,  };    // vector<int>
    for(auto& val : data)
        val *= 2; // verdoppeln
    for(const auto val : data)
        cout << val << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0291-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EPz4Kd6jP 
class Year {
    int value_;
public:
    explicit Year(int v) : value_{v} {}
    std::ostream& print(std::ostream& os) const;
    Year& advance(const Year& other);
    bool equals(const Year& other) const;
    bool less_than(const Year& other) const;
};
std::ostream& Year::print(std::ostream& os) const {
    return os << value_;
}
std::ostream& operator<<(std::ostream& os, const Year& year) {
    return year.print(os);
}
Year& Year::advance(const Year& other) {
    value_ += other.value_;
    return *this;
}
bool Year::equals(const Year& other) const {
    return value_ == other.value_;
}
bool Year::less_than(const Year& other) const {
    return value_ < other.value_;
}

Okt 23, 2024

lst-0263-book.cpp

// https://godbolt.org/z/r5EsnnsEG 
#include <string>       // string, stoi
#include <iostream>     // cin, cout, ostream
#include <format>
using std::ostream; using std::format;
class Year {  /* Hilfstypen für sicheres Datum */
    int value_; // z. B. 2024
public:
    Year(int v) : value_{v} {}
    int value() { return value_; }
};
class Month {
    int value_; // 1..12
public:
    Month(int v) : value_{v} {}
    int value() { return value_; }
};
class Day {
    int value_; // 1..31
public:
    Day(int v) : value_{v} {}
    int value() { return value_; }
};
/* typsicher konstruierendes Datum */
class Date {
    Year year_;
    Month month_ = 1;
    Day day_ = 1;
public:
    Date(int y) : year_{y}           // 1-Argument-Konstruktor
        {}                           // setzt 1. Januar des angegebenen Jahres
    Date(Year y, Month m, Day d)     // 3-Argument-Konstruktor
        : year_{y}, month_{m}, day_{d}
        {}
    ostream& print(ostream& os);     // z. B. 2024-04-20
};
ostream& Date::print(ostream& os) {  // z. B. 2024-04-20
    return os << format("{}-{:02}-{:02}",
        year_.value(), month_.value(), day_.value());
}
ostream& operator<<(ostream& os, Date d) {
    return d.print(os);
}
// http://codegolf.stackexchange.com/a/11146/1405, user Fors, 2014-02-25
Date ostern(Year year) {
    const int y = year.value();
    int a = y/100*1483 - y/400*2225 + 2613;
    int b = (y%19*3510 + a/25*319)/330%29;
    b = 148 - b - (y*5/4 + a - b)%7;
    return Date{Year{y}, Month{b/31}, Day{b%31 + 1}}; // Datum erzeugen
}
int main(int argc, const char *argv[] ) {
    /* Eingabe */
    int zahl {};
    if(argc > 1) {
        zahl = std::stoi(argv[1]);
    } else {
        std::cout << "Jahr? "; std::cin >> zahl;
    }
    /* Berechnung */
    Date date = ostern(zahl);  // implizite Konvertierung nach Year
    /* Ausgabe */
    std::cout << "Ostern: " << date << "\n";
}

Okt 23, 2024

lst-0294-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sP3W8jx6E 
class Year {
    int value_;                         // eigentlich intern verwendeter Typ
public:
    explicit Year(int v) : value_{v} {} // Typ wird Teil des Interface
    int value() { return value_; }      // auch bei der Rückgabe
};
int main() {
   Year year{ 2024 };                   // Typ int
   int val = year.value();              // passender Typ
}

Okt 23, 2024

lst-0311-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/T1ohsxbje 
#include <string>
#include <iostream>                    // ostream, cout
namespace plant {
    class Baum {
        std::string name_;
    public:
        explicit Baum(const std::string_view name) : name_{name} {}
        void print(std::ostream& os) const { os << name_; }
    };
    std::ostream& operator<<(std::ostream& os, const Baum& arg)
        { arg.print(os); return os; }
    using NadelBaum = Baum;            // für spätere Erweiterungen 
    using LaubBaum = Baum;             //  vorsorgen
    namespace beispielnamen {          // eingebetteter Namensraum
        std::string eicheName = "Eiche";
        std::string bucheName = "Buche";
        std::string tanneName = "Tanne";
    } // Ende namespace beispielnamen
} // Ende namespace plant

int main() {  // main darf nicht in einem Namespace stehen
    using namespace plant::beispielnamen; // alle Beispielnamen verfügbar machen
    plant::NadelBaum tanne{ tanneName };
    plant::LaubBaum eiche{ eicheName };
    tanne.print(std::cout); std::cout << "\n";
    using plant::operator<<;           // ohne geht 'cout << eiche' nicht
    std::cout << eiche << "\n";
}

Okt 23, 2024

lst-0322-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h5qond6db 
#include <iostream>                     // cout
class Keyboard {
    Keyboard(const Keyboard&) = delete; // keine Kopie
    const size_t nr_;                   // aktuelle Nummer
public:
    static inline size_t count_ = 0;    // zählt erzeugte Instanzen
    explicit Keyboard() : nr_{count_++} {
        std::cout << "  Keyboard().nr:"<<nr_<<"\n";
    }
};
Keyboard& getKeyboard() {
    std::cout << "  getKeyboard()\n";
    static Keyboard keyboard{};         // statische lokale Variable
    return keyboard;
}
void func() {
    std::cout << "kbFunc...\n";
    Keyboard& kbFunc = getKeyboard();
}
int main() {
    std::cout << "kbA...\n";
    Keyboard& kbA = getKeyboard();
    func();
    std::cout << "kbB...\n";
    Keyboard& kbB = getKeyboard();
    std::cout << "count:" << Keyboard::count_ << "\n";
}

Okt 23, 2024

lst-0262-book.cpp

// https://godbolt.org/z/PaG9nTs7s 
class Rect {
    int area_;         // private Daten

public:
    int x_, y_;
    void set(int x, int y) { x_=x; y_=y; area_=x_*y_; }
    int calc() { return area_; }
    Rect() = default;  // den Compiler einen Konstruktor generieren lassen
};
class Pow {
    int result_;       // private Daten; hält 'base' hoch 'exp'
public:
    int base_, exp_;
    void set(int b, int e) { /* ... */ }
    int calc() { return result_; }
    Pow() : result_{1},base_{1},exp_{1} {} // sinnvoll initialisieren
};

Okt 23, 2024

lst-0295-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r3xaPv5Mr 
class Year {
public:
    using value_type = int;             // Typalias einführen
    value_type value_;                  // eigentlich intern verwendeter Typ
public:
    explicit Year(value_type v) : value_{v} {}
    value_type value() { return value_; }
};
int main() {
   Year year{ 2024 };                   // hier auf Compilerkonvertierung zählen
   Year::value_type val = year.value(); // verwenden Sie ::
}

Okt 23, 2024

lst-0256-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/osM9ncPzr 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person(sview n, int a, sview o)
    {                   //                 (ERR)  Initialisierungsliste fehlt
        init(n, a, o);  //                 (ERR)  fragwürdiger »Initialisierungsaufruf«
    }
    void init(sview n, int a, sview o) {
      name_ = n; alter_ = a; ort_ = o;
    }
};

Okt 23, 2024

lst-0306-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8ejPs6zr6 
#include <vector>
struct Zahl {
    int wert_ = 0;
    Zahl() {} // Standardkonstruktor
    explicit Zahl(int w) : wert_{w} {}
};
int main() {
    std::vector<Zahl> zahlen{}; // okay: Zahl erfüllt die Bedingungen
    zahlen.push_back( Zahl{2} );
}

Okt 23, 2024

lst-0307-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vrdKPvh7f 
#include <set>
struct Zahl {
    int wert_ = 0;
    explicit Zahl(int w) : wert_{w} {}
};
bool operator<(const Zahl& links, const Zahl& rechts) {
    return links.wert_ < rechts.wert_;
}
int main() {
    std::set<Zahl> zahlen{};  // okay
    zahlen.insert( Zahl{3} ); // hier wird operator< gebraucht
}

Okt 23, 2024

lst-0317-book.cpp

// https://godbolt.org/z/cTYhMfo5W 
// modul.cpp
#include "modul.hpp"
static std::string PREFIX = "BAUM:";
static void printInfo(std::ostream& os) {
    os << "Autor: Torsten T. Will\n";
}
bool debug = false;
// Rest wie bisher

Okt 23, 2024

lst-0260-book.cpp

// https://godbolt.org/z/e6rqbq3bE 
#include <string>
#include <string_view>
using std::string; using std::string_view;

class Person { // eine Klasse beginnt mit privater Sichtbarkeit
    string name_;
    int alter_;
    string ort_;
public:  // alles ab hier darf von außen verwendet werden
    Person(string_view n, int a, string_view o)
      : name_{n}, alter_{a}, ort_{o} { }
    void drucke();
};

Okt 23, 2024

lst-0321-book.cpp

// https://godbolt.org/z/b9arcEMM1 
constinit auto SZ = 10*1000-1;                 // globale Variable
size_t autoincrement() {
    static constinit size_t i = 0;             // lokale statische Variable
    return i++;
}
class BraitenbergVehicle {
    inline static constinit size_t count_ = 0; // Klassenvariable
public:
    size_t id_;
    BraitenbergVehicle() : id_{++count_} {}
    ~BraitenbergVehicle() { --count_; }
};

Okt 23, 2024

lst-0294-book.cpp

// https://godbolt.org/z/sP3W8jx6E 
class Year {
    int value_;                         // eigentlich intern verwendeter Typ
public:
    explicit Year(int v) : value_{v} {} // Typ wird Teil des Interface
    int value() { return value_; }      // auch bei der Rückgabe
};
int main() {
   Year year{ 2024 };                   // Typ int
   int val = year.value();              // passender Typ
}

Okt 23, 2024

lst-0316-book.cpp

// https://godbolt.org/z/M6EnPT3Gr 
// modul.hpp
#include <string>
#include <iostream>
namespace plant {
    class Baum {
        std::string name_;
    public:
        explicit Baum(const std::string_view name);
        void print(std::ostream& os) const;
    };
    std::ostream& operator<<(std::ostream& os, const Baum& arg);
}
// modul.cpp
#include "modul.hpp"
namespace {  // anonymer Namensraum
    std::string PREFIX = "BAUM:";
    void printInfo(std::ostream& os) {
        os << "Autor: Torsten T. Will\n";
    }
}
bool debug = false;  // global, kein Namensraum
namespace plant {
    Baum::Baum(const std::string_view name)
        : name_{name} {}
    void Baum::print(std::ostream& os) const {
        os << PREFIX << name_;
    }
    std::ostream& operator<<(std::ostream& os, const Baum& arg) {
        if(debug) printInfo(os);
        arg.print(os); return os;
    }
}
// main.cpp
#include "modul.hpp"
int main() {
    plant::Baum x{"x"};
    x.print(std::cout); std::cout << "\n";
}

Okt 23, 2024

lst-0324-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/115M1csEE 
#include <iostream>
namespace mylib {
    namespace v1 {
        int version() { return 1; }
    }
    inline namespace v2 { // aktuelle Version
        int version() { return 2; }
    }
}

int main() {
    std::cout << "Version " << mylib::version() << "\n";     // Ausgabe: 2
    std::cout << "Version " << mylib::v1::version() << "\n"; // Ausgabe: 1
    std::cout << "Version " << mylib::v2::version() << "\n"; // Ausgabe: 2
}

Okt 23, 2024

lst-0334-book.cpp

// https://godbolt.org/z/WTWxYa3rd 
class Widget {
    unsigned x = 0, y = 0, w = 0, h = 0; // zum Beispiel
public:
    unsigned getLeft() const;
    unsigned getTop() const;
    unsigned getRight() const;
    unsigned getBottom() const;
    void setWidth(unsigned w);
    void setHeight(unsigned h);
};

Okt 23, 2024

lst-0311-book.cpp

// https://godbolt.org/z/T1ohsxbje 
#include <string>
#include <iostream>                    // ostream, cout
namespace plant {
    class Baum {
        std::string name_;
    public:
        explicit Baum(const std::string_view name) : name_{name} {}
        void print(std::ostream& os) const { os << name_; }
    };
    std::ostream& operator<<(std::ostream& os, const Baum& arg)
        { arg.print(os); return os; }
    using NadelBaum = Baum;            // für spätere Erweiterungen …
    using LaubBaum = Baum;             // … vorsorgen
    namespace beispielnamen {          // eingebetteter Namensraum
        std::string eicheName = "Eiche";
        std::string bucheName = "Buche";
        std::string tanneName = "Tanne";
    } // Ende namespace beispielnamen
} // Ende namespace plant

int main() {  // main darf nicht in einem Namespace stehen
    using namespace plant::beispielnamen; // alle Beispielnamen verfügbar machen
    plant::NadelBaum tanne{ tanneName };
    plant::LaubBaum eiche{ eicheName };
    tanne.print(std::cout); std::cout << "\n";
    using plant::operator<<;           // ohne geht 'cout << eiche' nicht
    std::cout << eiche << "\n";
}

Okt 23, 2024

lst-0296-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vjTWjfKKz 
#include <vector>
#include <set>
#include <iostream>
using std::vector; using std::set; using std::cout;
using vector_t = vector<unsigned long long>; // Ihr eigener Typalias
int main() {
    vector_t huge{ 12ULL, 10'000'000'000ULL, 9ULL, 0ULL,  };
    vector_t::size_type sz = huge.size();
    vector_t::value_type uiuiui = huge[1];
    for(vector_t::iterator it = huge.begin(); it != huge.end(); ++it)
        *it *= 2; // verdoppeln
    /* sortieren per set */
    set<vector_t::value_type> sortiert{huge.begin(), huge.end()};
    for(vector_t::value_type val : sortiert)
        cout << val << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0301-book.cpp

// https://godbolt.org/z/hT8o3dqrK 
#include <vector>
#include <set>
#include <iostream> // cout
#include <concepts> // integral
#include <iterator> // output_iterator, input_iterator
using namespace std;
using vector_t = vector<unsigned long long>;        // Ihr eigener Typalias
int main() {
  vector_t huge{ 12ULL, 10000000000ULL, 9ULL, 0ULL,  };
  unsigned_integral auto sz = huge.size();
  unsigned_integral auto uiuiui = huge[1];
  signed_integral auto meh = huge[1];               //             (ERR)  Concept nicht erfüllt
  input_or_output_iterator auto itx = huge.begin(); // Concept ohne Parameter
  for(output_iterator<unsigned long long> auto i=huge.begin();
      it!=huge.end(); ++it)
    *it *= 2; // verdoppeln
  /* sortieren per set */
  set sortiert(huge.begin(), huge.end());           // set<vector_t::value_type>
  for(const unsigned_integral auto& val : sortiert)
    cout << val << " ";
  cout << "\n";
}

Okt 23, 2024

lst-0334-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WTWxYa3rd 
class Widget {
    unsigned x = 0, y = 0, w = 0, h = 0; // zum Beispiel
public:
    unsigned getLeft() const;
    unsigned getTop() const;
    unsigned getRight() const;
    unsigned getBottom() const;
    void setWidth(unsigned w);
    void setHeight(unsigned h);
};

Okt 23, 2024

lst-0339-book.cpp

// https://godbolt.org/z/q3Ga7hTGa 
#include <vector>
namespace {                         // anonymer Namensraum für Konstanten
    const unsigned DATA_SIZE = 100; /* Anzahl Elemente in Data */
    const double LIMIT = 999.999;   /* Maxwert bei Initialisierung */
};
std::vector<int> createData() {
    std::vector<int> result(DATA_SIZE);
    double currVal = 1.0;
    for(auto &elem : result) {
        elem = currVal;
        currVal *= 2;         // nächster Wert ist größer
        if(currVal > LIMIT) {
            currVal = LIMIT;  // kein Wert darf größer sein
        }
    }
    return result;
}

Okt 23, 2024

lst-0301-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hT8o3dqrK 
#include <vector>
#include <set>
#include <iostream> // cout
#include <concepts> // integral
#include <iterator> // output_iterator, input_iterator
using namespace std;
using vector_t = vector<unsigned long long>;        // Ihr eigener Typalias
int main() {
  vector_t huge{ 12ULL, 10000000000ULL, 9ULL, 0ULL,  };
  unsigned_integral auto sz = huge.size();
  unsigned_integral auto uiuiui = huge[1];
  signed_integral auto meh = huge[1];               //             (ERR)  Concept nicht erfüllt
  input_or_output_iterator auto itx = huge.begin(); // Concept ohne Parameter
  for(output_iterator<unsigned long long> auto i=huge.begin();
      it!=huge.end(); ++it)
    *it *= 2; // verdoppeln
  /* sortieren per set */
  set sortiert(huge.begin(), huge.end());           // set<vector_t::value_type>
  for(const unsigned_integral auto& val : sortiert)
    cout << val << " ";
  cout << "\n";
}

Okt 23, 2024

lst-0339-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/q3Ga7hTGa 
#include <vector>
namespace {                         // anonymer Namensraum für Konstanten
    const unsigned DATA_SIZE = 100; /* Anzahl Elemente in Data */
    const double LIMIT = 999.999;   /* Maxwert bei Initialisierung */
};
std::vector<int> createData() {
    std::vector<int> result(DATA_SIZE);
    double currVal = 1.0;
    for(auto &elem : result) {
        elem = currVal;
        currVal *= 2;         // nächster Wert ist größer
        if(currVal > LIMIT) {
            currVal = LIMIT;  // kein Wert darf größer sein
        }
    }
    return result;
}

Okt 23, 2024

lst-0306-book.cpp

// https://godbolt.org/z/8ejPs6zr6 
#include <vector>
struct Zahl {
    int wert_ = 0;
    Zahl() {} // Standardkonstruktor
    explicit Zahl(int w) : wert_{w} {}
};
int main() {
    std::vector<Zahl> zahlen{}; // okay: Zahl erfüllt die Bedingungen
    zahlen.push_back( Zahl{2} );
}

Okt 23, 2024

lst-0302-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ro6fdsvT9 
#include <vector>
#include <iostream> // cout
using std::vector; using std::cout;
int main() {
    vector data{ 12, 100, -1, 0,  };    // vector<int>
    for(auto& val : data)
        val *= 2; // verdoppeln
    for(const auto val : data)
        cout << val << " ";
    cout << "\n";
}

Okt 23, 2024

lst-0317-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cTYhMfo5W 
// modul.cpp
#include "modul.hpp"
static std::string PREFIX = "BAUM:";
static void printInfo(std::ostream& os) {
    os << "Autor: Torsten T. Will\n";
}
bool debug = false;
// Rest wie bisher

Okt 23, 2024

lst-0259-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zrE55vWq3 
#include <string>
#include <string_view>
using std::string; using std::string_view;

struct Person {
private: // alles ab hier kann von außen nicht benutzt werden
    string name_;
    int alter_;
    string ort_;
public:  // alles ab hier darf von außen verwendet werden
    Person(string_view n, int a, string_view o)
      : name_{n}, alter_{a}, ort_{o} { }
    void drucke();
};

Okt 23, 2024

lst-0261-book.cpp

// https://godbolt.org/z/Pr76Y55P4 
class Rect {
    int area_;  // private Daten
public:
    int x_, y_;
    void set(int x, int y) { x_=x; y_=y; area_=x_*y_; }
    int calc() { return area_; }
};

Okt 23, 2024

lst-0261-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Pr76Y55P4 
class Rect {
    int area_;  // private Daten
public:
    int x_, y_;
    void set(int x, int y) { x_=x; y_=y; area_=x_*y_; }
    int calc() { return area_; }
};

Okt 23, 2024

lst-0321-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/b9arcEMM1 
constinit auto SZ = 10*1000-1;                 // globale Variable
size_t autoincrement() {
    static constinit size_t i = 0;             // lokale statische Variable
    return i++;
}
class BraitenbergVehicle {
    inline static constinit size_t count_ = 0; // Klassenvariable
public:
    size_t id_;
    BraitenbergVehicle() : id_{++count_} {}
    ~BraitenbergVehicle() { --count_; }
};

Okt 23, 2024

lst-0251-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vzneMWW9r 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;
struct Person {
    string name_ = "kein Name";
    int alter_ = -1;
    string ort_ = "kein Ort";
    Person() {}
    Person(sview n, int a, sview o)
      : name_{n}, alter_{a}, ort_{o} { }
    Person(sview n, int a)
      : name_{n}, alter_{a} { }
    Person(sview n)
      : name_{n} { }
};

Okt 23, 2024

lst-0226-book.cpp

// https://godbolt.org/z/e9Wshbx3q 
Person otto1 {"Otto", 45, "Kassel" }; // korrekt
Person otto2 {"Kassel", 45, "Otto" }; // oje, vertauscht, und keiner merkt's
Person hans { .name_ = "Hans", .alter_ = 23, .ort_ = "Berlin" }; // okay
Person willi { .name_ = "Willi", .alter_ = 48  }; // okay, nicht alle angegeben
Person karl { "Karl", .alter_ = 53  }; //             (ERR)  alle designiert oder keiner
Person paul { .alter_ = 34, .name_ = "Paul", .ort = "Bonn" }; //             (ERR)  vertauscht
Person pit(.name_="Pit", .alter_=34, .ort_="Wyk"); //             (ERR)  nicht mit runden Klammern

Okt 23, 2024

lst-0219-book.cpp

// https://godbolt.org/z/5Tfr6xxa5 
#include <string>
#include <string_view>
#include <vector>
#include <map> // multimap
namespace qw::impl_multimap {
using std::vector; using std::multimap; 
using std::string; using std::string_view;
class index_impl {
    vector<string> entries;
    multimap<string,size_t> qindex;
public:
    void add(string_view normalized, string_view original);
    string getBestMatch(string_view normalized) const;
    size_t size() const {
        return entries.size();
    }
private:
    vector<string> qgramify(string_view normalized) const;
    static constexpr size_t Q = 3;
    static const std::string PREFIX;
    static const std::string SUFFIX;
public: // test interface
    vector<string> _qgramify(string_view n) const { return qgramify(n); }
    static size_t _q() { return Q; }
    static std::string _prefix() { return PREFIX; }
    static std::string _suffix() { return SUFFIX; }
};
} // namespace qw::impl_multimap

Okt 23, 2024

lst-0255-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vb1Wsr5d3 
#include <vector>
#include <string>
#include <string_view>
#include <iostream>
using std::string; using std::cout; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    // fungiert als Defaultkonstruktor:
    Person(sview n = "N.N.", int a = 18, sview o = "Berlin")
      : name_(n), alter_(a), ort_(o) { }
};

int main() {
    std::vector<Person> personen{}; // zunächst leer
    personen.resize(5); // auf fünf »leere« Personen erweitern
    cout << personen[3].ort_ << "\n"; // Ausgabe: Berlin
}

Okt 23, 2024

lst-0242-book.cpp

// https://godbolt.org/z/bEdfWqqnn 
// Ausschnitt …
    std::ostream& drucke(std::ostream& os);
};
std::ostream& Person::drucke(std::ostream& os) {
    return os << format("{} ({}) aus {}", p.name_, p.alter_,  p.ort_);
}
std::ostream& operator<<(std::ostream& os, Person p) {
    return p.drucke(os);
}
int main() {
    Person paul {"Paul", 23, "Dresden"};
    cout << "Sie sind " << paul << ", richtig?\n";
}

Okt 23, 2024

lst-0255-book.cpp

// https://godbolt.org/z/vb1Wsr5d3 
#include <vector>
#include <string>
#include <string_view>
#include <iostream>
using std::string; using std::cout; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    // fungiert als Defaultkonstruktor:
    Person(sview n = "N.N.", int a = 18, sview o = "Berlin")
      : name_(n), alter_(a), ort_(o) { }
};

int main() {
    std::vector<Person> personen{}; // zunächst leer
    personen.resize(5); // auf fünf »leere« Personen erweitern
    cout << personen[3].ort_ << "\n"; // Ausgabe: Berlin
}

Okt 23, 2024

lst-0211-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sz9hxKozf 
#include <iostream>            // cout, cerr
#include <vector>
#include <string>
#include <fstream>             // ifstream
#include <stdexcept>           // invalid_argument
using std::vector; using std::string; using std::cout; using std::ifstream;
size_t zaehleWoerter(const string& filename) { // 0 oder größer
    std::ifstream file{};      // ungeöffnet erzeugen
    // anmelden für Exceptions:
    file.exceptions(ifstream::failbit | ifstream::badbit);
    file.open(filename);       // könnte eine Exception auslösen
    size_t count = 0;
    string wort;
    file.exceptions(ifstream::badbit); // EOF keine Exception mehr
    while(!file.eof()) {       // noch nicht am Ende?
        file >> wort;   ++count;
    }
    return count-1;            // 1: am EOF wurde noch ein Wort gelesen
}
void process(const vector<string>& args) {
    if(args.size() == 0) {     // process erwartet Parameter
        throw std::invalid_argument{"Kommandozeilenarg. fehlt"}; // auslösen
    } else {
        for(const string filename : args) {
            cout << filename << ": " << zaehleWoerter(filename) << std::endl;
        }
    }
}
int main(int argc, const char* argv[]) {
    try {                                      // Block mit Fehlerbehandlungen
        process(
          vector<string>{argv+1, argv+argc} ); // const char*[] nach vector<string>
        return 0;
    } catch(std::exception &exc) {  // Fehlerbehandlung
        std::cerr << "Es trat ein Fehler auf: " << exc.what() << "\n";
        return 1;
    }
}

Okt 23, 2024

lst-0216-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TsP33njar 
#include <iostream>
#include <stdexcept> // exception

int main() {
    try {
        //  Ihr sonstiger Code 
    } catch(std::exception& exc) {
        std::cerr << "main: " << exc.what() << "\n";
    }
}

Okt 23, 2024

lst-0243-book.cpp

// https://godbolt.org/z/zf9Tc4ahs 
#include <string>
#include <iostream>    // ostream

using std::string; using std::ostream;

struct Person {
  string name_;
  int alter_;
  string ort_;
  ostream& drucke(ostream& os) {  // Methode inline definiert
    return os << format("{} ({}) aus {}", p.name_, p.alter_,  p.ort_);
  }
};

Okt 23, 2024

lst-0252-book.cpp

// https://godbolt.org/z/83efx7Gex 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;

    Person(sview n, int a, sview o)                   // delegierter Konstruktor
      : name_(n), alter_(a), ort_(o) { }              // … ausimplementiert
    Person() : Person{"kein Name",-1,"kein Ort"} { }  // delegierend
    Person(sview n, int a) : Person{n, a, "kein Ort"} { } // delegierend
    Person(sview n) : Person{n, -1, "kein Ort"} { }       // delegierend
};

Okt 23, 2024

lst-0221-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gvcj6hhYf 
#include <cstdlib>  // EXIT_SUCCESS
#include <iostream> // cout
#include <vector>
#include <string>
#include "qwort/qwort.hpp"
using std::cout; using std::vector; using std::string;
int main(int argc, const char* argv[]) {
    cout << "qwort version " << qw::version() << "\n";

    /* Index bauen */
    qw::index myindex{};

    /* - Demodaten */
    myindex.add("Deutschland");
    myindex.add("Griechenland");

    /* Abfragen erzeugen */
    vector<string> args(argv+1, argv+argc); // iteratorbasierte Initialisierung
    for(auto &querystring : args) {
        cout << "Suche '" << querystring << "'... ";
        const auto match = myindex.getBestMatch(querystring);
        cout << match << "\n";
    }
    return EXIT_SUCCESS;
}

Okt 23, 2024

lst-0256-book.cpp

// https://godbolt.org/z/osM9ncPzr 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person(sview n, int a, sview o)
    {                   //                 (ERR)  Initialisierungsliste fehlt
        init(n, a, o);  //                 (ERR)  fragwürdiger »Initialisierungsaufruf«
    }
    void init(sview n, int a, sview o) {
      name_ = n; alter_ = a; ort_ = o;
    }
};

Okt 23, 2024

lst-0236-book.cpp

// https://godbolt.org/z/hEvqWqqc6 
int wert = 5;                         // globale Variable
struct Wrap {
    int wert = 3;                     // Datenfeld
    void setze(int wert) {            // Parameter
        this->wert = wert + ::wert;
    }
};

Okt 23, 2024

lst-0236-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hEvqWqqc6 
int wert = 5;                         // globale Variable
struct Wrap {
    int wert = 3;                     // Datenfeld
    void setze(int wert) {            // Parameter
        this->wert = wert + ::wert;
    }
};

Okt 23, 2024

lst-0218-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zbcdd1jha 
#include "qwort/qwort.hpp" // selbst
#include <map>
#include <algorithm>       // transform
#include <cctype>          // toupper
#include "impl_multimap.hpp"
using std::map; using std::string;

namespace qw {
    int version() {
        return 1;
    }
    // Verwaltung
    index::index()
        : pimpl{ new index_impl{} }
        { }
    index::~index() noexcept = default;
    index::index(index&&) noexcept = default;
    // Schnittstelle
    void index::add(const string &arg) {
        pimpl->add(normalize(arg), arg);
    }
    size_t index::size() const {
        return pimpl->size();
    }
    string index::getBestMatch(const string& query) const {
        return pimpl->getBestMatch(normalize(query));
    }
    string index::normalize(string str) const {
        using namespace std; // begin, end
        transform(begin(str), end(str), begin(str), [](char c) {
                return ::isalpha(c) ? ::toupper(c) : '#';
            });
        return str;
    }
} // namespace qw

Okt 23, 2024

lst-0226-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/e9Wshbx3q 
Person otto1 {"Otto", 45, "Kassel" }; // korrekt
Person otto2 {"Kassel", 45, "Otto" }; // oje, vertauscht, und keiner merkt's
Person hans { .name_ = "Hans", .alter_ = 23, .ort_ = "Berlin" }; // okay
Person willi { .name_ = "Willi", .alter_ = 48  }; // okay, nicht alle angegeben
Person karl { "Karl", .alter_ = 53  }; //             (ERR)  alle designiert oder keiner
Person paul { .alter_ = 34, .name_ = "Paul", .ort = "Bonn" }; //             (ERR)  vertauscht
Person pit(.name_="Pit", .alter_=34, .ort_="Wyk"); //             (ERR)  nicht mit runden Klammern

Okt 23, 2024

lst-0232-book.cpp

// https://godbolt.org/z/M1ozTorEz 
#include <string>
#include <iostream>
#include <format>
using std::string; using std::cout; using std::format;
struct Person {
  string name_;
  int alter_;
  string ort_;
  void drucke();            // Funktion als Methode des Typs
};
void Person::drucke() {     // Name der Methode wird um Person:: erweitert
  cout << format("{} ({}) aus {}\n",
    name_, alter_, ort_);   // in einer Methode können Sie direkt auf Felder zugreifen
}
int main() {
  Person otto {"Otto", 45, "Kassel" };
  otto.drucke();            // Aufruf der Methode für eine Variable des Typs
}

Okt 23, 2024

lst-0253-book.cpp

// https://godbolt.org/z/Exh4PnMTE 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;

    Person(sview n = "N.N.", int a = 18, sview o = "Berlin")
      : name_(n), alter_(a), ort_(o) { }
};

Okt 23, 2024

lst-0218-book.cpp

// https://godbolt.org/z/zbcdd1jha 
#include "qwort/qwort.hpp" // selbst
#include <map>
#include <algorithm>       // transform
#include <cctype>          // toupper
#include "impl_multimap.hpp"
using std::map; using std::string;

namespace qw {
    int version() {
        return 1;
    }
    // Verwaltung
    index::index()
        : pimpl{ new index_impl{} }
        { }
    index::~index() noexcept = default;
    index::index(index&&) noexcept = default;
    // Schnittstelle
    void index::add(const string &arg) {
        pimpl->add(normalize(arg), arg);
    }
    size_t index::size() const {
        return pimpl->size();
    }
    string index::getBestMatch(const string& query) const {
        return pimpl->getBestMatch(normalize(query));
    }
    string index::normalize(string str) const {
        using namespace std; // begin, end
        transform(begin(str), end(str), begin(str), [](char c) {
                return ::isalpha(c) ? ::toupper(c) : '#';
            });
        return str;
    }
} // namespace qw

Okt 23, 2024

lst-0239-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bjWKjaeaK 
// Ausschnitt. Person wie zuvor
void Person::drucke(std::ostream& os) {
    os << format("{} ({}) aus {}", name_, alter_,  ort_);
}
int main() {
    Person karl {"Karl", 12, "Stetten"};
    karl.drucke(cout);        // auf dem Bildschirm
    cout << "\n";
    std::ofstream datei {"personen.txt"};
    karl.drucke(datei);       // in eine Datei
    // automatischer Test:
    std::ostringstream oss{}; // schreibt in einen string
    karl.drucke(oss);
    if(oss.str() == "Karl (12) aus Stetten") {
        cout << "ok\n";
    } else {
        cout << "Fehler in Person::drucke!\n";
        return 1;             // Fehler nach außen weiterleiten
    }
}

Okt 23, 2024

lst-0253-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Exh4PnMTE 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;

    Person(sview n = "N.N.", int a = 18, sview o = "Berlin")
      : name_(n), alter_(a), ort_(o) { }
};

Okt 23, 2024

lst-0228-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YYfxMdfP8 
Person erzeuge(string name, int alter, string ort) {
    return Person{name, alter, ort};       // direkt zurückgegeben
}
int main() {
    drucke(erzeuge("Otto", 45, "Kassel")); // Rückgabe direkt verwendet
}

Okt 23, 2024

lst-0222-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8YqoTEx58 
#include <string>
#include <iostream>                     // cout
#include <format>
using std::string; using std::cout; using std::format;
struct Person {                         // definiert den neuen Typ Person
    string name_;
    int alter_;
    string ort_;
};                                      // abschließendes Semikolon
void drucke(Person p) {                 // ganze Person als ein Parameter
    cout << format("{} ({}) aus {}\n",
      p.name_, p.alter_, p.ort_);       // Zugriff per Punkt
}
int main() {
    Person otto {"Otto", 45, "Kassel" }; // Initialisierung
    drucke(otto);                        // Aufruf als Einheit
}

Okt 23, 2024

lst-0216-book.cpp

// https://godbolt.org/z/TsP33njar 
#include <iostream>
#include <stdexcept> // exception

int main() {
    try {
        // … Ihr sonstiger Code …
    } catch(std::exception& exc) {
        std::cerr << "main: " << exc.what() << "\n";
    }
}

Okt 23, 2024

lst-0227-book.cpp

// https://godbolt.org/z/xnT7voqen 
// Ausschnitt
Person erzeuge(string name, int alter, string ort) { // Rückgabetyp
    Person result {name, alter, ort};
    return result;
}
int main() {
    Person otto = erzeuge("Otto", 45, "Kassel"); // Rückgabe speichern
    drucke(otto);
}

Okt 23, 2024

lst-0215-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/67cd5bhhE 
#include <string>
#include <iostream> // cout
using std::string; using std::to_string; using std::cout;
void fehlerAusloesen(int fehlerfall) {
   try {
       if(fehlerfall < 10) throw (int)fehlerfall;
       else if(fehlerfall < 20) throw 1.0/(fehlerfall-10.0);
       else throw string{"Fehler " + to_string(fehlerfall)};
   } catch(int eval) {
       cout << "int-fehler: " << eval << "\n";
   } catch(double eval) {
       cout << "double-fehler: " << eval << "\n";
   } catch(string eval) {
       cout << "string-fehler: " << eval << "\n";
   }
}
int main() {
    fehlerAusloesen(3);  // int-fehler: 3
    fehlerAusloesen(14); // Ausgabe: double-fehler: 0.25
    fehlerAusloesen(50); // Ausgabe: string-fehler: Fehler 50
}

Okt 23, 2024

lst-0252-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/83efx7Gex 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;

    Person(sview n, int a, sview o)                   // delegierter Konstruktor
      : name_(n), alter_(a), ort_(o) { }              //  ausimplementiert
    Person() : Person{"kein Name",-1,"kein Ort"} { }  // delegierend
    Person(sview n, int a) : Person{n, a, "kein Ort"} { } // delegierend
    Person(sview n) : Person{n, -1, "kein Ort"} { }       // delegierend
};

Okt 23, 2024

lst-0223-book.cpp

// https://godbolt.org/z/jPqn7c3T8 
#include <memory>                      // shared_ptr
#include <vector>                      // vector
struct Mitarbeiter;                    // Klassendeklaration
struct Chef;                           // Klassendeklaration
struct Mitarbeiter {                   // Klassendefinition
    std::shared_ptr<Chef> chef_;       // Zeiger auf Chef
    void print() const;                // Methodendeklaration
};
struct Chef {                           // Definition
    std::vector<std::shared_ptr<Mitarbeiter>> mitarbeiter_; // Zeiger auf Mitarbeiter
    void print() const;                 // Methodendeklaration
};
void Mitarbeiter::print() const {       // Methodendefinition
    // …
}
void Chef::print() const {              // Methodendefinition
    // …
}

Okt 23, 2024

lst-0250-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cqoTsWbhW 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person();                         // Konstruktor ohne Argumente
    Person(sview n, int a, sview o);  // Konstruktor mit drei Argumenten
    Person(sview n, int a);           // Konstruktor mit zwei Argumenten
    Person(sview n);                  // Konstruktor mit einem Argument
};

Person::Person() 
  : name_{"kein Name"}, alter_{-1}, ort_{"kein Ort"} { } 
Person::Person(sview n, int a, sview o) 
  : name_{n}, alter_{a}, ort_{o} { } 
Person::Person(sview n, int a)
  : name_{n}, alter_{a}, ort_{"kein Ort"} { }
Person::Person(sview n)
  : name_{n}, alter_{-1}, ort_{"kein Ort"} { }

Okt 23, 2024

lst-0220-book.cpp

// https://godbolt.org/z/41sPszG1G 
#include "impl_multimap.hpp" // Header zu dieser Datei
#include <map>
#include <string>
#include <string_view>

namespace qw::impl_multimap {

using std::vector; using std::multimap; using std::map; using std::string;
using std::string_view; using namespace std::literals::string_literals;

void index_impl::add(string_view normalized, string_view original) {
    /* TODO: Vorhandensein in 'entries' prüfen */
    const auto pos = entries.size(); // Index des neuen Eintrags
    entries.push_back(string(original));
    auto qgrams = qgramify(normalized);
    for(const auto& qgram : qgrams) {
        qindex.insert( make_pair(qgram, pos) );
    }
}
string index_impl::getBestMatch(string_view normalized) const {
    auto qgrams = qgramify(normalized);
    /* hits speichert, welche Wörter wie oft getroffen wurden */
    map<size_t, size_t> hits; /* 'entries-index' zu 'hit-count' */
    size_t maxhits = 0z; /* immer: max(hits.second) */
    for(const auto& qgram : qgrams) {
        auto [beg, end] = qindex.equal_range(qgram);
        for(auto it=beg; it!=end; ++it) {
            hits[it->second] += 1z; /* hit-count des Eintrags */
            if(hits[it->second] > maxhits) { /* max-Suche einfacher */
                maxhits = hits[it->second];
            }
        }
    }
    /* Suche ersten Eintrag mit maxhits. Bessere Implementierung mit PrioQueue möglich */
    for(auto const &hit : hits) {
        if(hit.second == maxhits) {
            return entries[hit.first];
        }
    }
    /* nur erreicht, wenn entries leer ist */
    return ""s;
}
const string index_impl::PREFIX = string(Q-1, '^');
const string index_impl::SUFFIX = string(Q-1, '$');

vector<string> index_impl::qgramify(string_view normalized) const {
    auto word = PREFIX + string(normalized)+SUFFIX; /* Trick für bessere QGramme */
    vector<string> result {};
    auto left = word.cbegin();
    auto right = std::next(word.cbegin(), Q); /* okay: |"^^"|+|"$$"| => 3 */
    for( ; right <= word.end(); ++left, ++right) {
        result.emplace_back(left, right);
    }
    return result;
}
} // namespace qw::impl_multimap

Okt 23, 2024

lst-0223-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jPqn7c3T8 
#include <memory>                      // shared_ptr
#include <vector>                      // vector
struct Mitarbeiter;                    // Klassendeklaration
struct Chef;                           // Klassendeklaration
struct Mitarbeiter {                   // Klassendefinition
    std::shared_ptr<Chef> chef_;       // Zeiger auf Chef
    void print() const;                // Methodendeklaration
};
struct Chef {                           // Definition
    std::vector<std::shared_ptr<Mitarbeiter>> mitarbeiter_; // Zeiger auf Mitarbeiter
    void print() const;                 // Methodendeklaration
};
void Mitarbeiter::print() const {       // Methodendefinition
    // 
}
void Chef::print() const {              // Methodendefinition
    // 
}

Okt 23, 2024

lst-0239-book.cpp

// https://godbolt.org/z/bjWKjaeaK 
// Ausschnitt. Person wie zuvor
void Person::drucke(std::ostream& os) {
    os << format("{} ({}) aus {}", name_, alter_,  ort_);
}
int main() {
    Person karl {"Karl", 12, "Stetten"};
    karl.drucke(cout);        // auf dem Bildschirm
    cout << "\n";
    std::ofstream datei {"personen.txt"};
    karl.drucke(datei);       // in eine Datei
    // automatischer Test:
    std::ostringstream oss{}; // schreibt in einen string
    karl.drucke(oss);
    if(oss.str() == "Karl (12) aus Stetten") {
        cout << "ok\n";
    } else {
        cout << "Fehler in Person::drucke!\n";
        return 1;             // Fehler nach außen weiterleiten
    }
}

Okt 23, 2024

lst-0215-book.cpp

// https://godbolt.org/z/67cd5bhhE 
#include <string>
#include <iostream> // cout
using std::string; using std::to_string; using std::cout;
void fehlerAusloesen(int fehlerfall) {
   try {
       if(fehlerfall < 10) throw (int)fehlerfall;
       else if(fehlerfall < 20) throw 1.0/(fehlerfall-10.0);
       else throw string{"Fehler " + to_string(fehlerfall)};
   } catch(int eval) {
       cout << "int-fehler: " << eval << "\n";
   } catch(double eval) {
       cout << "double-fehler: " << eval << "\n";
   } catch(string eval) {
       cout << "string-fehler: " << eval << "\n";
   }
}
int main() {
    fehlerAusloesen(3);  // int-fehler: 3
    fehlerAusloesen(14); // Ausgabe: double-fehler: 0.25
    fehlerAusloesen(50); // Ausgabe: string-fehler: Fehler 50
}

Okt 23, 2024

lst-0220-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/41sPszG1G 
#include "impl_multimap.hpp" // Header zu dieser Datei
#include <map>
#include <string>
#include <string_view>

namespace qw::impl_multimap {

using std::vector; using std::multimap; using std::map; using std::string;
using std::string_view; using namespace std::literals::string_literals;

void index_impl::add(string_view normalized, string_view original) {
    /* TODO: Vorhandensein in 'entries' prüfen */
    const auto pos = entries.size(); // Index des neuen Eintrags
    entries.push_back(string(original));
    auto qgrams = qgramify(normalized);
    for(const auto& qgram : qgrams) {
        qindex.insert( make_pair(qgram, pos) );
    }
}
string index_impl::getBestMatch(string_view normalized) const {
    auto qgrams = qgramify(normalized);
    /* hits speichert, welche Wörter wie oft getroffen wurden */
    map<size_t, size_t> hits; /* 'entries-index' zu 'hit-count' */
    size_t maxhits = 0z; /* immer: max(hits.second) */
    for(const auto& qgram : qgrams) {
        auto [beg, end] = qindex.equal_range(qgram);
        for(auto it=beg; it!=end; ++it) {
            hits[it->second] += 1z; /* hit-count des Eintrags */
            if(hits[it->second] > maxhits) { /* max-Suche einfacher */
                maxhits = hits[it->second];
            }
        }
    }
    /* Suche ersten Eintrag mit maxhits. Bessere Implementierung mit PrioQueue möglich */
    for(auto const &hit : hits) {
        if(hit.second == maxhits) {
            return entries[hit.first];
        }
    }
    /* nur erreicht, wenn entries leer ist */
    return ""s;
}
const string index_impl::PREFIX = string(Q-1, '^');
const string index_impl::SUFFIX = string(Q-1, '$');

vector<string> index_impl::qgramify(string_view normalized) const {
    auto word = PREFIX + string(normalized)+SUFFIX; /* Trick für bessere QGramme */
    vector<string> result {};
    auto left = word.cbegin();
    auto right = std::next(word.cbegin(), Q); /* okay: |"^^"|+|"$$"| => 3 */
    for( ; right <= word.end(); ++left, ++right) {
        result.emplace_back(left, right);
    }
    return result;
}
} // namespace qw::impl_multimap

Okt 23, 2024

lst-0227-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xnT7voqen 
// Ausschnitt
Person erzeuge(string name, int alter, string ort) { // Rückgabetyp
    Person result {name, alter, ort};
    return result;
}
int main() {
    Person otto = erzeuge("Otto", 45, "Kassel"); // Rückgabe speichern
    drucke(otto);
}

Okt 23, 2024

lst-0219-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5Tfr6xxa5 
#include <string>
#include <string_view>
#include <vector>
#include <map> // multimap
namespace qw::impl_multimap {
using std::vector; using std::multimap; 
using std::string; using std::string_view;
class index_impl {
    vector<string> entries;
    multimap<string,size_t> qindex;
public:
    void add(string_view normalized, string_view original);
    string getBestMatch(string_view normalized) const;
    size_t size() const {
        return entries.size();
    }
private:
    vector<string> qgramify(string_view normalized) const;
    static constexpr size_t Q = 3;
    static const std::string PREFIX;
    static const std::string SUFFIX;
public: // test interface
    vector<string> _qgramify(string_view n) const { return qgramify(n); }
    static size_t _q() { return Q; }
    static std::string _prefix() { return PREFIX; }
    static std::string _suffix() { return SUFFIX; }
};
} // namespace qw::impl_multimap

Okt 23, 2024

lst-0251-book.cpp

// https://godbolt.org/z/vzneMWW9r 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;
struct Person {
    string name_ = "kein Name";
    int alter_ = -1;
    string ort_ = "kein Ort";
    Person() {}
    Person(sview n, int a, sview o)
      : name_{n}, alter_{a}, ort_{o} { }
    Person(sview n, int a)
      : name_{n}, alter_{a} { }
    Person(sview n)
      : name_{n} { }
};

Okt 23, 2024

lst-0217-book.cpp

// https://godbolt.org/z/7nasGjGq6 
#ifndef QWORT_H // Header-Guard
#define QWORT_H
#include <string>
#include <memory> // unique_ptr
namespace qw { // Namensraum der Bibliothek
    int version();
    namespace impl_multimap {
        class index_impl;
    }
    class index {
        using index_impl = impl_multimap::index_impl;
    public:
        index();
        ~index() noexcept; // wird für pimpl benötigt
        index(const index&) = default;
        index(index&&) noexcept;
        index& operator=(const index&) = default;
        index& operator=(index&&) = default;
    public:
        void add(const std::string &arg);
        size_t size() const;
        std::string getBestMatch(const std::string& query) const;
    public:          // public für Tests
        std::string normalize(std::string arg) const;
    private:
        const std::unique_ptr<index_impl> pimpl;
    };
} // namespace qw
#endif // Header-Guard

Okt 23, 2024

lst-0232-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M1ozTorEz 
#include <string>
#include <iostream>
#include <format>
using std::string; using std::cout; using std::format;
struct Person {
  string name_;
  int alter_;
  string ort_;
  void drucke();            // Funktion als Methode des Typs
};
void Person::drucke() {     // Name der Methode wird um Person:: erweitert
  cout << format("{} ({}) aus {}\n",
    name_, alter_, ort_);   // in einer Methode können Sie direkt auf Felder zugreifen
}
int main() {
  Person otto {"Otto", 45, "Kassel" };
  otto.drucke();            // Aufruf der Methode für eine Variable des Typs
}

Okt 23, 2024

lst-0243-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zf9Tc4ahs 
#include <string>
#include <iostream>    // ostream

using std::string; using std::ostream;

struct Person {
  string name_;
  int alter_;
  string ort_;
  ostream& drucke(ostream& os) {  // Methode inline definiert
    return os << format("{} ({}) aus {}", p.name_, p.alter_,  p.ort_);
  }
};

Okt 23, 2024

lst-0242-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bEdfWqqnn 
// Ausschnitt 
    std::ostream& drucke(std::ostream& os);
};
std::ostream& Person::drucke(std::ostream& os) {
    return os << format("{} ({}) aus {}", p.name_, p.alter_,  p.ort_);
}
std::ostream& operator<<(std::ostream& os, Person p) {
    return p.drucke(os);
}
int main() {
    Person paul {"Paul", 23, "Dresden"};
    cout << "Sie sind " << paul << ", richtig?\n";
}

Okt 23, 2024

lst-0221-book.cpp

// https://godbolt.org/z/Gvcj6hhYf 
#include <cstdlib>  // EXIT_SUCCESS
#include <iostream> // cout
#include <vector>
#include <string>
#include "qwort/qwort.hpp"
using std::cout; using std::vector; using std::string;
int main(int argc, const char* argv[]) {
    cout << "qwort version " << qw::version() << "\n";

    /* Index bauen */
    qw::index myindex{};

    /* - Demodaten */
    myindex.add("Deutschland");
    myindex.add("Griechenland");

    /* Abfragen erzeugen */
    vector<string> args(argv+1, argv+argc); // iteratorbasierte Initialisierung
    for(auto &querystring : args) {
        cout << "Suche '" << querystring << "'... ";
        const auto match = myindex.getBestMatch(querystring);
        cout << match << "\n";
    }
    return EXIT_SUCCESS;
}

Okt 23, 2024

lst-0228-book.cpp

// https://godbolt.org/z/YYfxMdfP8 
Person erzeuge(string name, int alter, string ort) {
    return Person{name, alter, ort};       // direkt zurückgegeben
}
int main() {
    drucke(erzeuge("Otto", 45, "Kassel")); // Rückgabe direkt verwendet
}

Okt 23, 2024

lst-0231-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KvTx3rPs5 
auto erzeuge(string name, int alter, string ort) {
    return Person{name, alter, ort};  // auto verlangt Konstruktornamen
}
auto erzeuge2(string name, int alter, string ort) {
    return {name, alter, ort};       //             (ERR)  auto mit initializer_list geht nicht
}

Okt 23, 2024

lst-0231-book.cpp

// https://godbolt.org/z/KvTx3rPs5 
auto erzeuge(string name, int alter, string ort) {
    return Person{name, alter, ort};  // auto verlangt Konstruktornamen
}
auto erzeuge2(string name, int alter, string ort) {
    return {name, alter, ort};       //             (ERR)  auto mit initializer_list geht nicht
}

Okt 23, 2024

lst-0217-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7nasGjGq6 
#ifndef QWORT_H // Header-Guard
#define QWORT_H
#include <string>
#include <memory> // unique_ptr
namespace qw { // Namensraum der Bibliothek
    int version();
    namespace impl_multimap {
        class index_impl;
    }
    class index {
        using index_impl = impl_multimap::index_impl;
    public:
        index();
        ~index() noexcept; // wird für pimpl benötigt
        index(const index&) = default;
        index(index&&) noexcept;
        index& operator=(const index&) = default;
        index& operator=(index&&) = default;
    public:
        void add(const std::string &arg);
        size_t size() const;
        std::string getBestMatch(const std::string& query) const;
    public:          // public für Tests
        std::string normalize(std::string arg) const;
    private:
        const std::unique_ptr<index_impl> pimpl;
    };
} // namespace qw
#endif // Header-Guard

Okt 23, 2024

lst-0222-book.cpp

// https://godbolt.org/z/8YqoTEx58 
#include <string>
#include <iostream>                     // cout
#include <format>
using std::string; using std::cout; using std::format;
struct Person {                         // definiert den neuen Typ Person
    string name_;
    int alter_;
    string ort_;
};                                      // abschließendes Semikolon
void drucke(Person p) {                 // ganze Person als ein Parameter
    cout << format("{} ({}) aus {}\n",
      p.name_, p.alter_, p.ort_);       // Zugriff per Punkt
}
int main() {
    Person otto {"Otto", 45, "Kassel" }; // Initialisierung
    drucke(otto);                        // Aufruf als Einheit
}

Okt 23, 2024

lst-0250-book.cpp

// https://godbolt.org/z/cqoTsWbhW 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person();                         // Konstruktor ohne Argumente
    Person(sview n, int a, sview o);  // Konstruktor mit drei Argumenten
    Person(sview n, int a);           // Konstruktor mit zwei Argumenten
    Person(sview n);                  // Konstruktor mit einem Argument
};

Person::Person() 
  : name_{"kein Name"}, alter_{-1}, ort_{"kein Ort"} { } 
Person::Person(sview n, int a, sview o) 
  : name_{n}, alter_{a}, ort_{o} { } 
Person::Person(sview n, int a)
  : name_{n}, alter_{a}, ort_{"kein Ort"} { }
Person::Person(sview n)
  : name_{n}, alter_{-1}, ort_{"kein Ort"} { }

Okt 23, 2024

lst-0195-book.cpp

// https://godbolt.org/z/cjfG7bc33 
#include <iostream>
int main() {
    try {                                       // Beginn des try-Blocks
        for(int n=1; ; n=n*2) {
            if(n < 0) {
                throw "Es gab einen Ueberlauf";  // Fehler auslösen
            }
        }
    }                                            // Ende des try-Blocks
    catch(const char *fehler) {                  // falls dieser Fehler auftritt, …
      std::cout << "Fehler: " << fehler << "\n"; // … behandle ihn so
    }
}

Okt 23, 2024

lst-0196-book.cpp

// https://godbolt.org/z/E1aGdox6q 
#include <iostream>           // cout
#include <string>
void drucke(int n) {          // Funktion drucke für Typ int
    std::cout << "Zahl:" << n << "\n";
}
void drucke(std::string s) {  // gleicher Name, anderer Typ
    std::cout << "Zeichenkette:" << s << "\n";
}
int main() {
    int zahl = 10;
    std::string name = "Bilbo";
    drucke(zahl);              // ruft drucke(int) auf, zahl ist int
    drucke(name);              // ruft drucke(string) auf, name ist string
    drucke(11 + 22);           // Ausdruck ist int
    drucke(name + " Baggins"); // Ausdruck ist string
}

Okt 23, 2024

lst-0158-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8Gdso36zf 
class Widget : public Base {
    explicit Widget(int);     // keine automatische Konvertierung von int
    ~Widget();                // Destruktor mit ~ vor dem Namen
    virtual void update();    // vorangestelltes virtual
    void calc1() override;    // nachgestelltes override
    void calc2() final;       // nachgestelltes final
    void draw() const;        // nachgestelltes const
    virtual void paint() = 0; // abstrakte Methode
};

Okt 23, 2024

lst-0194-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/b361eeba3 
// #includes, prims, eingabeBis(), ausgabePrims() und main() wie zuvor 
std::vector<int> prims{2};
void berechnePrimsBis(int bis) {
    /* Prims-Berechnung */
    /* vector muss an dieser Stelle {2} enthalten */
    for(int n=3; n<bis; n=n+2) {
        for(int teil: prims) {
            if(teil*teil > n)
                goto prim;     // mit goto, weil ein break 
            if(n%teil==0)
                goto nichtPrim;//  über zwei Schleifen nicht geht.
        }
      prim: ;                  // Ziel des Sprungs vor push_back
        prims.push_back(n);    // n ist prim! Merken als Teiler und Ergebnis
      nichtPrim: ;             // Ziel des Sprungs hinter push_back
    }
}

Okt 23, 2024

lst-0192-book.cpp

// https://godbolt.org/z/5ddxa9v1j 
#include <iostream>                      // cout
int min3(int x, int y, int z) {          // Funktion liefert einen int zurück
    if(x<y) {
        if(x<z) return x;
        else return z;
    } else if(y<z) {
        return y;
    }
    else return z;
}
void printMin(int x, int y, int z) {     // Funktion liefert nichts zurück
    if(x<0 || y<0 || z<0) {
        std::cout << "Bitte nur Zahlen groesser 0\n";
        return;
    }
    std::cout << min3(x,y,z) << "\n";
}                                        // hier steht kein return
int main() {
    printMin(3, -4, 8);
    printMin(6, 77, 4);
    return;                              // besonderes return in main
}

Okt 23, 2024

lst-0193-book.cpp

// https://godbolt.org/z/ohd5Pr8fb 
#include <iostream>
int main() {
    int idx = 4;
    goto mehr;                      // springe zu Label mehr
  drucke:                           // Label für die nächste Anweisung
    std::cout << idx << std::endl;
    idx = idx * 2;
  mehr:
    idx = idx + 3;
    if(idx < 20)
        goto drucke;                // goto kann auch in einem if stehen
  ende:                             // dies ist ein Label, wird aber nicht verwendet
    return 0;
}

Okt 23, 2024

lst-0186-book.cpp

// https://godbolt.org/z/185ha3q3f 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    int zahl = 1;                         // Initialisierung vor der Schleife
    for(  ; zahl <= 100; zahl=zahl+1) {   // leere Initialisierung
        summe = summe + zahl;
    }
    std::cout << zahl << std::endl;       // zahl gibt es nun noch außerhalb
}

Okt 23, 2024

lst-0189-book.cpp

// https://godbolt.org/z/5oe38obPr 
#include <string>
#include <vector>
#include <iostream>       // cout

void rechner(std::ostream& out, std::string input) {
    std::vector<int> stapel {};
    for(char c : input) {
        if(c>='0' && c<='9') {
            stapel.push_back( c-'0' ); // Zahlenwert des Zeichens
            continue;     // nächste Schleifeniteration
        }
        int top = 0;
        int second = 0;
        switch(c) {       // Bedingung auf zeichen
        case '+':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second + top);
            break;
        case '-':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second - top);
            break;
        case '*':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second * top);
            break;
        case '=':
            for(int elem : stapel) { out << elem; }
            out << "\n";
            break;
        case ' ':
            break;
        default:
            out << "\n'" << c << "' verstehe ich nicht.\n";
        } /* switch */
    } /* for c */
}
int main(int argc, const char* argv[]) {
    if(argc > 1) {
        rechner(std::cout, argv[1]);
    } else {
        // 3 + 4 * 5 + 6 mit Punkt- vor Strichrechnung ergibt 29
        rechner(std::cout, "345*+6+=");
    }
}

Okt 23, 2024

lst-0190-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jaMTcshEf 
#include <iostream>
#include <string>

using std::string; using std::cout;

void rateMonat(unsigned welchenTagHabenwirHeute) {
    switch(welchenTagHabenwirHeute) {
    /* fehlende break-Anweisungen: Fall-through beabsichtigt */
    default:
        if(welchenTagHabenwirHeute>31) {
            cout << "Sie schummeln";
            break;
        }
    case 28:
    case 29:
        cout << "Feb ";
    case 30:
        cout << "Apr Jun Sep Nov ";
    case 31:
        cout << "Jan Mar Mai Jul Aug Okt Dez ";
    }

    cout << ".\n";
}
int main() {
    rateMonat(31); // wenn wir heute den 31. hätten?
    // Ausgabe: Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(30); // wenn es der 30. wäre?
    // Ausgabe: Apr Jun Sep Nov Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(4);
    // Ausgabe: Feb Apr Jun Sep Nov Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(77);
    // Ausgabe: Sie schummeln.
}

Okt 23, 2024

lst-0172-book.cpp

// https://godbolt.org/z/G7P4ErTE1 
#include <iostream>
#include <tuple> // make_tuple
auto mkTpl() {
    return std::make_tuple(2, 'b', 3.14); // tuple<int,char,double>
}
struct Point {
    int x, y;
};
int main() {
    // Strukuriertes Binden eines C-Arrays
    int ungerade[5] = { 1,3,7,9,11 };
    auto [ eins, zwei, drei, vier, fuenf ] = ungerade;
    // Strukuriertes Binden eines Tupels
    auto [ two, bee, pi ] = mkTpl();
    // Strukuriertes Binden einer Struktur
    Point p0{  10, 15 };
    auto [ the_x, the_y ] = p0;
}

Okt 23, 2024

lst-0172-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/G7P4ErTE1 
#include <iostream>
#include <tuple> // make_tuple
auto mkTpl() {
    return std::make_tuple(2, 'b', 3.14); // tuple<int,char,double>
}
struct Point {
    int x, y;
};
int main() {
    // Strukuriertes Binden eines C-Arrays
    int ungerade[5] = { 1,3,7,9,11 };
    auto [ eins, zwei, drei, vier, fuenf ] = ungerade;
    // Strukuriertes Binden eines Tupels
    auto [ two, bee, pi ] = mkTpl();
    // Strukuriertes Binden einer Struktur
    Point p0{  10, 15 };
    auto [ the_x, the_y ] = p0;
}

Okt 23, 2024

lst-0196-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/E1aGdox6q 
#include <iostream>           // cout
#include <string>
void drucke(int n) {          // Funktion drucke für Typ int
    std::cout << "Zahl:" << n << "\n";
}
void drucke(std::string s) {  // gleicher Name, anderer Typ
    std::cout << "Zeichenkette:" << s << "\n";
}
int main() {
    int zahl = 10;
    std::string name = "Bilbo";
    drucke(zahl);              // ruft drucke(int) auf, zahl ist int
    drucke(name);              // ruft drucke(string) auf, name ist string
    drucke(11 + 22);           // Ausdruck ist int
    drucke(name + " Baggins"); // Ausdruck ist string
}

Okt 23, 2024

lst-0182-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gc53z6K1W 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    int zahl = 1;
    while(zahl <= 100)       // Bedingung
    {                        // Block, der wiederholt ausgeführt wird
        summe += zahl;       // fürs Ergebnis
        zahl += 1;           // nächste Zahl
    }                        // Ende des wiederholten Blocks
    std::cout << summe << std::endl;
}

Okt 23, 2024

lst-0210-book.cpp

// https://godbolt.org/z/K37fMW8fE 
#include <iostream> // cout, cerr
#include <fstream>
#include <vector>
#include <string>
using std::vector; using std::string; using std::cout; using std::cerr;

int zaehleWoerter(const string& filename) { // Rückgabe kleiner 0 bei Fehler
    std::ifstream file{filename};
    if(!file) {     // Gab es einen Fehler beim Öffnen der Datei?
        cerr << "Fehler beim Oeffnen von " << filename << "\n";
        return -1;  // dem Aufrufer einen Fehler mittels besonderem Wert melden
    }
    int count = 0;
    string wort;
    while(!file.eof()) {    // noch nicht am Ende?
        file >> wort;
        ++count;
    }
    return count-1;         // –1: am EOF wurde noch ein Wort gelesen
}
bool process(const vector<string>& args) { // Rückgabe true bei alles okay
    if(args.size() == 0) {  // erwarten Parameter
        cerr << "Kommandozeilenargument fehlt\n";
        return false;       // mittels Rückgabe einen Fehler mitteilen
    } else {
        bool result = true; // fürs Endergebnis
        for(const string filename : args) {
            cout << filename << ": ";
            int count = zaehleWoerter(filename);
            if(count < 0) { // besondere Rückgabe zeigt Fehler an
                cout << "Fehler!\n";
                result = false;         // mindestens ein Fehler
            } else {
                cout << count << "\n";  // normales Ergebnis ausgeben
            }
        }
        return result;                  // Gesamtergebnis zurückgeben
    }
}

int main(int argc, const char* argv[]) {
    bool result = process(              // Rückgabewert enthält Fehlerindikator
        {argv+1, argv+argc} );          // const char*[] nach vector<string>
    if(result) {                        // Rückgabewert auswerten
        return 0;
    } else {
        cerr << "Es trat ein Fehler auf.\n";
        return 1;   // außen Fehler anzeigen
    }
}

Okt 23, 2024

lst-0189-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5oe38obPr 
#include <string>
#include <vector>
#include <iostream>       // cout

void rechner(std::ostream& out, std::string input) {
    std::vector<int> stapel {};
    for(char c : input) {
        if(c>='0' && c<='9') {
            stapel.push_back( c-'0' ); // Zahlenwert des Zeichens
            continue;     // nächste Schleifeniteration
        }
        int top = 0;
        int second = 0;
        switch(c) {       // Bedingung auf zeichen
        case '+':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second + top);
            break;
        case '-':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second - top);
            break;
        case '*':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second * top);
            break;
        case '=':
            for(int elem : stapel) { out << elem; }
            out << "\n";
            break;
        case ' ':
            break;
        default:
            out << "\n'" << c << "' verstehe ich nicht.\n";
        } /* switch */
    } /* for c */
}
int main(int argc, const char* argv[]) {
    if(argc > 1) {
        rechner(std::cout, argv[1]);
    } else {
        // 3 + 4 * 5 + 6 mit Punkt- vor Strichrechnung ergibt 29
        rechner(std::cout, "345*+6+=");
    }
}

Okt 23, 2024

lst-0203-book.cpp

// https://godbolt.org/z/EY5K6Wsr3 
std::vector<int> data(10);     // 10 mal 0 in einem vector
data.front() = 666;            // schreibt 666 an die vorderste Stelle

Okt 23, 2024

lst-0184-book.cpp

// https://godbolt.org/z/6hh5KhExM 
#include <iostream>                 // cin
#include <string>
int main() {
    std::string line;
    do {                            // mindestens einmal getline ausführen
       std::getline(std::cin, line);
       if(!std::cin) break;         // Fehler oder Dateiende
    } while(line != "quit");        // Ende bei bestimmter Eingabe
}

Okt 23, 2024

lst-0204-book.cpp

// https://godbolt.org/z/K9c913had 
if(int result;  (result = read(buffer, 100)) != 0) {
    std::cerr << "Es trat Fehler Nummer "<< result << " auf.\n";
}

Okt 23, 2024

lst-0159-book.cpp

// https://godbolt.org/z/3hf7h67Pe 
#include <iostream>                   // cout
#include <vector>                     // Container vector
#include <string>                     // stoi
int eingabeBis(int argc, const char* argv[]) {
    /* Zahl ermitteln */
    int bis = 0;                      // neue Variable einführen
    if(argc<=1) {                     // if-Anweisung mit then- und else-Block
        std::cout << "Bis wohin wollen Sie Primzahlen berechnen? ";
        if(!(std::cin >> bis)) {      // Prüfen des Rückgabewerts
            return -1;                // Fehler bei Benutzereingabe
        }
    } else {                          // else-Teil der if-Anweisung
        bis = std::stoi(argv[1]);
    }
    return bis;                       // Eingabe zurückliefern
}
std::vector prims{2};                 // neuer vector<int> mit Initialisierung
bool testeObPrim(int n) {
    /* prims muss aufsteigend sortiert sein */
    for(int teil : prims) {           // bereichsbasierte for-Schleife
        if(teil*teil > n)             // zu groß, um überhaupt Teiler zu sein?
            return true;              // … dann innere Schleife vorzeitig beenden
        if(n%teil==0)                 // ist Teiler?
            return false;             // … dann raus
    }
    return true;                      // kein Teiler gefunden
}
void berechnePrimsBis(int bis) {
    /* Prims-Berechnung */
    /* vector muss an dieser Stelle {2} enthalten */
    for(int n=3; n<bis; n=n+2) {      // Standard-for-Schleife
        if(testeObPrim(n)) {
            prims.push_back(n);       // ist prim – merken als Teiler und Ergebnis
        }
    }
}
void ausgabePrims() {
    for(int prim : prims) {           // bereichsbasiert, über alle Elemente
        std::cout << prim << " ";
    }
    std::cout << "\n";
}
int main(int argc, const char* argv[]) {
    int bis = eingabeBis(argc, argv); // deklariert Variable
    if(bis < 2) { return 1; }         // Raus aus main mit Nicht-okay-Wert.
    berechnePrimsBis(bis);
    ausgabePrims();
    return 0;
}

Okt 23, 2024

lst-0173-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YTTE96rfc 
int main() {
    int ungerade[5] = { 1,3,7,9,11 };
    auto &[ eins, zwei, drei, vier, fuenf ] = ungerade;
    auto &[ two, bee, pi ] = mkTpl(); //             (ERR)  kein &-Binden an Tempwerte
    Point p0{  10, 15 };
    auto &[ the_x, the_y ] = p0;
}

Okt 23, 2024

lst-0181-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ycse4EWav 
#include <iostream> // cout

template<typename T>
void speicher(T x) {
    if constexpr(sizeof(T) > 4) {
       std::cout << "Braucht viel Speicher: " << x << " \n";
    }
}

constexpr auto DEBUG = true;
int main() {
    if constexpr(DEBUG) {
        std::cout << "Debug ist an.\n";
    }
    speicher<long long>(44LL);
}

Okt 23, 2024

lst-0181-book.cpp

// https://godbolt.org/z/Ycse4EWav 
#include <iostream> // cout

template<typename T>
void speicher(T x) {
    if constexpr(sizeof(T) > 4) {
       std::cout << "Braucht viel Speicher: " << x << " \n";
    }
}

constexpr auto DEBUG = true;
int main() {
    if constexpr(DEBUG) {
        std::cout << "Debug ist an.\n";
    }
    speicher<long long>(44LL);
}

Okt 23, 2024

lst-0192-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5ddxa9v1j 
#include <iostream>                      // cout
int min3(int x, int y, int z) {          // Funktion liefert einen int zurück
    if(x<y) {
        if(x<z) return x;
        else return z;
    } else if(y<z) {
        return y;
    }
    else return z;
}
void printMin(int x, int y, int z) {     // Funktion liefert nichts zurück
    if(x<0 || y<0 || z<0) {
        std::cout << "Bitte nur Zahlen groesser 0\n";
        return;
    }
    std::cout << min3(x,y,z) << "\n";
}                                        // hier steht kein return
int main() {
    printMin(3, -4, 8);
    printMin(6, 77, 4);
    return;                              // besonderes return in main
}

Okt 23, 2024

lst-0182-book.cpp

// https://godbolt.org/z/Gc53z6K1W 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    int zahl = 1;
    while(zahl <= 100)       // Bedingung
    {                        // Block, der wiederholt ausgeführt wird
        summe += zahl;       // fürs Ergebnis
        zahl += 1;           // nächste Zahl
    }                        // Ende des wiederholten Blocks
    std::cout << summe << std::endl;
}

Okt 23, 2024

lst-0185-book.cpp

// https://godbolt.org/z/7foYcMMaz 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    for(int zahl=1; zahl <= 100; zahl+=1) {   // kompakt
        summe += zahl;                        // fürs Ergebnis
    }
    std::cout << summe << std::endl;
}

Okt 23, 2024

lst-0193-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ohd5Pr8fb 
#include <iostream>
int main() {
    int idx = 4;
    goto mehr;                      // springe zu Label mehr
  drucke:                           // Label für die nächste Anweisung
    std::cout << idx << std::endl;
    idx = idx * 2;
  mehr:
    idx = idx + 3;
    if(idx < 20)
        goto drucke;                // goto kann auch in einem if stehen
  ende:                             // dies ist ein Label, wird aber nicht verwendet
    return 0;
}

Okt 23, 2024

lst-0190-book.cpp

// https://godbolt.org/z/jaMTcshEf 
#include <iostream>
#include <string>

using std::string; using std::cout;

void rateMonat(unsigned welchenTagHabenwirHeute) {
    switch(welchenTagHabenwirHeute) {
    /* fehlende break-Anweisungen: Fall-through beabsichtigt */
    default:
        if(welchenTagHabenwirHeute>31) {
            cout << "Sie schummeln";
            break;
        }
    case 28:
    case 29:
        cout << "Feb ";
    case 30:
        cout << "Apr Jun Sep Nov ";
    case 31:
        cout << "Jan Mar Mai Jul Aug Okt Dez ";
    }

    cout << ".\n";
}
int main() {
    rateMonat(31); // wenn wir heute den 31. hätten?
    // Ausgabe: Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(30); // wenn es der 30. wäre?
    // Ausgabe: Apr Jun Sep Nov Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(4);
    // Ausgabe: Feb Apr Jun Sep Nov Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(77);
    // Ausgabe: Sie schummeln.
}

Okt 23, 2024

lst-0173-book.cpp

// https://godbolt.org/z/YTTE96rfc 
int main() {
    int ungerade[5] = { 1,3,7,9,11 };
    auto &[ eins, zwei, drei, vier, fuenf ] = ungerade;
    auto &[ two, bee, pi ] = mkTpl(); //             (ERR)  kein &-Binden an Tempwerte
    Point p0{  10, 15 };
    auto &[ the_x, the_y ] = p0;
}

Okt 23, 2024

lst-0191-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/75h9Y95vf 
#include <iostream>                // cout
int main() {
    for(int x=1; x<20; x+=1) {     // äußere for-Schleife
        for(int y=1; y<20; y+=1) { // innere for-Schleife
            int prod = x*y;
            if(prod>=100) {
                break;             // raus aus innerer y-Schleife
            }
            std::cout << prod << " ";
        } /* Ende for y */
        // Ziel von break
    } /* Ende for x */                // erste wirkliche Zeile nach break
    std::cout << "\n";
}

Okt 23, 2024

lst-0180-book.cpp

// https://godbolt.org/z/d6PscKx4M 
#include <map>
#include <string>
#include <algorithm> // any_of
#include <iostream>  // cerr
std::map<int, std::string> m;
int main() {
   if(auto it = m.find(10); it != m.end()) { return it->second.size(); }
   if(char buf[10]={0}; std::fgets(buf, 10, stdin)) { m[0] += buf; }
   std::string s;
   if(auto keywords = {"if", "for", "while"};
       std::any_of(keywords.begin(), keywords.end(),
       [&s](const char* kw) { return s == kw; })) {
           std::cerr << "Fehler\n";
   }
}

Okt 23, 2024

lst-0185-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7foYcMMaz 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    for(int zahl=1; zahl <= 100; zahl+=1) {   // kompakt
        summe += zahl;                        // fürs Ergebnis
    }
    std::cout << summe << std::endl;
}

Okt 23, 2024

lst-0184-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6hh5KhExM 
#include <iostream>                 // cin
#include <string>
int main() {
    std::string line;
    do {                            // mindestens einmal getline ausführen
       std::getline(std::cin, line);
       if(!std::cin) break;         // Fehler oder Dateiende
    } while(line != "quit");        // Ende bei bestimmter Eingabe
}

Okt 23, 2024

lst-0186-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/185ha3q3f 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    int zahl = 1;                         // Initialisierung vor der Schleife
    for(  ; zahl <= 100; zahl=zahl+1) {   // leere Initialisierung
        summe = summe + zahl;
    }
    std::cout << zahl << std::endl;       // zahl gibt es nun noch außerhalb
}

Okt 23, 2024

lst-0211-book.cpp

// https://godbolt.org/z/sz9hxKozf 
#include <iostream>            // cout, cerr
#include <vector>
#include <string>
#include <fstream>             // ifstream
#include <stdexcept>           // invalid_argument
using std::vector; using std::string; using std::cout; using std::ifstream;
size_t zaehleWoerter(const string& filename) { // 0 oder größer
    std::ifstream file{};      // ungeöffnet erzeugen
    // anmelden für Exceptions:
    file.exceptions(ifstream::failbit | ifstream::badbit);
    file.open(filename);       // könnte eine Exception auslösen
    size_t count = 0;
    string wort;
    file.exceptions(ifstream::badbit); // EOF keine Exception mehr
    while(!file.eof()) {       // noch nicht am Ende?
        file >> wort;   ++count;
    }
    return count-1;            // –1: am EOF wurde noch ein Wort gelesen
}
void process(const vector<string>& args) {
    if(args.size() == 0) {     // process erwartet Parameter
        throw std::invalid_argument{"Kommandozeilenarg. fehlt"}; // auslösen
    } else {
        for(const string filename : args) {
            cout << filename << ": " << zaehleWoerter(filename) << std::endl;
        }
    }
}
int main(int argc, const char* argv[]) {
    try {                                      // Block mit Fehlerbehandlungen
        process(
          vector<string>{argv+1, argv+argc} ); // const char*[] nach vector<string>
        return 0;
    } catch(std::exception &exc) {  // Fehlerbehandlung
        std::cerr << "Es trat ein Fehler auf: " << exc.what() << "\n";
        return 1;
    }
}

Okt 23, 2024

lst-0180-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/d6PscKx4M 
#include <map>
#include <string>
#include <algorithm> // any_of
#include <iostream>  // cerr
std::map<int, std::string> m;
int main() {
   if(auto it = m.find(10); it != m.end()) { return it->second.size(); }
   if(char buf[10]={0}; std::fgets(buf, 10, stdin)) { m[0] += buf; }
   std::string s;
   if(auto keywords = {"if", "for", "while"};
       std::any_of(keywords.begin(), keywords.end(),
       [&s](const char* kw) { return s == kw; })) {
           std::cerr << "Fehler\n";
   }
}

Okt 23, 2024

lst-0194-book.cpp

// https://godbolt.org/z/b361eeba3 
// #includes, prims, eingabeBis(), ausgabePrims() und main() wie zuvor 
std::vector<int> prims{2};
void berechnePrimsBis(int bis) {
    /* Prims-Berechnung */
    /* vector muss an dieser Stelle {2} enthalten */
    for(int n=3; n<bis; n=n+2) {
        for(int teil: prims) {
            if(teil*teil > n)
                goto prim;     // mit goto, weil ein break …
            if(n%teil==0)
                goto nichtPrim;// … über zwei Schleifen nicht geht.
        }
      prim: ;                  // Ziel des Sprungs vor push_back
        prims.push_back(n);    // n ist prim! Merken als Teiler und Ergebnis
      nichtPrim: ;             // Ziel des Sprungs hinter push_back
    }
}

Okt 23, 2024

lst-0191-book.cpp

// https://godbolt.org/z/75h9Y95vf 
#include <iostream>                // cout
int main() {
    for(int x=1; x<20; x+=1) {     // äußere for-Schleife
        for(int y=1; y<20; y+=1) { // innere for-Schleife
            int prod = x*y;
            if(prod>=100) {
                break;             // raus aus innerer y-Schleife
            }
            std::cout << prod << " ";
        } /* Ende for y */
        // Ziel von break
    } /* Ende for x */                // erste wirkliche Zeile nach break
    std::cout << "\n";
}

Okt 23, 2024

lst-0159-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3hf7h67Pe 
#include <iostream>                   // cout
#include <vector>                     // Container vector
#include <string>                     // stoi
int eingabeBis(int argc, const char* argv[]) {
    /* Zahl ermitteln */
    int bis = 0;                      // neue Variable einführen
    if(argc<=1) {                     // if-Anweisung mit then- und else-Block
        std::cout << "Bis wohin wollen Sie Primzahlen berechnen? ";
        if(!(std::cin >> bis)) {      // Prüfen des Rückgabewerts
            return -1;                // Fehler bei Benutzereingabe
        }
    } else {                          // else-Teil der if-Anweisung
        bis = std::stoi(argv[1]);
    }
    return bis;                       // Eingabe zurückliefern
}
std::vector prims{2};                 // neuer vector<int> mit Initialisierung
bool testeObPrim(int n) {
    /* prims muss aufsteigend sortiert sein */
    for(int teil : prims) {           // bereichsbasierte for-Schleife
        if(teil*teil > n)             // zu groß, um überhaupt Teiler zu sein?
            return true;              //  dann innere Schleife vorzeitig beenden
        if(n%teil==0)                 // ist Teiler?
            return false;             //  dann raus
    }
    return true;                      // kein Teiler gefunden
}
void berechnePrimsBis(int bis) {
    /* Prims-Berechnung */
    /* vector muss an dieser Stelle {2} enthalten */
    for(int n=3; n<bis; n=n+2) {      // Standard-for-Schleife
        if(testeObPrim(n)) {
            prims.push_back(n);       // ist prim  merken als Teiler und Ergebnis
        }
    }
}
void ausgabePrims() {
    for(int prim : prims) {           // bereichsbasiert, über alle Elemente
        std::cout << prim << " ";
    }
    std::cout << "\n";
}
int main(int argc, const char* argv[]) {
    int bis = eingabeBis(argc, argv); // deklariert Variable
    if(bis < 2) { return 1; }         // Raus aus main mit Nicht-okay-Wert.
    berechnePrimsBis(bis);
    ausgabePrims();
    return 0;
}

Okt 23, 2024

lst-0210-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/K37fMW8fE 
#include <iostream> // cout, cerr
#include <fstream>
#include <vector>
#include <string>
using std::vector; using std::string; using std::cout; using std::cerr;

int zaehleWoerter(const string& filename) { // Rückgabe kleiner 0 bei Fehler
    std::ifstream file{filename};
    if(!file) {     // Gab es einen Fehler beim Öffnen der Datei?
        cerr << "Fehler beim Oeffnen von " << filename << "\n";
        return -1;  // dem Aufrufer einen Fehler mittels besonderem Wert melden
    }
    int count = 0;
    string wort;
    while(!file.eof()) {    // noch nicht am Ende?
        file >> wort;
        ++count;
    }
    return count-1;         // 1: am EOF wurde noch ein Wort gelesen
}
bool process(const vector<string>& args) { // Rückgabe true bei alles okay
    if(args.size() == 0) {  // erwarten Parameter
        cerr << "Kommandozeilenargument fehlt\n";
        return false;       // mittels Rückgabe einen Fehler mitteilen
    } else {
        bool result = true; // fürs Endergebnis
        for(const string filename : args) {
            cout << filename << ": ";
            int count = zaehleWoerter(filename);
            if(count < 0) { // besondere Rückgabe zeigt Fehler an
                cout << "Fehler!\n";
                result = false;         // mindestens ein Fehler
            } else {
                cout << count << "\n";  // normales Ergebnis ausgeben
            }
        }
        return result;                  // Gesamtergebnis zurückgeben
    }
}

int main(int argc, const char* argv[]) {
    bool result = process(              // Rückgabewert enthält Fehlerindikator
        {argv+1, argv+argc} );          // const char*[] nach vector<string>
    if(result) {                        // Rückgabewert auswerten
        return 0;
    } else {
        cerr << "Es trat ein Fehler auf.\n";
        return 1;   // außen Fehler anzeigen
    }
}

Okt 23, 2024

lst-0203-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EY5K6Wsr3 
std::vector<int> data(10);     // 10 mal 0 in einem vector
data.front() = 666;            // schreibt 666 an die vorderste Stelle

Okt 23, 2024

lst-0195-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cjfG7bc33 
#include <iostream>
int main() {
    try {                                       // Beginn des try-Blocks
        for(int n=1; ; n=n*2) {
            if(n < 0) {
                throw "Es gab einen Ueberlauf";  // Fehler auslösen
            }
        }
    }                                            // Ende des try-Blocks
    catch(const char *fehler) {                  // falls dieser Fehler auftritt, 
      std::cout << "Fehler: " << fehler << "\n"; //  behandle ihn so
    }
}

Okt 23, 2024

lst-0204-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/K9c913had 
if(int result;  (result = read(buffer, 100)) != 0) {
    std::cerr << "Es trat Fehler Nummer "<< result << " auf.\n";
}

Okt 23, 2024

lst-0134-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/caExoc36Y 
#include <iostream>
double verdopple(double zahl) {    // Wertparameter und Rückgabewert
    return zahl * 2.0;
}
int main() {
    double zahl = 7.25;
    zahl = verdopple(zahl);        // Änderung ausgedrückt durch Rückgabewert
    std::cout << zahl << "\n";     // auch 14.5
}

Okt 23, 2024

lst-0114-book.cpp

// https://godbolt.org/z/a4zxbd99z 
#include <array>
#include <algorithm>                    // accumulate
#include <numeric>                      // iota
using Januar = std::array<int,31>;      // Alias für wiederholte Verwendung

void initJanuar(Januar& jan) {          // das genaue Array als Parameter
    std::iota(begin(jan), end(jan), 1); // füllt mit  1, 2, 3 … 31
}
int sumJanuar(const Januar& jan) {      // das genaue Array als Parameter
    return std::accumulate(begin(jan), end(jan), 0); // Hilfsfunktion für Summe
}
int main() {
    Januar jan;                         // deklariert ein array<int,31>
    initJanuar( jan );
    int sum = sumJanuar( jan );
}

Okt 23, 2024

lst-0147-book.cpp

// https://godbolt.org/z/fjc37rvEr 
int add(int n=0, int m=0, int o=0, int p=0, int q=0) {
    return n+m+o+p+q;
}
int main() {
    std::cout << add(1,2,3,4,5) << "\n";
    std::cout << add(1,2,3,4) << "\n"; // wie add(1,2,3,4,0)
    std::cout << add(1,2,3) << "\n";   // wie add(1,2,3,0,0)
    std::cout << add(1,2) << "\n";     // wie add(1,2,0,0,0)
    std::cout << add(1) << "\n";       // wie add(1,0,0,0,0)
    std::cout << add() << "\n";        // wie add(0,0,0,0,0)
}

Okt 23, 2024

lst-0119-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4G67rso8T 
#include <vector>
#include <algorithm>                           // count_if
#include <numeric>                             // iota
#include <iostream>
bool even(int n) { return n%2==0; }            // Test auf gerade
int main() {
    std::vector<int> data(100);                // 100 x null
    std::iota(data.begin(), data.end(), 0);    // 0, 1, 2,  99
    // zählt gerade Zahlen
    std::cout << std::count_if(data.begin(), data.end(), even);
}

Okt 23, 2024

lst-0138-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6hWvqhY7W 
#include <iostream>
#include <format>
void prints(short s, int i, float f, double d) {
  std::cout << std::format("short: {} int: {} float: {:.2f} double: {:.2f}\n",
    s, i, f, d);
}
int main() {
  int mill = 1000*1000;                // 1 Million
  prints(mill, mill, mill, mill);      // short läuft über
  // Ausgabe: short: 16960 int: 1000000 float: 1000000.00 double: 1000000.00
  long bill = 1000L*1000L*1000L*1000L; // 1 Billion
  prints(bill, bill, bill, bill);      // sogar int läuft über, float wird ungenau
  // Ausgabe: short: 4096 int: 727379968 
  // float: 999999995904.00 double: 1000000000000.00
  float drei = 3.75f;
  prints(drei, drei, drei, drei);     // Nachkommastellen gehen verloren
  // Ausgabe: short: 3 int: 3 float: 3.75 double: 3.75
}

Okt 23, 2024

lst-0113-book.cpp

// https://godbolt.org/z/zfe7dM4ex 
#include <array>
#include <iostream>
constexpr size_t MONATE = 12; /* Monate im Jahr */
int main() {
    std::array<unsigned,MONATE> mtage = {     // okay mit einer Konstante
        31,28,31,30,31,30,31,31,30,31,30,31};
    unsigned alter = 0;
    std::cout << "Wie alt sind Sie? "; std::cin >> alter;
    std::array<int,alter> lebensjahre;       // Arraygröße geht nicht per Variable
}

Okt 23, 2024

lst-0109-book.cpp

//https://godbolt.org/z/EcnWz3r3j 
#include <iostream>
#include <iomanip>                   // fixed, setprecision
#include <format>                    // C++20
using std::cout; using std::format;  // Abkürzung cout, format
int main() {
    cout << std::fixed               // Punktschreibweise, nicht wissenschaftlich
         << std::setprecision(15);   // 15 Nachkommastellen
    cout << 0.5 << "\n";             // Ausgabe: 0.500000000000000*
    cout << std::setprecision(5);    // 5 Nachkommastellen
    cout << 0.25 << "\n";            // Ausgabe: 0.25000
    cout << format("{:0.4f}", 0.75) << "\n"; // (C++20) Ausgabe: 0.7500
    return 0;
}

Okt 23, 2024

lst-0157-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dMvqG85fr 
double add(double a, double b) { return a + b; }
double add(int, int) = delete;   // add(3,4) verbieten

Okt 23, 2024

lst-0117-book.cpp

// https://godbolt.org/z/xcKM7v1Eo 
#include <vector>
#include <iostream>                           // cout, endl
int main() {
  std::vector qus{1,4,9,16,25};
  for(unsigned idx=0; idx<qus.size(); ++idx)  // size enthält die Anzahl
    std::cout << qus[idx] << " ";             // [idx] oder at(idx) holt ein Element
  std::cout << std::endl;
}

Okt 23, 2024

lst-0119-book.cpp

// https://godbolt.org/z/4G67rso8T 
#include <vector>
#include <algorithm>                           // count_if
#include <numeric>                             // iota
#include <iostream>
bool even(int n) { return n%2==0; }            // Test auf gerade
int main() {
    std::vector<int> data(100);                // 100 x null
    std::iota(data.begin(), data.end(), 0);    // 0, 1, 2, … 99
    // zählt gerade Zahlen
    std::cout << std::count_if(data.begin(), data.end(), even);
}

Okt 23, 2024

lst-0153-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6d5fxn9ed 
auto maxOf2(int a, int b) {
    return a<b ? b : a;   // ein return: der Compiler ermittelt int
}
auto minOf3(int a, int b, int c) {
     if(a<b) return a<c ? a : c;
     else return b<c ? b : c;
}
auto medianOf3(int a, int b, int c) {
     // komplexer, aber kein Problem für den Compiler
     return minOf3(maxOf2(a,b), maxOf2(b,c), maxOf2(a,c));
}

Okt 23, 2024

lst-0140-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9YcPraT15 
#include <iostream>
void print(int wert) { std::cout << "int-Wert: " << wert << "\n"; }
void print(double wert) { std::cout << "double-Wert: " << wert << "\n"; }
void print(int w1, double w2) { std::cout << "Werte: "<<w1<<", "<<w2<<"\n"; }
int add(int n, int m) { return n + m; }
double add(double a, double b) { return a + b; }
int main() {
    print( add(3, 4) );        // add(int, int) und print(int)
    print( add(3.25f, 1.5f) ); // add(double, double) und print(double)
    print( 7, 3.25 );          // print(int, double)
}

Okt 23, 2024

lst-0109-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/EcnWz3r3j 
#include <iostream>
#include <iomanip>                   // fixed, setprecision
#include <format>                    // C++20
using std::cout; using std::format;  // Abkürzung cout, format
int main() {
    cout << std::fixed               // Punktschreibweise, nicht wissenschaftlich
         << std::setprecision(15);   // 15 Nachkommastellen
    cout << 0.5 << "\n";             // Ausgabe: 0.500000000000000*
    cout << std::setprecision(5);    // 5 Nachkommastellen
    cout << 0.25 << "\n";            // Ausgabe: 0.25000
    cout << format("{:0.4f}", 0.75) << "\n"; // (C++20) Ausgabe: 0.7500
    return 0;
}

Okt 23, 2024

lst-0133-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fTvT5sKqY 
#include <iostream>
void verdopple(double &zahl) {     // Ausgabeparameter als veränderbare Referenz
    zahl *= 2.0;
}

int main() {
    double zahl = 7.25;
    verdopple(zahl);
    std::cout << zahl << "\n";     // nun 14.5
}

Okt 23, 2024

lst-0153-book.cpp

// https://godbolt.org/z/6d5fxn9ed 
auto maxOf2(int a, int b) {
    return a<b ? b : a;   // ein return: der Compiler ermittelt int
}
auto minOf3(int a, int b, int c) {
     if(a<b) return a<c ? a : c;
     else return b<c ? b : c;
}
auto medianOf3(int a, int b, int c) {
     // komplexer, aber kein Problem für den Compiler
     return minOf3(maxOf2(a,b), maxOf2(b,c), maxOf2(a,c));
}

Okt 23, 2024

lst-0127-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5ssc6W5o6 
#include <iostream>              // cout
#include <cmath>                 // sin
#include <string>
#include <vector>
using std::sin;
int main() {
    std::cout << "sin(0.0): " << sin(0.0) << "\n";  // Aufruf von sin() mit Literal
    double winkel = 3.1415/2;
    std::cout << "sin("<<winkel<<"): "<<sin(winkel)<<"\n"; // Aufruf mit Variable
    std::string name = "Han Solo";
    std::cout << name.length() << "\n"; // Aufruf einer Methode
                                        //  konzeptionell wie length(name)
    std::vector<int> data{};
    data.push_back(5);                 // weiterer Methodenaufruf mit Parameter
    data.push_back(10);
    std::cout << data.back() << " ";
    data.pop_back();
    std::cout << data.back() << "\n";
    data.pop_back();
}

Okt 23, 2024

lst-0117-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xcKM7v1Eo 
#include <vector>
#include <iostream>                           // cout, endl
int main() {
  std::vector qus{1,4,9,16,25};
  for(unsigned idx=0; idx<qus.size(); ++idx)  // size enthält die Anzahl
    std::cout << qus[idx] << " ";             // [idx] oder at(idx) holt ein Element
  std::cout << std::endl;
}

Okt 23, 2024

lst-0115-book.cpp

// https://godbolt.org/z/T9jsEoMj4 
#include <vector>                    // Sie benötigen diesen Header
int main() {
    std::vector<int> quadrate{};     // leer initialisieren
    for(int idx = 0; idx<100; ++idx) {
        quadrate.push_back(idx*idx); // Anfügen eines Elements
    }
}

Okt 23, 2024

lst-0134-book.cpp

// https://godbolt.org/z/caExoc36Y 
#include <iostream>
double verdopple(double zahl) {    // Wertparameter und Rückgabewert
    return zahl * 2.0;
}
int main() {
    double zahl = 7.25;
    zahl = verdopple(zahl);        // Änderung ausgedrückt durch Rückgabewert
    std::cout << zahl << "\n";     // auch 14.5
}

Okt 23, 2024

lst-0129-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8zcvMdM3b 
#include <iostream>

void print_val8(int n) {            // Parameter als Wert
    std::cout << n << " ";
    n = 8;                          // setzt Parameter auf 8
    std::cout << n << "\n";
}

int main() {
    int x = 5;
    print_val8(x);                  // x als Wert: druckt 5, dann 8
    std::cout << x << "\n";         // x ist unverändert 5
    print_val8(42);                 // 42 als Wert: druckt 42, dann 8
}

Okt 23, 2024

lst-0138-book.cpp

// https://godbolt.org/z/6hWvqhY7W 
#include <iostream>
#include <format>
void prints(short s, int i, float f, double d) {
  std::cout << std::format("short: {} int: {} float: {:.2f} double: {:.2f}\n",
    s, i, f, d);
}
int main() {
  int mill = 1000*1000;                // 1 Million
  prints(mill, mill, mill, mill);      // short läuft über
  // Ausgabe: short: 16960 int: 1000000 float: 1000000.00 double: 1000000.00
  long bill = 1000L*1000L*1000L*1000L; // 1 Billion
  prints(bill, bill, bill, bill);      // sogar int läuft über, float wird ungenau
  // Ausgabe: short: 4096 int: –727379968 
  // float: 999999995904.00 double: 1000000000000.00
  float drei = 3.75f;
  prints(drei, drei, drei, drei);     // Nachkommastellen gehen verloren
  // Ausgabe: short: 3 int: 3 float: 3.75 double: 3.75
}

Okt 23, 2024

lst-0112-book.cpp

// https://godbolt.org/z/cd1d1W7T1 
#include <array>
#include <iostream>
using std::cout; using std::array; using std::string;
int main() {
  array<string,7> wotag = { "Montag", "Dienstag",        // definieren
      "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag" };
  cout << "Die Woche beginnt mit " << wotag[0] << ".\n"; // Werte lesen
  cout << "Sie endet mit " << wotag.at(6) << ".\n";      // sicheres Werte lesen
  /* nordisch? */
  wotag[5] = "Sonnabend";                                // Werte verändern
}

Okt 23, 2024

lst-0144-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/evGqG1oqa 
int verdopple(int a) { return a * 2; }
double verdopple(double a) { return a * 2.0; }
int main() {
    int x = verdopple(7);
    double y = verdopple(7.0);
}

Okt 23, 2024

lst-0131-book.cpp

// https://godbolt.org/z/dcKnx3Pno 
#include <iostream>
void print_cref(const int& n) {     // Parameter als konstante Referenz
    std::cout << n << " ";
}

int main() {
    int x = 5;
    print_cref(x);                  // Aufruf mit einer Variablen
    print_cref(42);                 // Aufruf mit einem konstanten Literal
}

Okt 23, 2024

lst-0131-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dcKnx3Pno 
#include <iostream>
void print_cref(const int& n) {     // Parameter als konstante Referenz
    std::cout << n << " ";
}

int main() {
    int x = 5;
    print_cref(x);                  // Aufruf mit einer Variablen
    print_cref(42);                 // Aufruf mit einem konstanten Literal
}

Okt 23, 2024

lst-0107-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/P9z8n8v16 
#include <fstream>
int main(int argc, char* argv[]) {
    int wert = 0;
    std::ifstream meineEingabe{"input1.txt"};
    meineEingabe >> wert;
}

Okt 23, 2024

lst-0143-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/58cTfvYhe 
int zwei() { return 2; }      //             (ERR)  einmal int als Rückgabetyp
double zwei() { return 2.0; } //             (ERR)   und einmal double
int main() {
    int x = zwei();
    double y = zwei();
}

Okt 23, 2024

lst-0118-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1WG8zvhYe 
#include <vector>
#include <iostream>                  // cout, endl
int main() {
  std::vector qus{1,4,9,16,25};
  for(auto it = qus.begin(); it!=qus.end(); ++it) // zwischen begin() und end()
    std::cout << *it << " ";         // mit *it kommen Sie vom Iterator zum Element
  std::cout << std::endl;
}

Okt 23, 2024

lst-0157-book.cpp

// https://godbolt.org/z/dMvqG85fr 
double add(double a, double b) { return a + b; }
double add(int, int) = delete;   // add(3,4) verbieten

Okt 23, 2024

lst-0133-book.cpp

// https://godbolt.org/z/fTvT5sKqY 
#include <iostream>
void verdopple(double &zahl) {     // Ausgabeparameter als veränderbare Referenz
    zahl *= 2.0;
}

int main() {
    double zahl = 7.25;
    verdopple(zahl);
    std::cout << zahl << "\n";     // nun 14.5
}

Okt 23, 2024

lst-0116-book.cpp

// https://godbolt.org/z/hhhavG5he 
#include <vector>
#include <iostream>                     // cout, endl
int main() {
    std::vector quadrate{1,4,9,16,25};  // gefüllt initialisieren
    for(int zahl : quadrate)  // zahl ist ein Quadrat nach dem anderen
        std::cout << zahl << " ";
    std::cout << std::endl;
}

Okt 23, 2024

lst-0127-book.cpp

// https://godbolt.org/z/5ssc6W5o6 
#include <iostream>              // cout
#include <cmath>                 // sin
#include <string>
#include <vector>
using std::sin;
int main() {
    std::cout << "sin(0.0): " << sin(0.0) << "\n";  // Aufruf von sin() mit Literal
    double winkel = 3.1415/2;
    std::cout << "sin("<<winkel<<"): "<<sin(winkel)<<"\n"; // Aufruf mit Variable
    std::string name = "Han Solo";
    std::cout << name.length() << "\n"; // Aufruf einer Methode
                                        // … konzeptionell wie length(name)
    std::vector<int> data{};
    data.push_back(5);                 // weiterer Methodenaufruf mit Parameter
    data.push_back(10);
    std::cout << data.back() << " ";
    data.pop_back();
    std::cout << data.back() << "\n";
    data.pop_back();
}

Okt 23, 2024

lst-0130-book.cpp

// https://godbolt.org/z/63dTshz3Y 
#include <iostream>
void print_ref8(int& n) {           // Parameter als Referenz
    std::cout << n << " ";
    n = 8;                          // setzt Parameter auf 8
    std::cout << n << "\n";
}
int main() {
    int x = 5;
    print_ref8(x);                  // x als Referenz: druckt 5, dann 8
    std::cout << x << "\n";         // x ist nun 8
}

Okt 23, 2024

lst-0143-book.cpp

// https://godbolt.org/z/58cTfvYhe 
int zwei() { return 2; }      //             (ERR)  einmal int als Rückgabetyp…
double zwei() { return 2.0; } //             (ERR)  … und einmal double
int main() {
    int x = zwei();
    double y = zwei();
}

Okt 23, 2024

lst-0130-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/63dTshz3Y 
#include <iostream>
void print_ref8(int& n) {           // Parameter als Referenz
    std::cout << n << " ";
    n = 8;                          // setzt Parameter auf 8
    std::cout << n << "\n";
}
int main() {
    int x = 5;
    print_ref8(x);                  // x als Referenz: druckt 5, dann 8
    std::cout << x << "\n";         // x ist nun 8
}

Okt 23, 2024

lst-0113-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zfe7dM4ex 
#include <array>
#include <iostream>
constexpr size_t MONATE = 12; /* Monate im Jahr */
int main() {
    std::array<unsigned,MONATE> mtage = {     // okay mit einer Konstante
        31,28,31,30,31,30,31,31,30,31,30,31};
    unsigned alter = 0;
    std::cout << "Wie alt sind Sie? "; std::cin >> alter;
    std::array<int,alter> lebensjahre;       // Arraygröße geht nicht per Variable
}

Okt 23, 2024

lst-0108-book.cpp

//https://godbolt.org/z/ssW3eKEGq 
#include <iostream> // cerr
#include <fstream>
int main(int argc, char* argv[]) {
    int wert;
    std::ifstream meineEingabe{"input1.txt"};
    if(!meineEingabe) {
        std::cerr << "Fehler beim Öffnen der Datei!\n";
    } else {
        meineEingabe >> wert;
    }
}

Okt 23, 2024

lst-0118-book.cpp

// https://godbolt.org/z/1WG8zvhYe 
#include <vector>
#include <iostream>                  // cout, endl
int main() {
  std::vector qus{1,4,9,16,25};
  for(auto it = qus.begin(); it!=qus.end(); ++it) // zwischen begin() und end()
    std::cout << *it << " ";         // mit *it kommen Sie vom Iterator zum Element
  std::cout << std::endl;
}

Okt 23, 2024

lst-0144-book.cpp

// https://godbolt.org/z/evGqG1oqa 
int verdopple(int a) { return a * 2; }
double verdopple(double a) { return a * 2.0; }
int main() {
    int x = verdopple(7);
    double y = verdopple(7.0);
}

Okt 23, 2024

lst-0116-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hhhavG5he 
#include <vector>
#include <iostream>                     // cout, endl
int main() {
    std::vector quadrate{1,4,9,16,25};  // gefüllt initialisieren
    for(int zahl : quadrate)  // zahl ist ein Quadrat nach dem anderen
        std::cout << zahl << " ";
    std::cout << std::endl;
}

Okt 23, 2024

lst-0115-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/T9jsEoMj4 
#include <vector>                    // Sie benötigen diesen Header
int main() {
    std::vector<int> quadrate{};     // leer initialisieren
    for(int idx = 0; idx<100; ++idx) {
        quadrate.push_back(idx*idx); // Anfügen eines Elements
    }
}

Okt 23, 2024

lst-0158-book.cpp

// https://godbolt.org/z/8Gdso36zf 
class Widget : public Base {
    explicit Widget(int);     // keine automatische Konvertierung von int
    ~Widget();                // Destruktor mit ~ vor dem Namen
    virtual void update();    // vorangestelltes virtual
    void calc1() override;    // nachgestelltes override
    void calc2() final;       // nachgestelltes final
    void draw() const;        // nachgestelltes const
    virtual void paint() = 0; // abstrakte Methode
};

Okt 23, 2024

lst-0107-book.cpp

//https://godbolt.org/z/P9z8n8v16 
#include <fstream>
int main(int argc, char* argv[]) {
    int wert = 0;
    std::ifstream meineEingabe{"input1.txt"};
    meineEingabe >> wert;
}

Okt 23, 2024

lst-0140-book.cpp

// https://godbolt.org/z/9YcPraT15 
#include <iostream>
void print(int wert) { std::cout << "int-Wert: " << wert << "\n"; }
void print(double wert) { std::cout << "double-Wert: " << wert << "\n"; }
void print(int w1, double w2) { std::cout << "Werte: "<<w1<<", "<<w2<<"\n"; }
int add(int n, int m) { return n + m; }
double add(double a, double b) { return a + b; }
int main() {
    print( add(3, 4) );        // add(int, int) und print(int)
    print( add(3.25f, 1.5f) ); // add(double, double) und print(double)
    print( 7, 3.25 );          // print(int, double)
}

Okt 23, 2024

lst-0129-book.cpp

// https://godbolt.org/z/8zcvMdM3b 
#include <iostream>

void print_val8(int n) {            // Parameter als Wert
    std::cout << n << " ";
    n = 8;                          // setzt Parameter auf 8
    std::cout << n << "\n";
}

int main() {
    int x = 5;
    print_val8(x);                  // x als Wert: druckt 5, dann 8
    std::cout << x << "\n";         // x ist unverändert 5
    print_val8(42);                 // 42 als Wert: druckt 42, dann 8
}

Okt 23, 2024

lst-0112-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cd1d1W7T1 
#include <array>
#include <iostream>
using std::cout; using std::array; using std::string;
int main() {
  array<string,7> wotag = { "Montag", "Dienstag",        // definieren
      "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag" };
  cout << "Die Woche beginnt mit " << wotag[0] << ".\n"; // Werte lesen
  cout << "Sie endet mit " << wotag.at(6) << ".\n";      // sicheres Werte lesen
  /* nordisch? */
  wotag[5] = "Sonnabend";                                // Werte verändern
}

Okt 23, 2024

lst-0114-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a4zxbd99z 
#include <array>
#include <algorithm>                    // accumulate
#include <numeric>                      // iota
using Januar = std::array<int,31>;      // Alias für wiederholte Verwendung

void initJanuar(Januar& jan) {          // das genaue Array als Parameter
    std::iota(begin(jan), end(jan), 1); // füllt mit  1, 2, 3  31
}
int sumJanuar(const Januar& jan) {      // das genaue Array als Parameter
    return std::accumulate(begin(jan), end(jan), 0); // Hilfsfunktion für Summe
}
int main() {
    Januar jan;                         // deklariert ein array<int,31>
    initJanuar( jan );
    int sum = sumJanuar( jan );
}

Okt 23, 2024

lst-0147-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fjc37rvEr 
int add(int n=0, int m=0, int o=0, int p=0, int q=0) {
    return n+m+o+p+q;
}
int main() {
    std::cout << add(1,2,3,4,5) << "\n";
    std::cout << add(1,2,3,4) << "\n"; // wie add(1,2,3,4,0)
    std::cout << add(1,2,3) << "\n";   // wie add(1,2,3,0,0)
    std::cout << add(1,2) << "\n";     // wie add(1,2,0,0,0)
    std::cout << add(1) << "\n";       // wie add(1,0,0,0,0)
    std::cout << add() << "\n";        // wie add(0,0,0,0,0)
}

Okt 23, 2024

lst-0108-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/ssW3eKEGq 
#include <iostream> // cerr
#include <fstream>
int main(int argc, char* argv[]) {
    int wert;
    std::ifstream meineEingabe{"input1.txt"};
    if(!meineEingabe) {
        std::cerr << "Fehler beim Öffnen der Datei!\n";
    } else {
        meineEingabe >> wert;
    }
}

Okt 23, 2024

lst-0059-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5hqanTeYh 
#include <iostream>
#include <bitset>  // hilft bei der Ausgabe von Zahlen als Bitfolge
int main() {
    int a = 0;
    for(int idx=0; idx<8; idx++) {
        a <<= 2;                       // um zwei Bit nach links schieben: "…100"
        a |= 1;                        // unterstes Bit setzen: "…1"
    }
    std::cout << std::bitset<16>(a) << "\n"; // 0101010101010101
    std::cout << a << "\n";            // 21845
}

Okt 23, 2024

lst-0106-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/McqfcWb8j 
#include <fstream>
int main(int argc, char* argv[]) {
    std::ofstream meineAusgabe{"output1.txt"};
    meineAusgabe << "Zeile 1\n";
    meineAusgabe << "Zeile 2\n";
}

Okt 23, 2024

lst-0105-book.cpp

//https://godbolt.org/z/a6qqbWKMs 
#include <cstdlib>
#include <iostream>

int main(int argc, char* argv[]) {
    for(int i=1; i<argc; ++i) {                // Start bei 1
        for(char* p=argv[i]; *p!='\0'; ++p) {
            char c = toupper(*p);
            std::cout << c;
        }
        std::cout << ' ';
    }
    std::cout << '\n';
}

Okt 23, 2024

lst-0106-book.cpp

//https://godbolt.org/z/McqfcWb8j 
#include <fstream>
int main(int argc, char* argv[]) {
    std::ofstream meineAusgabe{"output1.txt"};
    meineAusgabe << "Zeile 1\n";
    meineAusgabe << "Zeile 2\n";
}

Okt 23, 2024

lst-0079-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zGso3xGcj 
#include <vector>
#include <cstddef>  // size_t
int main() {
    std::vector<int> data = {  100, -4, 6'699, 88, 0,  } ;
    int sum = 0;
    for(size_t idx = 0; idx < data.size(); ++idx) { // ein bestimmter int-Typ
        sum += data[idx];
    }
}

Okt 23, 2024

lst-0076-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ebPcdxzvj 
#include <iostream>
int main() {
    std::cout << 3 + 4 * 5 + 6 << "\n";               // 29
    std::cout << 20/7 << " Rest " << 20%7 << "\n";    // 2 Rest 6
}

Okt 23, 2024

lst-0074-book.cpp

// https://godbolt.org/z/3Y65Ps6G4 
#include <iostream>   // cin, cout für Eingabe und Ausgabe

void eingabe(unsigned &gebTag_,
             unsigned &gebMonat_,
             unsigned &gebJahr_,
             unsigned long long &steuernummer_,
             double &koerperlaenge_) 
{
    /* Eingaben noch ohne gute Fehlerbehandlung... */
    std::cout << "Geb.-Tag: "; std::cin >> gebTag_;
    std::cout << "Geb.-Monat: "; std::cin >> gebMonat_;
    std::cout << "Geb.-Jahr: "; std::cin >> gebJahr_;
    std::cout << "Steuernummer: "; std::cin >> steuernummer_;
    std::cout << "Koerperlaenge: "; std::cin >> koerperlaenge_;
}
int main() {
    /* Daten */
    unsigned gebTag_ = 0;
    unsigned gebMonat_ = 0;
    unsigned gebJahr_ = 0;
    unsigned long long steuernummer_ = 0;
    double koerperlaenge_ = 0.0;
    /* Eingabe */
    eingabe(gebTag_, gebMonat_, gebJahr_, steuernummer_, koerperlaenge_);
    /* Berechnungen */
    // …
}

Okt 23, 2024

lst-0083-book.cpp

// https://godbolt.org/z/v98fWc49E 
#include <iostream>
#include <cmath>  // fpclassify
#include <limits> // numeric_limits
#include <string>
std::string fpklass(double x) {
    switch(std::fpclassify(x)) {
        case FP_INFINITE:  return "unendlich";
        case FP_NAN:       return "NaN";
        case FP_NORMAL:    return "normal";
        case FP_SUBNORMAL: return "subnormal";
        case FP_ZERO:      return "Null";
        default:           return "unbekannt";
    }
}
int main() {
    const auto dmin = std::numeric_limits<double>::min();
    std::cout
      <<"1.0/0.0 ist "<<fpklass(1/0.0)<<'\n'   // Ausgabe: 1.0/0.0 ist unendlich
      <<"0.0/0.0 ist "<<fpklass(0.0/0.0)<<'\n' // Ausgabe: 0.0/0.0 ist NaN
      <<"dmin/2 ist "<<fpklass(dmin/2)<<'\n'   // Ausgabe: dmin/2 ist subnormal
      <<"-0.0 ist "<<fpklass(-0.0)<<'\n'       // Ausgabe: –0.0 ist null
      <<"1.0 ist "<<fpklass(1.0)<<'\n';        // Ausgabe: 1.0 ist normal
}

Okt 23, 2024

lst-0082-book.cpp

// https://godbolt.org/z/6qfo4oYnr 
#include <iostream>
#include <iomanip> // fixed, setprecision
int main() {
    std::cout << std::setprecision(30) << std::fixed;     // immer 30 Stellen
                                                          // ausgeben
    std::cout <<  1.111222333444555666777888999f << "\n"; // float-Literal
    // Ausgabe: 1.111222386360168457031250000000
    std::cout <<  1.111222333444555666777888999 << "\n";  // double ist Default
    // Ausgabe: 1.111222333444555676607023997349
    std::cout <<  1.111222333444555666777888999d << "\n"; // double-Literal
    // Ausgabe: 1.111222333444555676607023997349
    std::cout <<  1.111222333444555666777888999L << "\n"; // long double
    // Ausgabe: 1.111222333444555666740784227731
}

Okt 23, 2024

lst-0099-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vMvs47nfs 
#include <iostream>       // cin, cout für Eingabe und Ausgabe
#include <string>         // Sie benötigen diesen Header der Standardbibliothek

void eingabe(
    std::string &name,    // als Parameter
    unsigned &gebJahr)
{
    /* Eingaben noch ohne gute Fehlerbehandlung... */
    std::cout << "Name: ";
    std::getline(std::cin, name); // getline liest in einen String ein
    if(name.length() == 0) {      // length ist eine Methode von string
        std::cout << "Sie haben einen leeren Namen eingegeben.\n";
        exit(1);
    }
    std::cout << "Geb.-Jahr: ";
    std::cin >> gebJahr;
}
int main() {
    /* Daten */
    std::string name;             // definiert und initialisiert eine string-Variable
    unsigned gebJahr = 0;
    /* Eingabe */
    eingabe(name, gebJahr);
    /* Berechnungen */
    // 
}

Okt 23, 2024

lst-0098-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4TMn37qhE 
#include <iostream>
int func ( int arg1, int arg2 )
{
  if (arg1 > arg2)
    return arg1 - arg2;
  else
    return arg2 - arg1;
}
int main ( int argc, const char *argv[] )
{
  for ( int x = 0 ; x < 10 ; ++x )
  {
    for ( int y = 0 ; y < 10 ; ++y )
      std::cout << func ( x, y ) << " ";
    std::cout << "\n";
  }
}

Okt 23, 2024

lst-0087-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/863b1z4GY 
int main() {
   std::cout << std::setprecision(15) << std::fixed;
   dreieck(100'000.0f, 99'999.999'79f, 0.000'29f);
   dreieck(100'000.0,  99'999.999'79,  0.000'29);
}

Okt 23, 2024

lst-0081-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/f7T5Y6sd3 
#include <iostream>
#include <iomanip>                              // fixed, setprecision
using std::cout;                                // abgekürzt cout
int main() {
    cout << std::setprecision(2) << std::fixed; // zwei Nachkommastellen
    cout << "1/4: " << 0.25 << "\n";            // Kommaschreibweise für double
    // Ausgabe: 1/4: 0.25

    cout << "2/4: " << 0.5 << "\n";
    // Ausgabe: 2/4: 0.50
    cout << "3/4: " << 0.75 << "\n";
    // Ausgabe: 3/4: 0.75
    cout << "4/4: " << 1 << " oder " << 1.0 << "\n"; //                     (ERR)  erkennt 1 als int
    // Ausgabe 4/4: 1 oder 1.00
    cout << "1e0: " << 1e0 << "\n";             // wissenschaftliche Schreibweise
    // Ausgabe: 1e0: 1.00
    cout << "0x10.1p0: " << 0x10.1p0 << "\n";   // hexadezimale Schreibweise
    // Ausgabe: 0x10.1p0: 16.06
}

Okt 23, 2024

lst-0068-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xrMYz93WP 
int main() {
    for(int w1 = 1; w1 <= 6; ++w1) { // 1..6
        for(int w2 = 0; w2 < 10; ++w2) { // 0..9
            int max = w1 > w2 ? w1 : w2;  // ternärer Operator
        }
    }
}

Okt 23, 2024

lst-0079-book.cpp

// https://godbolt.org/z/zGso3xGcj 
#include <vector>
#include <cstddef>  // size_t
int main() {
    std::vector<int> data = {  100, -4, 6'699, 88, 0,  } ;
    int sum = 0;
    for(size_t idx = 0; idx < data.size(); ++idx) { // ein bestimmter int-Typ
        sum += data[idx];
    }
}

Okt 23, 2024

lst-0057-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TTjxzrYf3 
#include <iostream>
#include <bitset>
constexpr unsigned n_bits = sizeof(unsigned short)*8; // 8 Bit pro char
auto bits_umdrehen(unsigned val) -> unsigned short {
  unsigned short ret = 0;
  for (unsigned i = 0; i < n_bits; ++i ) {
    ret = (ret << 1) | (val & 1);   // eins zur Seite, unterstes evtl. setzen
    val >>= 1;                      // eins in die andere Richtung
  }
  return ret;
}
void zeig(unsigned short val) {
    std::bitset<n_bits> bits{val};
    std::cout << val << "=" << bits << " -> ";
    auto lav = bits_umdrehen(val);
    std::bitset<n_bits> stib{lav};
    std::cout << lav << "=" << stib << "\n";
}
int main() {
    zeig(36u);  // Ausgabe: 36=0000000000100100 -> 9216=0010010000000000
    zeig(199u); // Ausgabe: 199=0000000011000111 -> 58112=1110001100000000
    zeig(255u); // Ausgabe: 255=0000000011111111 -> 65280=1111111100000000
    zeig(256u); // Ausgabe: 256=0000000100000000 -> 128=0000000010000000
}

Okt 23, 2024

lst-0097-book.cpp

// https://godbolt.org/z/eP77v498E 
#include <iostream>
int func(int arg1, int arg2) {
    if(arg1 > arg2) {
        return arg1-arg2;
    } else {
        return arg2-arg1;
    }
}
int main(int argc, const char* argv[]) {
    for(int x=0; x<10; ++x) {
        for(int y=0; y<10; ++y) {
            std::cout << func(x,y) << " ";
        }
        std::cout << "\n";
    }
}

Okt 23, 2024

lst-0083-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/v98fWc49E 
#include <iostream>
#include <cmath>  // fpclassify
#include <limits> // numeric_limits
#include <string>
std::string fpklass(double x) {
    switch(std::fpclassify(x)) {
        case FP_INFINITE:  return "unendlich";
        case FP_NAN:       return "NaN";
        case FP_NORMAL:    return "normal";
        case FP_SUBNORMAL: return "subnormal";
        case FP_ZERO:      return "Null";
        default:           return "unbekannt";
    }
}
int main() {
    const auto dmin = std::numeric_limits<double>::min();
    std::cout
      <<"1.0/0.0 ist "<<fpklass(1/0.0)<<'\n'   // Ausgabe: 1.0/0.0 ist unendlich
      <<"0.0/0.0 ist "<<fpklass(0.0/0.0)<<'\n' // Ausgabe: 0.0/0.0 ist NaN
      <<"dmin/2 ist "<<fpklass(dmin/2)<<'\n'   // Ausgabe: dmin/2 ist subnormal
      <<"-0.0 ist "<<fpklass(-0.0)<<'\n'       // Ausgabe: 0.0 ist null
      <<"1.0 ist "<<fpklass(1.0)<<'\n';        // Ausgabe: 1.0 ist normal
}

Okt 23, 2024

lst-0095-book.cpp

// https://godbolt.org/z/eW1cfYcGs 
#include <iostream>
void ausgabe(int a, int b) {
    std::cout << a << ' ' << b << '\n';
}
int zahl() {
    static int val = 0;
    return ++val;
}
int main() {
    ausgabe(zahl(), zahl()); // in welcher Reihenfolge?
}

Okt 23, 2024

lst-0093-book.cpp

// https://godbolt.org/z/43rYYeKx9 
#include <iostream>
#include <iomanip>    // setprecision, fixed
#include <complex>
using std::cout; using std::complex;

int main() {
    using namespace std::complex_literals;   // für i-Suffix
    cout << std::fixed << std::setprecision(1);
    complex<double> z1 = 1i * 1i;            // i mal i
    cout << z1 << '\n';                      // Ausgabe: (–1.0,0.0)
    complex<double> z2 = std::pow(1i, 2);    // i-Quadrat
    cout << z2 << '\n';                      // Ausgabe: (–1.0,0.0)
    double PI = std::acos(-1);               // Länge eines halben Einheitskreises
    complex<double> z3 = std::exp(1i * PI);  // Euler-Formel
    cout << z3 << '\n';                      // Ausgabe: (–1.0,0.0)
    complex<double> a(3, 4);                 // gewohnt als Konstruktor
    complex<double> b = 1. - 2i;             // praktisch als Literal

    // Berechnungen:
    cout << "a + b = " << a + b << "\n";     // Ausgabe: a + b = (4.0,2.0)
    cout << "a * b = " << a * b << "\n";     // Ausgabe: a * b = (11.0,–2.0)
    cout << "a / b = " << a / b << "\n";     // Ausgabe: a / b = (–1.0,2.0)
    cout << "|a| = "   << abs(a) << "\n";    // Ausgabe: |a| = 5.0
    cout << "conj(a) = " << conj(a) << "\n"; // Ausgabe: conj(a) = (3.0,–4.0)
    cout << "norm(a) = " << norm(a) << "\n"; // Ausgabe: norm(a) = 25.0
    cout << "abs(a) = " << abs(a) << "\n";   // Ausgabe: abs(a) = 5.0
    cout << "exp(a) = " << exp(a) << "\n";   // Ausgabe: exp(a) = (–13.1,–15.2)
}

Okt 23, 2024

lst-0077-book.cpp

// https://godbolt.org/z/jeTs5Exqx 
#include <iostream>
int main() {
    unsigned a = 0b1111'0000;       // 240
    unsigned b = 0b0011'1100;       // 60
    std::cout << ( a | b ) << "\n"; // Bit-Oder: 252, in Bits 1111'1100
    std::cout << ( a & b ) << "\n"; // Bit-Und: 48, in Bits 0011'0000
    std::cout << ( a ^ b ) << "\n"; // Exklusiv-Oder: 204, in Bits 1100'1100
    unsigned int c = 170;           // in Bits 0..(24x0)..0'1010'1010
    std::cout << ( ~c ) << "\n";    // Inv.: 4294967125, Bits: 1..(24x1)..1'0101'0101
}

Okt 23, 2024

lst-0105-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/a6qqbWKMs 
#include <cstdlib>
#include <iostream>

int main(int argc, char* argv[]) {
    for(int i=1; i<argc; ++i) {                // Start bei 1
        for(char* p=argv[i]; *p!='\0'; ++p) {
            char c = toupper(*p);
            std::cout << c;
        }
        std::cout << ' ';
    }
    std::cout << '\n';
}

Okt 23, 2024

lst-0080-book.cpp

// https://godbolt.org/z/h86Wh5dbo 
#include <iostream>      // cout
#include <iomanip>       // setprecision, etc.
#include <cmath>         // fabs
using std::cout;         // cout als Abkürzung für std::cout
int main() {
    cout << std::fixed << std::setprecision(25);  // für besser lesbare Ausgabe
    // 0.1 und 0.01 kann double nicht exakt speichern
    double x = 0.1 * 0.1;
    cout << "0.1*0.1: " << x << "\n";
    // Ausgabe: 0.1*0.1: 0.0100000000000000019428903
    if(x == 0.01) {      //                 (ERR)  vergleichen Sie double niemals mit ==
        cout << "Ja! x == 0.01" << "\n";
    } else {
        cout << "Oh-oh! x != 0.01" << "\n";      // Sie sehen diese Ausgabe
    }
    // Achtung vor allem beim Vergleich mit 0.0
    double null = x - 0.01;
    cout << "null: " << null << "\n";
    // Ausgabe: null: 0.0000000000000000017347235
    if(std::fabs(null) < 0.00000001) {           // gegen ein "Epsilon"
        cout << "Ja! null ist nahe 0.0" << "\n"; // Sie sehen diese Ausgabe
    } else {
        cout << "Oh-oh! null nicht nahe 0.0" << "\n";
    }
    // Brüche von 2er-Potenzen sind weniger kritisch
    double y = 0.5 * 0.5; 
    cout << "0.5*0.5: " <<  y << "\n";
    // Ausgabe: 0.5*0.5: 0.2500000000000000000000000
    if(y == 0.25) {    // hier klappt der gefährliche Vergleich ausnahmsweise
        cout << "Ja! y == 0.25" << "\n";         // Sie sehen diese Ausgabe
    } else {
        cout << "Oh-oh! y != 0.25" << "\n";
    }
    //
    return 0;
}

Okt 23, 2024

lst-0057-book.cpp

// https://godbolt.org/z/TTjxzrYf3 
#include <iostream>
#include <bitset>
constexpr unsigned n_bits = sizeof(unsigned short)*8; // 8 Bit pro char
auto bits_umdrehen(unsigned val) -> unsigned short {
  unsigned short ret = 0;
  for (unsigned i = 0; i < n_bits; ++i ) {
    ret = (ret << 1) | (val & 1);   // eins zur Seite, unterstes evtl. setzen
    val >>= 1;                      // eins in die andere Richtung
  }
  return ret;
}
void zeig(unsigned short val) {
    std::bitset<n_bits> bits{val};
    std::cout << val << "=" << bits << " -> ";
    auto lav = bits_umdrehen(val);
    std::bitset<n_bits> stib{lav};
    std::cout << lav << "=" << stib << "\n";
}
int main() {
    zeig(36u);  // Ausgabe: 36=0000000000100100 -> 9216=0010010000000000
    zeig(199u); // Ausgabe: 199=0000000011000111 -> 58112=1110001100000000
    zeig(255u); // Ausgabe: 255=0000000011111111 -> 65280=1111111100000000
    zeig(256u); // Ausgabe: 256=0000000100000000 -> 128=0000000010000000
}

Okt 23, 2024

lst-0068-book.cpp

// https://godbolt.org/z/xrMYz93WP 
int main() {
    for(int w1 = 1; w1 <= 6; ++w1) { // 1..6
        for(int w2 = 0; w2 < 10; ++w2) { // 0..9
            int max = w1 > w2 ? w1 : w2;  // ternärer Operator
        }
    }
}

Okt 23, 2024

lst-0082-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6qfo4oYnr 
#include <iostream>
#include <iomanip> // fixed, setprecision
int main() {
    std::cout << std::setprecision(30) << std::fixed;     // immer 30 Stellen
                                                          // ausgeben
    std::cout <<  1.111222333444555666777888999f << "\n"; // float-Literal
    // Ausgabe: 1.111222386360168457031250000000
    std::cout <<  1.111222333444555666777888999 << "\n";  // double ist Default
    // Ausgabe: 1.111222333444555676607023997349
    std::cout <<  1.111222333444555666777888999d << "\n"; // double-Literal
    // Ausgabe: 1.111222333444555676607023997349
    std::cout <<  1.111222333444555666777888999L << "\n"; // long double
    // Ausgabe: 1.111222333444555666740784227731
}

Okt 23, 2024

lst-0059-book.cpp

// https://godbolt.org/z/5hqanTeYh 
#include <iostream>
#include <bitset>  // hilft bei der Ausgabe von Zahlen als Bitfolge
int main() {
    int a = 0;
    for(int idx=0; idx<8; idx++) {
        a <<= 2;                       // um zwei Bit nach links schieben: "…100"
        a |= 1;                        // unterstes Bit setzen: "…1"
    }
    std::cout << std::bitset<16>(a) << "\n"; // 0101010101010101
    std::cout << a << "\n";            // 21845
}

Okt 23, 2024

lst-0074-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3Y65Ps6G4 
#include <iostream>   // cin, cout für Eingabe und Ausgabe

void eingabe(unsigned &gebTag_,
             unsigned &gebMonat_,
             unsigned &gebJahr_,
             unsigned long long &steuernummer_,
             double &koerperlaenge_) 
{
    /* Eingaben noch ohne gute Fehlerbehandlung... */
    std::cout << "Geb.-Tag: "; std::cin >> gebTag_;
    std::cout << "Geb.-Monat: "; std::cin >> gebMonat_;
    std::cout << "Geb.-Jahr: "; std::cin >> gebJahr_;
    std::cout << "Steuernummer: "; std::cin >> steuernummer_;
    std::cout << "Koerperlaenge: "; std::cin >> koerperlaenge_;
}
int main() {
    /* Daten */
    unsigned gebTag_ = 0;
    unsigned gebMonat_ = 0;
    unsigned gebJahr_ = 0;
    unsigned long long steuernummer_ = 0;
    double koerperlaenge_ = 0.0;
    /* Eingabe */
    eingabe(gebTag_, gebMonat_, gebJahr_, steuernummer_, koerperlaenge_);
    /* Berechnungen */
    // 
}

Okt 23, 2024

lst-0076-book.cpp

// https://godbolt.org/z/ebPcdxzvj 
#include <iostream>
int main() {
    std::cout << 3 + 4 * 5 + 6 << "\n";               // 29
    std::cout << 20/7 << " Rest " << 20%7 << "\n";    // 2 Rest 6
}

Okt 23, 2024

lst-0088-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/drz7fzohh 
#include <iostream>
#include <iomanip> // setprecision, fixed
constexpr int bilderProSek = 25;
constexpr int laufZeitInSek = 3600;
constexpr int bilderInsg = laufZeitInSek * bilderProSek;
constexpr float bildzeit = 1.0f / bilderProSek;

int main() {
    float filmzeit = 0.f;
    for(int n=1; n <= bilderInsg; ++n) { // 1 .. bilderInsg
        filmzeit += bildzeit;// akkumulieren
        //  hier Code für dieses Frame 
    }
    std::cout << std::setprecision(10) << std::fixed
        << filmzeit << '\n'; // Ausgabe: 3602.2695312500
}

Okt 23, 2024

lst-0089-book.cpp

// https://godbolt.org/z/xz6TGdc19 
#include <iostream>
#include <iomanip> // setprecision, fixed
constexpr int bilderProSek = 25;
constexpr int laufZeitInSek = 3600;
constexpr int bilderInsg = laufZeitInSek * bilderProSek;
constexpr float bildzeit = 1.0f / bilderProSek;
int main() {
    float filmzeit = 0.f;
    for(int n=1; n <= bilderInsg; ++n) { // 1 .. bilderInsg, wegen Formel
        filmzeit = bildzeit * n; // skalieren
        // … hier Code für dieses Frame …
    }
    std::cout << std::setprecision(10) << std::fixed
        << filmzeit << '\n';     // Ausgabe: 3600.0000000000
}

Okt 23, 2024

lst-0089-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xz6TGdc19 
#include <iostream>
#include <iomanip> // setprecision, fixed
constexpr int bilderProSek = 25;
constexpr int laufZeitInSek = 3600;
constexpr int bilderInsg = laufZeitInSek * bilderProSek;
constexpr float bildzeit = 1.0f / bilderProSek;
int main() {
    float filmzeit = 0.f;
    for(int n=1; n <= bilderInsg; ++n) { // 1 .. bilderInsg, wegen Formel
        filmzeit = bildzeit * n; // skalieren
        //  hier Code für dieses Frame 
    }
    std::cout << std::setprecision(10) << std::fixed
        << filmzeit << '\n';     // Ausgabe: 3600.0000000000
}

Okt 23, 2024

lst-0080-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h86Wh5dbo 
#include <iostream>      // cout
#include <iomanip>       // setprecision, etc.
#include <cmath>         // fabs
using std::cout;         // cout als Abkürzung für std::cout
int main() {
    cout << std::fixed << std::setprecision(25);  // für besser lesbare Ausgabe
    // 0.1 und 0.01 kann double nicht exakt speichern
    double x = 0.1 * 0.1;
    cout << "0.1*0.1: " << x << "\n";
    // Ausgabe: 0.1*0.1: 0.0100000000000000019428903
    if(x == 0.01) {      //                 (ERR)  vergleichen Sie double niemals mit ==
        cout << "Ja! x == 0.01" << "\n";
    } else {
        cout << "Oh-oh! x != 0.01" << "\n";      // Sie sehen diese Ausgabe
    }
    // Achtung vor allem beim Vergleich mit 0.0
    double null = x - 0.01;
    cout << "null: " << null << "\n";
    // Ausgabe: null: 0.0000000000000000017347235
    if(std::fabs(null) < 0.00000001) {           // gegen ein "Epsilon"
        cout << "Ja! null ist nahe 0.0" << "\n"; // Sie sehen diese Ausgabe
    } else {
        cout << "Oh-oh! null nicht nahe 0.0" << "\n";
    }
    // Brüche von 2er-Potenzen sind weniger kritisch
    double y = 0.5 * 0.5; 
    cout << "0.5*0.5: " <<  y << "\n";
    // Ausgabe: 0.5*0.5: 0.2500000000000000000000000
    if(y == 0.25) {    // hier klappt der gefährliche Vergleich ausnahmsweise
        cout << "Ja! y == 0.25" << "\n";         // Sie sehen diese Ausgabe
    } else {
        cout << "Oh-oh! y != 0.25" << "\n";
    }
    //
    return 0;
}

Okt 23, 2024

lst-0086-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/We3oWrcWW 
#include <iostream>
#include <cmath>     // sqrt
#include <concepts>  // floating_point
using std::min; using std::max; using std::floating_point;

template<floating_point T> T heron(T a, T b, T c) {
    auto s = (a+b+c) / 2;
    return sqrt(s*(s-a)*(s-b)*(s-c));
}

template<floating_point T> T kahan(T a, T b, T c) {
   auto x = max(a,max(b,c));
   auto y = max(min(a,b), min(max(a,b),c));
   auto z = min(a,min(b,c));
   return sqrt( (x+(y+z))*(z-(x-y))*(z+(x-y))*(x+(y-z)) )/4 ;
}

template<floating_point T> void dreieck(T a, T b, T c) {
   std::cout << "heron: " << heron(a,b,c) << '\n';
   std::cout << "kahan: " << kahan(a,b,c) << '\n';
}

int main() {
   dreieck(3.0f, 4.0f, 5.0f);
}

Okt 23, 2024

lst-0099-book.cpp

// https://godbolt.org/z/vMvs47nfs 
#include <iostream>       // cin, cout für Eingabe und Ausgabe
#include <string>         // Sie benötigen diesen Header der Standardbibliothek

void eingabe(
    std::string &name,    // als Parameter
    unsigned &gebJahr)
{
    /* Eingaben noch ohne gute Fehlerbehandlung... */
    std::cout << "Name: ";
    std::getline(std::cin, name); // getline liest in einen String ein
    if(name.length() == 0) {      // length ist eine Methode von string
        std::cout << "Sie haben einen leeren Namen eingegeben.\n";
        exit(1);
    }
    std::cout << "Geb.-Jahr: ";
    std::cin >> gebJahr;
}
int main() {
    /* Daten */
    std::string name;             // definiert und initialisiert eine string-Variable
    unsigned gebJahr = 0;
    /* Eingabe */
    eingabe(name, gebJahr);
    /* Berechnungen */
    // …
}

Okt 23, 2024

lst-0070-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vd85f7rMj 
#include <iostream>
int main() {
    int arr[] = { 8,3,7,3,11,999,5,6,7 };
    int len = 9;
    for(int i=0, *p=arr; i<len && *p!=999; ++i, ++p) { // erst ++i, dann ++p
        std::cout << i << ":" << *p << " ";
    }
    std::cout << "\n";
    // Ausgabe: 0:8 1:3 2:7 3:3 4:11
}

Okt 23, 2024

lst-0095-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eW1cfYcGs 
#include <iostream>
void ausgabe(int a, int b) {
    std::cout << a << ' ' << b << '\n';
}
int zahl() {
    static int val = 0;
    return ++val;
}
int main() {
    ausgabe(zahl(), zahl()); // in welcher Reihenfolge?
}

Okt 23, 2024

lst-0070-book.cpp

// https://godbolt.org/z/vd85f7rMj 
#include <iostream>
int main() {
    int arr[] = { 8,3,7,3,11,999,5,6,7 };
    int len = 9;
    for(int i=0, *p=arr; i<len && *p!=999; ++i, ++p) { // erst ++i, dann ++p
        std::cout << i << ":" << *p << " ";
    }
    std::cout << "\n";
    // Ausgabe: 0:8 1:3 2:7 3:3 4:11
}

Okt 23, 2024

lst-0069-book.cpp

// https://godbolt.org/z/rq66cWr3d 
int main() {
    int a = 0;
    int b = 0;
    for(int w1 = 1; w1 <= 6; ++w1) { // 1..6
        for(int w2 = 0; w2 < 10; ++w2) { // 0..9
            int max = w1 > w2 ? (a+=b , w1) :( b+=1 , w2); // Sequenzoperator
        }
    }
}

Okt 23, 2024

lst-0081-book.cpp

// https://godbolt.org/z/f7T5Y6sd3 
#include <iostream>
#include <iomanip>                              // fixed, setprecision
using std::cout;                                // abgekürzt cout
int main() {
    cout << std::setprecision(2) << std::fixed; // zwei Nachkommastellen
    cout << "1/4: " << 0.25 << "\n";            // Kommaschreibweise für double
    // Ausgabe: 1/4: 0.25

    cout << "2/4: " << 0.5 << "\n";
    // Ausgabe: 2/4: 0.50
    cout << "3/4: " << 0.75 << "\n";
    // Ausgabe: 3/4: 0.75
    cout << "4/4: " << 1 << " oder " << 1.0 << "\n"; //                     (ERR)  erkennt 1 als int
    // Ausgabe 4/4: 1 oder 1.00
    cout << "1e0: " << 1e0 << "\n";             // wissenschaftliche Schreibweise
    // Ausgabe: 1e0: 1.00
    cout << "0x10.1p0: " << 0x10.1p0 << "\n";   // hexadezimale Schreibweise
    // Ausgabe: 0x10.1p0: 16.06
}

Okt 23, 2024

lst-0069-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rq66cWr3d 
int main() {
    int a = 0;
    int b = 0;
    for(int w1 = 1; w1 <= 6; ++w1) { // 1..6
        for(int w2 = 0; w2 < 10; ++w2) { // 0..9
            int max = w1 > w2 ? (a+=b , w1) :( b+=1 , w2); // Sequenzoperator
        }
    }
}

Okt 23, 2024

lst-0098-book.cpp

// https://godbolt.org/z/4TMn37qhE 
#include <iostream>
int func ( int arg1, int arg2 )
{
  if (arg1 > arg2)
    return arg1 - arg2;
  else
    return arg2 - arg1;
}
int main ( int argc, const char *argv[] )
{
  for ( int x = 0 ; x < 10 ; ++x )
  {
    for ( int y = 0 ; y < 10 ; ++y )
      std::cout << func ( x, y ) << " ";
    std::cout << "\n";
  }
}

Okt 23, 2024

lst-0087-book.cpp

// https://godbolt.org/z/863b1z4GY 
int main() {
   std::cout << std::setprecision(15) << std::fixed;
   dreieck(100'000.0f, 99'999.999'79f, 0.000'29f);
   dreieck(100'000.0,  99'999.999'79,  0.000'29);
}

Okt 23, 2024

lst-0088-book.cpp

// https://godbolt.org/z/drz7fzohh 
#include <iostream>
#include <iomanip> // setprecision, fixed
constexpr int bilderProSek = 25;
constexpr int laufZeitInSek = 3600;
constexpr int bilderInsg = laufZeitInSek * bilderProSek;
constexpr float bildzeit = 1.0f / bilderProSek;

int main() {
    float filmzeit = 0.f;
    for(int n=1; n <= bilderInsg; ++n) { // 1 .. bilderInsg
        filmzeit += bildzeit;// akkumulieren
        // … hier Code für dieses Frame …
    }
    std::cout << std::setprecision(10) << std::fixed
        << filmzeit << '\n'; // Ausgabe: 3602.2695312500
}

Okt 23, 2024

lst-0097-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eP77v498E 
#include <iostream>
int func(int arg1, int arg2) {
    if(arg1 > arg2) {
        return arg1-arg2;
    } else {
        return arg2-arg1;
    }
}
int main(int argc, const char* argv[]) {
    for(int x=0; x<10; ++x) {
        for(int y=0; y<10; ++y) {
            std::cout << func(x,y) << " ";
        }
        std::cout << "\n";
    }
}

Okt 23, 2024

lst-0093-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/43rYYeKx9 
#include <iostream>
#include <iomanip>    // setprecision, fixed
#include <complex>
using std::cout; using std::complex;

int main() {
    using namespace std::complex_literals;   // für i-Suffix
    cout << std::fixed << std::setprecision(1);
    complex<double> z1 = 1i * 1i;            // i mal i
    cout << z1 << '\n';                      // Ausgabe: (1.0,0.0)
    complex<double> z2 = std::pow(1i, 2);    // i-Quadrat
    cout << z2 << '\n';                      // Ausgabe: (1.0,0.0)
    double PI = std::acos(-1);               // Länge eines halben Einheitskreises
    complex<double> z3 = std::exp(1i * PI);  // Euler-Formel
    cout << z3 << '\n';                      // Ausgabe: (1.0,0.0)
    complex<double> a(3, 4);                 // gewohnt als Konstruktor
    complex<double> b = 1. - 2i;             // praktisch als Literal

    // Berechnungen:
    cout << "a + b = " << a + b << "\n";     // Ausgabe: a + b = (4.0,2.0)
    cout << "a * b = " << a * b << "\n";     // Ausgabe: a * b = (11.0,2.0)
    cout << "a / b = " << a / b << "\n";     // Ausgabe: a / b = (1.0,2.0)
    cout << "|a| = "   << abs(a) << "\n";    // Ausgabe: |a| = 5.0
    cout << "conj(a) = " << conj(a) << "\n"; // Ausgabe: conj(a) = (3.0,4.0)
    cout << "norm(a) = " << norm(a) << "\n"; // Ausgabe: norm(a) = 25.0
    cout << "abs(a) = " << abs(a) << "\n";   // Ausgabe: abs(a) = 5.0
    cout << "exp(a) = " << exp(a) << "\n";   // Ausgabe: exp(a) = (13.1,15.2)
}

Okt 23, 2024

lst-0077-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jeTs5Exqx 
#include <iostream>
int main() {
    unsigned a = 0b1111'0000;       // 240
    unsigned b = 0b0011'1100;       // 60
    std::cout << ( a | b ) << "\n"; // Bit-Oder: 252, in Bits 1111'1100
    std::cout << ( a & b ) << "\n"; // Bit-Und: 48, in Bits 0011'0000
    std::cout << ( a ^ b ) << "\n"; // Exklusiv-Oder: 204, in Bits 1100'1100
    unsigned int c = 170;           // in Bits 0..(24x0)..0'1010'1010
    std::cout << ( ~c ) << "\n";    // Inv.: 4294967125, Bits: 1..(24x1)..1'0101'0101
}

Okt 23, 2024

lst-0086-book.cpp

// https://godbolt.org/z/We3oWrcWW 
#include <iostream>
#include <cmath>     // sqrt
#include <concepts>  // floating_point
using std::min; using std::max; using std::floating_point;

template<floating_point T> T heron(T a, T b, T c) {
    auto s = (a+b+c) / 2;
    return sqrt(s*(s-a)*(s-b)*(s-c));
}

template<floating_point T> T kahan(T a, T b, T c) {
   auto x = max(a,max(b,c));
   auto y = max(min(a,b), min(max(a,b),c));
   auto z = min(a,min(b,c));
   return sqrt( (x+(y+z))*(z-(x-y))*(z+(x-y))*(x+(y-z)) )/4 ;
}

template<floating_point T> void dreieck(T a, T b, T c) {
   std::cout << "heron: " << heron(a,b,c) << '\n';
   std::cout << "kahan: " << kahan(a,b,c) << '\n';
}

int main() {
   dreieck(3.0f, 4.0f, 5.0f);
}

Okt 23, 2024

Okt 23, 2024

lst-0001-book.cpp

// https://godbolt.org/z/jrqEGvh1M 
#include <iostream>              // cout
#include <memory>                // make_shared
int main() {                     // ein Kommentar
  std::cout << "Blopp\n";        // hervorgehoben
  Typ feh-ler(args);             //             (ERR)  Zeile mit einem Fehler
  if consteval {                 // auf C++23-Features weise ich hin
      sin(55); }
  for(;;) break; // andere Markierung, zur Unterscheidung oder Hervorhebung
}

Okt 23, 2024

lst-0039-book.cpp

// https://godbolt.org/z/chTTqPjrM 
#include <string>
#include <iostream>
int main() {
    std::cout << "C-Zeichenkettenliteral\n";
    // using std::literals::string_literals::operator""s;
    // using namespace std::string_literals;
    // using namespace std::literals::string_literals;
    using namespace std::literals;
    std::cout << "Echter string\n"s;
}

Okt 23, 2024

lst-0006-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ee7eqq1MY 
Data* dataOwner = new Data(5);
Data* data = dataOwner;
Data* mehr = new Data(6);
data = mehr;
mehr->value = 7;
cout << data->value << '\n'; // jetzt auch 7
/* selbst wegräumen */
delete mehr;
delete dataOwner;

Okt 23, 2024

lst-0017-book.cpp

// https://godbolt.org/z/eWfGbv1dG 
#          include <iostream>        // # muss am Zeilenanfang stehen
int             main(
    ){
    std::cout
<<"Dies ist "
        "Text mit <Klammern>\n"   // String-Literal unterbrochen durch neue Zeile
        ;
    /*Typ:*/ int
    /*Variable:*/ ein_Wert
    /*Init:*/ = 100;               // innere Kommentare
std::cout<<ein_Wert<<"\n";}       // keine Leerzeichen

Okt 23, 2024

lst-0622-book.cpp

struct NachJahr { // implementiert less-than nach Zwerg::jahr_
    bool operator()(const Zwerg& a, const Zwerg& b) const {
        return a.jahr_ < b.jahr_;
    }
};

Okt 23, 2024

lst-0039-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/chTTqPjrM 
#include <string>
#include <iostream>
int main() {
    std::cout << "C-Zeichenkettenliteral\n";
    // using std::literals::string_literals::operator""s;
    // using namespace std::string_literals;
    // using namespace std::literals::string_literals;
    using namespace std::literals;
    std::cout << "Echter string\n"s;
}

Okt 23, 2024

lst-0002-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/aEvcPWzn5 
// modern101.cpp : Fibonacci-Konsole
#include <iostream>
int fib(int n) {
    return n<=1 ? n : fib(n-2) + fib(n-1);
}
int main() {
    std::cout << "Die wievielte Fibonacci-Zahl? ";
    int n = 0;
    std::cin >> n;
    std::cout << "fib(" << n << ")=" << fib(n) << "\n";
}

Okt 23, 2024

lst-0001-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jrqEGvh1M 
#include <iostream>              // cout
#include <memory>                // make_shared
int main() {                     // ein Kommentar
  std::cout << "Blopp\n";        // hervorgehoben
  Typ feh-ler(args);             //             (ERR)  Zeile mit einem Fehler
  if consteval {                 // auf C++23-Features weise ich hin
      sin(55); }
  for(;;) break; // andere Markierung, zur Unterscheidung oder Hervorhebung
}

Okt 23, 2024

lst-0002-book.cpp

// https://godbolt.org/z/aEvcPWzn5 
// modern101.cpp : Fibonacci-Konsole
#include <iostream>
int fib(int n) {
    return n<=1 ? n : fib(n-2) + fib(n-1);
}
int main() {
    std::cout << "Die wievielte Fibonacci-Zahl? ";
    int n = 0;
    std::cin >> n;
    std::cout << "fib(" << n << ")=" << fib(n) << "\n";
}

Okt 23, 2024

lst-0650-book.cpp

if constexpr std::integral<T> {
  // T ist ein integraler Typ
} else if constexpr std::floating_point<T> {
  // T ist ein Gleitkommatyp
} else {
  // T ist weder noch
}

Okt 23, 2024

lst-0967-book.cpp

error_condition make_error_condition(errc c) noexcept {
  return error_condition(
      static_cast<int>(e),
      generic_category());
}
error_condition make_error_condition(io_errc c) noexcept /*...*/
error_condition make_error_condition(future_errc c) noexcept /*...*/

Okt 23, 2024

Okt 23, 2024

lst-0021-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qWxq4KEKr 
void berechne(int n) {                           // eine eigene Funktion
    using namespace std;                         // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    for(int teiler=1; teiler <= n; ++teiler) {   // statt teiler=teiler+1
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}

Okt 23, 2024

lst-0053-book.cpp

// https://godbolt.org/z/cEGGfoeT7 
#include <iostream>
int main() {
    std::cout << "3+4*5+6=" << 3+4*5+6 << "\n";          // Punkt vor Strich; = 29
    std::cout << "(3+4)*(5+6)=" << (3+4)*(5+6) << "\n";  // Klammern; = 77
    std::cout << "22/7=" << 22/7 << " Rest " << 22%7 << "\n"; // 22/7 = 3 Rest 1
    for(int n=0; n < 10; ++n) {
        std::cout << -2*n*n + 13*n - 4 << " ";           // mit unärem Minus
    }
    std::cout << "\n";
    // Ausgabe: –4 7 14 17 16 11 2 –11 –28 –49
}

Okt 23, 2024

Okt 23, 2024

cpp23-listings-README.md

Listings of Gesamt.docx

This is linked summary of the listings. You can also view it on one page.

Okt 23, 2024

lst-0021-book.cpp

// https://godbolt.org/z/qWxq4KEKr 
void berechne(int n) {                           // eine eigene Funktion
    using namespace std;                         // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    for(int teiler=1; teiler <= n; ++teiler) {   // statt teiler=teiler+1
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}

Okt 23, 2024

lst-0035-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bh1MsPhje 
#include <iostream>
int main() {
    int a = 3;
    int b = 7 + (a = 12) + 6;   // enthält eine Zuweisung
    std::cout << a << std::endl;
}

Okt 23, 2024

lst-0005-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WM11Gs6sz 
auto data = make_shared<Data>(5);
auto mehr = make_shared<Data>(6);
data = mehr;
mehr->value = 7;
cout << data->value << '\n'; // jetzt auch 7

Okt 23, 2024

lst-0041-book.cpp

// https://godbolt.org/z/GbbcnYbqv 
std::vector vec { 1, 2, 3 };        // statt vector<int>
std::tuple tpl { 5, 'x' };          // statt tuple<int,char>
std::shared_ptr<int> ptr { new int(5) };
std::shared_ptr ptr2 { ptr };       // statt shared_ptr<int>

Okt 23, 2024

lst-0056-book.cpp

// https://godbolt.org/z/nMcsbxvvv 
#include <iostream>
void printBin(int x) {
    while(x>0) {         // fertig?
        int a = x/2;     // Division durch 2
        int b = x%2;     // Modulo, Rest der Division
        std::cout << x <<" / 2 = " << a << ", Rest " << b<<'\n'; // Ausgabe
        x = a;
    }
}
int main() {
    printBin(412);
}

Okt 23, 2024

lst-0024-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r5hjrqqK9 
#include <iostream>
int main() {
    int var = 10;
    var += 2;
    var *= 3;
    var /= 4;
    var -= 5;
    std::cout << var << "\n"; // ergibt 4
}

Okt 23, 2024

lst-0005-book.cpp

// https://godbolt.org/z/WM11Gs6sz 
auto data = make_shared<Data>(5);
auto mehr = make_shared<Data>(6);
data = mehr;
mehr->value = 7;
cout << data->value << '\n'; // jetzt auch 7

Okt 23, 2024

lst-0867-book.cpp

#include <iostream>
using std::cout; using std::endl;
int main() {
    auto ddash = [](auto &os) -> std::ostream& { return os << "-"; };
    cout << "Text1" << ddash << "Text2" << endl; // Ausgabe: Text1-Text2
}

Okt 23, 2024

lst-0037-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zK9Ke9n48 
#include <iostream>                     // cout
int main(int argc, const char* argv[]) {
    bool mitParametern = argc > 1;      // Vergleichsergebnis zwischengespeichert
    if(mitParametern) {                 //  und verwendet
        std::cout << "Sie haben das Programm mit Parametern aufgerufen.\n";
    }
    return 0;
}

Okt 23, 2024

lst-0024-book.cpp

// https://godbolt.org/z/r5hjrqqK9 
#include <iostream>
int main() {
    int var = 10;
    var += 2;
    var *= 3;
    var /= 4;
    var -= 5;
    std::cout << var << "\n"; // ergibt 4
}

Okt 23, 2024

lst-0041-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GbbcnYbqv 
std::vector vec { 1, 2, 3 };        // statt vector<int>
std::tuple tpl { 5, 'x' };          // statt tuple<int,char>
std::shared_ptr<int> ptr { new int(5) };
std::shared_ptr ptr2 { ptr };       // statt shared_ptr<int>

Okt 23, 2024

lst-0006-book.cpp

// https://godbolt.org/z/Ee7eqq1MY 
Data* dataOwner = new Data(5);
Data* data = dataOwner;
Data* mehr = new Data(6);
data = mehr;
mehr->value = 7;
cout << data->value << '\n'; // jetzt auch 7
/* selbst wegräumen */
delete mehr;
delete dataOwner;

Okt 23, 2024

lst-0964-book.cpp

bool operator==
   (const error_code&    lhs, const error_code&      rhs) noexcept;
(const error_code&      lhs, const error_condition& rhs) noexcept;
(const error_condition& lhs, const error_code&      rhs) noexcept;
(const error_condition& lhs, const error_condition& rhs) noexcept;

Okt 23, 2024

lst-0007-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Moe5M7sK8 
Data const * data = new Data(5);
data->value = 7;         // dieses const schützt Data
data = new Data(6);      // Zeiger neu zuweisen ist okay
Data * const mehr = new Data(8);
mehr->value = 9;         // jetzt okay
mehr = new Data(10);     // Referenz ist geschützt

Okt 23, 2024

lst-0053-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cEGGfoeT7 
#include <iostream>
int main() {
    std::cout << "3+4*5+6=" << 3+4*5+6 << "\n";          // Punkt vor Strich; = 29
    std::cout << "(3+4)*(5+6)=" << (3+4)*(5+6) << "\n";  // Klammern; = 77
    std::cout << "22/7=" << 22/7 << " Rest " << 22%7 << "\n"; // 22/7 = 3 Rest 1
    for(int n=0; n < 10; ++n) {
        std::cout << -2*n*n + 13*n - 4 << " ";           // mit unärem Minus
    }
    std::cout << "\n";
    // Ausgabe: 4 7 14 17 16 11 2 11 28 49
}

Okt 23, 2024

Okt 23, 2024

lst-0056-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nMcsbxvvv 
#include <iostream>
void printBin(int x) {
    while(x>0) {         // fertig?
        int a = x/2;     // Division durch 2
        int b = x%2;     // Modulo, Rest der Division
        std::cout << x <<" / 2 = " << a << ", Rest " << b<<'\n'; // Ausgabe
        x = a;
    }
}
int main() {
    printBin(412);
}

Okt 23, 2024

lst-0022-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4Mr6fnaEr 
#include <iostream> // cout
int main() {
    int basis = 2;
    int index = 10;
    int zahl = 3 * (basis + ++index) - 1;  // zuerst wird index erhöht
    std::cout << zahl << '\n';             // Ausgabe: 38
}

Okt 23, 2024

lst-0016-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/d7Yjr9jdb 
#include <iostream>    // für std::cin, std::cout, std::endl
#include <string>      // std::stoi

void berechne(int n) {                             // eine eigene Funktion
    using namespace std;                           // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    if(n == 0) { cout << "0\n"; return; }          // 0 ist Teiler von 0
    for(int teiler=1; teiler <= n; ++teiler) {     // statt teiler=teiler+1
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}
int main(int argc, const char* argv[]) {           // Argumente für main
    /* Zahl ermitteln */
    int wert = 0;
    if(argc<=1) {
        std::cout << "Geben Sie eine Zahl ein: ";
        std::cin >> wert;                          // in Variable wert lesen
        if(!std::cin) {                            // prüfen, ob lesen klappte
            return 1;                              // Fehler bei Benutzereingabe
        }
    } else {
        wert = std::stoi(argv[1]);
    }
    berechne(wert);                                // Funktionsaufruf
    return 0;
}

Okt 23, 2024

lst-0016-book.cpp

// https://godbolt.org/z/d7Yjr9jdb 
#include <iostream>    // für std::cin, std::cout, std::endl
#include <string>      // std::stoi

void berechne(int n) {                             // eine eigene Funktion
    using namespace std;                           // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    if(n == 0) { cout << "0\n"; return; }          // 0 ist Teiler von 0
    for(int teiler=1; teiler <= n; ++teiler) {     // statt teiler=teiler+1
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}
int main(int argc, const char* argv[]) {           // Argumente für main
    /* Zahl ermitteln */
    int wert = 0;
    if(argc<=1) {
        std::cout << "Geben Sie eine Zahl ein: ";
        std::cin >> wert;                          // in Variable wert lesen
        if(!std::cin) {                            // prüfen, ob lesen klappte
            return 1;                              // Fehler bei Benutzereingabe
        }
    } else {
        wert = std::stoi(argv[1]);
    }
    berechne(wert);                                // Funktionsaufruf
    return 0;
}

Okt 23, 2024

cpp23-listings-README-onepage.md

Listings of Gesamt.docx

This is the list of listings on one page. You can also view a linked summary.

Listing 1.1: Ein kleines Formatbeispiel

Book listing lst-0001-book.cpp:

// https://godbolt.org/z/jrqEGvh1M 
#include <iostream>              // cout
#include <memory>                // make_shared
int main() {                     // ein Kommentar
  std::cout << "Blopp\n";        // hervorgehoben
  Typ feh-ler(args);             //             (ERR)  Zeile mit einem Fehler
  if consteval {                 // auf C++23-Features weise ich hin
      sin(55); }
  for(;;) break; // andere Markierung, zur Unterscheidung oder Hervorhebung
}

Godbolt Listing lst-0001-godb.cpp, https://godbolt.org/z/jrqEGvh1M:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jrqEGvh1M 
#include <iostream>              // cout
#include <memory>                // make_shared
int main() {                     // ein Kommentar
  std::cout << "Blopp\n";        // hervorgehoben
  Typ feh-ler(args);             //             (ERR)  Zeile mit einem Fehler
  if consteval {                 // auf C++23-Features weise ich hin
      sin(55); }
  for(;;) break; // andere Markierung, zur Unterscheidung oder Hervorhebung
}

Listing 2.1: Jede Fibonacci-Zahl ist die Summe der beiden Zahlen davor.

Book listing lst-0002-book.cpp:

// https://godbolt.org/z/aEvcPWzn5 
// modern101.cpp : Fibonacci-Konsole
#include <iostream>
int fib(int n) {
    return n<=1 ? n : fib(n-2) + fib(n-1);
}
int main() {
    std::cout << "Die wievielte Fibonacci-Zahl? ";
    int n = 0;
    std::cin >> n;
    std::cout << "fib(" << n << ")=" << fib(n) << "\n";
}

Godbolt Listing lst-0002-godb.cpp, https://godbolt.org/z/aEvcPWzn5:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/aEvcPWzn5 
// modern101.cpp : Fibonacci-Konsole
#include <iostream>
int fib(int n) {
    return n<=1 ? n : fib(n-2) + fib(n-1);
}
int main() {
    std::cout << "Die wievielte Fibonacci-Zahl? ";
    int n = 0;
    std::cin >> n;
    std::cout << "fib(" << n << ")=" << fib(n) << "\n";
}

Listing 2.2: Eine zügig erstellte Tabelle von Fibonacci-Zahlen

Book listing lst-0003-book.cpp:

// https://godbolt.org/z/Tbx6qdrfx 
// modern102.cpp : Fibonacci-Konsole
#include <iostream>
#include <map>
int fib(int n) {
    static std::map<int, int> table{};
    table[n] = n<=1 ? n : table[n-2] + table[n-1];
    return table[n];
}
int main() {
    std::cout << "Wie viele Fibonacci-Zahlen? ";
    int n = 0;
    std::cin >> n;
    for (int i = 1; i <= n; ++i)
        std::cout << "fib(" << i << ")=" << fib(i) << "\n";
}

Godbolt Listing lst-0003-godb.cpp, https://godbolt.org/z/Tbx6qdrfx:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Tbx6qdrfx 
// modern102.cpp : Fibonacci-Konsole
#include <iostream>
#include <map>
int fib(int n) {
    static std::map<int, int> table{};
    table[n] = n<=1 ? n : table[n-2] + table[n-1];
    return table[n];
}
int main() {
    std::cout << "Wie viele Fibonacci-Zahlen? ";
    int n = 0;
    std::cin >> n;
    for (int i = 1; i <= n; ++i)
        std::cout << "fib(" << i << ")=" << fib(i) << "\n";
}

Listing 3.2: (C++) In C++ hat man statt Referenzen erst einmal Werte.

Book listing lst-0004-book.cpp:

Data data{5};
Data mehr{6};
data = mehr;
mehr.value = 7;
cout << data.value << '\n'; // immer noch 6

Listing 3.3: (C++) Modernes C++ mit Heapspeicher nutzt Hilfsklassen wie shared_ptr.

Book listing lst-0005-book.cpp:

// https://godbolt.org/z/WM11Gs6sz 
auto data = make_shared<Data>(5);
auto mehr = make_shared<Data>(6);
data = mehr;
mehr->value = 7;
cout << data->value << '\n'; // jetzt auch 7

Godbolt Listing lst-0005-godb.cpp, https://godbolt.org/z/WM11Gs6sz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WM11Gs6sz 
auto data = make_shared<Data>(5);
auto mehr = make_shared<Data>(6);
data = mehr;
mehr->value = 7;
cout << data->value << '\n'; // jetzt auch 7

Listing 3.4: (C++) Ohne moderne C++-Mittel muss man besonders auf den Zeigerbesitz achten.

Book listing lst-0006-book.cpp:

// https://godbolt.org/z/Ee7eqq1MY 
Data* dataOwner = new Data(5);
Data* data = dataOwner;
Data* mehr = new Data(6);
data = mehr;
mehr->value = 7;
cout << data->value << '\n'; // jetzt auch 7
/* selbst wegräumen */
delete mehr;
delete dataOwner;

Godbolt Listing lst-0006-godb.cpp, https://godbolt.org/z/Ee7eqq1MY:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ee7eqq1MY 
Data* dataOwner = new Data(5);
Data* data = dataOwner;
Data* mehr = new Data(6);
data = mehr;
mehr->value = 7;
cout << data->value << '\n'; // jetzt auch 7
/* selbst wegräumen */
delete mehr;
delete dataOwner;

Listing 3.6: (C++) const kann den Wert oder die Referenz schützen.

Book listing lst-0007-book.cpp:

// https://godbolt.org/z/Moe5M7sK8 
Data const * data = new Data(5);
data->value = 7;         // dieses const schützt Data
data = new Data(6);      // Zeiger neu zuweisen ist okay
Data * const mehr = new Data(8);
mehr->value = 9;         // jetzt okay
mehr = new Data(10);     // Referenz ist geschützt

Godbolt Listing lst-0007-godb.cpp, https://godbolt.org/z/Moe5M7sK8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Moe5M7sK8 
Data const * data = new Data(5);
data->value = 7;         // dieses const schützt Data
data = new Data(6);      // Zeiger neu zuweisen ist okay
Data * const mehr = new Data(8);
mehr->value = 9;         // jetzt okay
mehr = new Data(10);     // Referenz ist geschützt

Listing 4.7: Ein sehr einfaches C++-Programm

Book listing lst-0008-book.cpp:

// https://godbolt.org/z/Mdj7bGvar 
#include <iostream>                         // Module/Bibliotheken einbinden
int main()                                  // main() ist der Beginn des Programms
{
    int wert = 100;                         // Variable mit Anfangswert
    std::cout << "Teiler von " << wert << " sind:\n";    // Ausgabe von Text
    for(int teiler=1; teiler <= wert; teiler = teiler+1) // Schleife von 1 bis 100
    {                                       // hier beginnt der Wiederholungsteil
        if(wert % teiler == 0)              // Test für eine bedingte Ausführung
            std::cout << teiler << ", ";    // nur bei positivem Test
    }                                       // Ende der Schleife
    std::cout << "\n";                      // einmalige Ausgabe
    return 0;                               // bedeutet in main() Programmende
}                                           // Ende von main()

Godbolt Listing lst-0008-godb.cpp, https://godbolt.org/z/Mdj7bGvar:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mdj7bGvar 
#include <iostream>                         // Module/Bibliotheken einbinden
int main()                                  // main() ist der Beginn des Programms
{
    int wert = 100;                         // Variable mit Anfangswert
    std::cout << "Teiler von " << wert << " sind:\n";    // Ausgabe von Text
    for(int teiler=1; teiler <= wert; teiler = teiler+1) // Schleife von 1 bis 100
    {                                       // hier beginnt der Wiederholungsteil
        if(wert % teiler == 0)              // Test für eine bedingte Ausführung
            std::cout << teiler << ", ";    // nur bei positivem Test
    }                                       // Ende der Schleife
    std::cout << "\n";                      // einmalige Ausgabe
    return 0;                               // bedeutet in main() Programmende
}                                           // Ende von main()

Listing 4.8: Dieses Programm fragt seine Benutzer nach einer Zahl.

Book listing lst-0016-book.cpp:

// https://godbolt.org/z/d7Yjr9jdb 
#include <iostream>    // für std::cin, std::cout, std::endl
#include <string>      // std::stoi

void berechne(int n) {                             // eine eigene Funktion
    using namespace std;                           // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    if(n == 0) { cout << "0\n"; return; }          // 0 ist Teiler von 0
    for(int teiler=1; teiler <= n; ++teiler) {     // statt teiler=teiler+1
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}
int main(int argc, const char* argv[]) {           // Argumente für main
    /* Zahl ermitteln */
    int wert = 0;
    if(argc<=1) {
        std::cout << "Geben Sie eine Zahl ein: ";
        std::cin >> wert;                          // in Variable wert lesen
        if(!std::cin) {                            // prüfen, ob lesen klappte
            return 1;                              // Fehler bei Benutzereingabe
        }
    } else {
        wert = std::stoi(argv[1]);
    }
    berechne(wert);                                // Funktionsaufruf
    return 0;
}

Godbolt Listing lst-0016-godb.cpp, https://godbolt.org/z/d7Yjr9jdb:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/d7Yjr9jdb 
#include <iostream>    // für std::cin, std::cout, std::endl
#include <string>      // std::stoi

void berechne(int n) {                             // eine eigene Funktion
    using namespace std;                           // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    if(n == 0) { cout << "0\n"; return; }          // 0 ist Teiler von 0
    for(int teiler=1; teiler <= n; ++teiler) {     // statt teiler=teiler+1
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}
int main(int argc, const char* argv[]) {           // Argumente für main
    /* Zahl ermitteln */
    int wert = 0;
    if(argc<=1) {
        std::cout << "Geben Sie eine Zahl ein: ";
        std::cin >> wert;                          // in Variable wert lesen
        if(!std::cin) {                            // prüfen, ob lesen klappte
            return 1;                              // Fehler bei Benutzereingabe
        }
    } else {
        wert = std::stoi(argv[1]);
    }
    berechne(wert);                                // Funktionsaufruf
    return 0;
}

Listing 4.9: Ein sehr außergewöhnlich formatiertes Stück Quellcode

Book listing lst-0017-book.cpp:

// https://godbolt.org/z/eWfGbv1dG 
#          include <iostream>        // # muss am Zeilenanfang stehen
int             main(
    ){
    std::cout
<<"Dies ist "
        "Text mit <Klammern>\n"   // String-Literal unterbrochen durch neue Zeile
        ;
    /*Typ:*/ int
    /*Variable:*/ ein_Wert
    /*Init:*/ = 100;               // innere Kommentare
std::cout<<ein_Wert<<"\n";}       // keine Leerzeichen

Godbolt Listing lst-0017-godb.cpp, https://godbolt.org/z/eWfGbv1dG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eWfGbv1dG 
#          include <iostream>        // # muss am Zeilenanfang stehen
int             main(
    ){
    std::cout
<<"Dies ist "
        "Text mit <Klammern>\n"   // String-Literal unterbrochen durch neue Zeile
        ;
    /*Typ:*/ int
    /*Variable:*/ ein_Wert
    /*Init:*/ = 100;               // innere Kommentare
std::cout<<ein_Wert<<"\n";}       // keine Leerzeichen

Listing 4.10: Kommentare mit / und / können über mehrere Zeilen gehen oder eine Programmzeile auch unterbrechen.

Book listing lst-0018-book.cpp:

int main() {
    /* Mein erstes Programm. Es wurde
        geschrieben von Max Muster.*/
    return /* Die Null des Erfolgs */ 0;
}

Listing 4.11: Eine eigene C++-Funktion

Book listing lst-0021-book.cpp:

// https://godbolt.org/z/qWxq4KEKr 
void berechne(int n) {                           // eine eigene Funktion
    using namespace std;                         // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    for(int teiler=1; teiler <= n; ++teiler) {   // statt teiler=teiler+1
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}

Godbolt Listing lst-0021-godb.cpp, https://godbolt.org/z/qWxq4KEKr:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qWxq4KEKr 
void berechne(int n) {                           // eine eigene Funktion
    using namespace std;                         // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    for(int teiler=1; teiler <= n; ++teiler) {   // statt teiler=teiler+1
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}

Listing 4.12: Präfixoperatoren werden vor der Berechnung ausgeführt.

Book listing lst-0022-book.cpp:

// https://godbolt.org/z/4Mr6fnaEr 
#include <iostream> // cout
int main() {
    int basis = 2;
    int index = 10;
    int zahl = 3 * (basis + ++index) - 1;  // zuerst wird index erhöht
    std::cout << zahl << '\n';             // Ausgabe: 38
}

Godbolt Listing lst-0022-godb.cpp, https://godbolt.org/z/4Mr6fnaEr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4Mr6fnaEr 
#include <iostream> // cout
int main() {
    int basis = 2;
    int index = 10;
    int zahl = 3 * (basis + ++index) - 1;  // zuerst wird index erhöht
    std::cout << zahl << '\n';             // Ausgabe: 38
}

GodboltId:r5hjrqqK9

Book listing lst-0024-book.cpp:

// https://godbolt.org/z/r5hjrqqK9 
#include <iostream>
int main() {
    int var = 10;
    var += 2;
    var *= 3;
    var /= 4;
    var -= 5;
    std::cout << var << "\n"; // ergibt 4
}

Godbolt Listing lst-0024-godb.cpp, https://godbolt.org/z/r5hjrqqK9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r5hjrqqK9 
#include <iostream>
int main() {
    int var = 10;
    var += 2;
    var *= 3;
    var /= 4;
    var -= 5;
    std::cout << var << "\n"; // ergibt 4
}

Listing 4.13: Ein Programm, das nur aus main und return besteht

Book listing lst-0025-book.cpp:

int main() {
    if(2 < 1) return 1;    // ein return
    return 0;              // anderes return
}                          // Ende von main

Listing 4.14: Hier setzen Sie nur die äußeren geschweiftenKlammern.

Book listing lst-0026-book.cpp:

for(int teiler=1; teiler <= n; ++teiler)  // for-Schleife
{                                         // Beginn des Schleifenblocks
    if(n % teiler == 0)
        std::cout << teiler << ", ";
}                                         // Ende des Schleifenblocks

Listing 4.15: So sieht es aus, wenn Sie alle geschweiften Klammern setzen.

Book listing lst-0027-book.cpp:

if(argc<=1) {                             // Beginn der if-Anweisung
    std::cout << "Geben Sie eine Zahl ein: ";
    std::cin >> zahl;
    if(!std::cin) {
        return 1;
    }
} else {
    wert = std::stoi(argv[1]);
}                                         // Ende der if-Anweisung

Listing 4.16: Das »if« ist eine Anweisung und benötigt eigentlich keine geschweiften Klammern.

Book listing lst-0028-book.cpp:

for(int teiler=1; teiler <= wert; ++teiler)
    if(wert % teiler == 0)
        std::cout << teiler << ", ";

Listing 4.17: Setzen Sie besser auch einzelne Anweisungen in geschweifte Klammern.

Book listing lst-0030-book.cpp:

for(int teiler=1; teiler <= wert; ++teiler) {
    if(wert % teiler == 0) {
        std::cout << teiler << ", ";
    }
}

Listing 4.18: Zuweisung des Ergebnisses eines Funktionsaufrufs

Book listing lst-0033-book.cpp:

wert = std::stoi(argv[1]);

Listing 4.19: Zuweisung des Ergebnisses einer Berechnung

Book listing lst-0034-book.cpp:

teiler = teiler + 1

Listing 4.20: Eine Zuweisung ist ein Ausdruck mit dem Typ der zugewiesenen Variablen.

Book listing lst-0035-book.cpp:

// https://godbolt.org/z/bh1MsPhje 
#include <iostream>
int main() {
    int a = 3;
    int b = 7 + (a = 12) + 6;   // enthält eine Zuweisung
    std::cout << a << std::endl;
}

Godbolt Listing lst-0035-godb.cpp, https://godbolt.org/z/bh1MsPhje:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bh1MsPhje 
#include <iostream>
int main() {
    int a = 3;
    int b = 7 + (a = 12) + 6;   // enthält eine Zuweisung
    std::cout << a << std::endl;
}

Listing 4.21: Der Compiler hilft, korrekte Programme zu schreiben, indem er die Typen überprüft.

Book listing lst-0036-book.cpp:

// https://godbolt.org/z/9943MfExc 
#include <vector>
class Image {
    std::vector<char> data_;
public:
    void load(const char* filename); // lädt Bilddaten
};
class Screen {
public:
    void show(Image& image);         //                 (ERR)  image sollte const sein
};
void paint(Screen &screen, const Image& image) {
     screen.show(image);
}
int main() {
    Image image {};
    image.load("peter.png");
    Screen screen {};
    paint(screen, image);
}

Godbolt Listing lst-0036-godb.cpp, https://godbolt.org/z/9943MfExc:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9943MfExc 
#include <vector>
class Image {
    std::vector<char> data_;
public:
    void load(const char* filename); // lädt Bilddaten
};
class Screen {
public:
    void show(Image& image);         //                 (ERR)  image sollte const sein
};
void paint(Screen &screen, const Image& image) {
     screen.show(image);
}
int main() {
    Image image {};
    image.load("peter.png");
    Screen screen {};
    paint(screen, image);
}

Listing 4.22: Variablen vom Typ bool können das Ergebnis eines Vergleichs zwischenspeichern.

Book listing lst-0037-book.cpp:

// https://godbolt.org/z/zK9Ke9n48 
#include <iostream>                     // cout
int main(int argc, const char* argv[]) {
    bool mitParametern = argc > 1;      // Vergleichsergebnis zwischengespeichert
    if(mitParametern) {                 // … und verwendet
        std::cout << "Sie haben das Programm mit Parametern aufgerufen.\n";
    }
    return 0;
}

Godbolt Listing lst-0037-godb.cpp, https://godbolt.org/z/zK9Ke9n48:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zK9Ke9n48 
#include <iostream>                     // cout
int main(int argc, const char* argv[]) {
    bool mitParametern = argc > 1;      // Vergleichsergebnis zwischengespeichert
    if(mitParametern) {                 // … und verwendet
        std::cout << "Sie haben das Programm mit Parametern aufgerufen.\n";
    }
    return 0;
}

Listing 4.23: So können Sie einen C++-string als Literal in den Quellcode schreiben.

Book listing lst-0039-book.cpp:

// https://godbolt.org/z/chTTqPjrM 
#include <string>
#include <iostream>
int main() {
    std::cout << "C-Zeichenkettenliteral\n";
    // using std::literals::string_literals::operator""s;
    // using namespace std::string_literals;
    // using namespace std::literals::string_literals;
    using namespace std::literals;
    std::cout << "Echter string\n"s;
}

Godbolt Listing lst-0039-godb.cpp, https://godbolt.org/z/chTTqPjrM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/chTTqPjrM 
#include <string>
#include <iostream>
int main() {
    std::cout << "C-Zeichenkettenliteral\n";
    // using std::literals::string_literals::operator""s;
    // using namespace std::string_literals;
    // using namespace std::literals::string_literals;
    using namespace std::literals;
    std::cout << "Echter string\n"s;
}

Listing 4.24: Seit C++17 bestimmt der Compiler die Typparameter von Klassentemplates anhand der Konstruktorargumente.

Book listing lst-0041-book.cpp:

// https://godbolt.org/z/GbbcnYbqv 
std::vector vec { 1, 2, 3 };        // statt vector<int>
std::tuple tpl { 5, 'x' };          // statt tuple<int,char>
std::shared_ptr<int> ptr { new int(5) };
std::shared_ptr ptr2 { ptr };       // statt shared_ptr<int>

Godbolt Listing lst-0041-godb.cpp, https://godbolt.org/z/GbbcnYbqv:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GbbcnYbqv 
std::vector vec { 1, 2, 3 };        // statt vector<int>
std::tuple tpl { 5, 'x' };          // statt tuple<int,char>
std::shared_ptr<int> ptr { new int(5) };
std::shared_ptr ptr2 { ptr };       // statt shared_ptr<int>

Listing 4.25: Manchen Variablen können Sie nichts zuweisen, Sie können sie nur initialisieren.

Book listing lst-0042-book.cpp:

int main() {
     const int fest = 33; // Initialisierung als Konstante
     fest = 80;           //                 (ERR)  eine Zuweisung ist unmöglich
 }

Listing 4.26: Statt des = können Sie {…} zur Initialisierung verwenden.

Book listing lst-0043-book.cpp:

int index = 1;        // alter Stil, sieht wie eine Zuweisung aus
int zaehler { 1 };    // C++11-Stil, eindeutig eine Initialisierung
int counter = { 1 };  // beim C++11-Stil ist das »=« optional und wird ignoriert

Listing 4.27: Sie können einen Namensraum einbinden, um Programmtext kürzer zu machen.

Book listing lst-0050-book.cpp:

#include <iostream>                            // für std::cin, std::cout, std::endl
#include <string>                              // für std::stoi
void berechne(int n) {
    using namespace std;                       // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";  // cout statt std::cout
    for(int teiler=1; teiler <= n; ++teiler) {
        if(n % teiler == 0)
            cout << teiler << ", ";            // cout statt std::cout
    }
    cout << endl;
}

Listing 4.28: »using namespace« können Sie auch global verwenden, sollten es aber selten tun.

Book listing lst-0051-book.cpp:

#include <iostream>
#include <string>
using namespace std; //                 (ERR)  wirkt sich global aus; klappt, ist aber kritisch
void berechne(int n) {
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    // …
}
// … auch in weiteren Funktionen …

Listing 4.29: Holen Sie sich mit »using« einzelne Bezeichner.

Book listing lst-0052-book.cpp:

#include <iostream>                               // cin, cout, endl
using std::endl;                                  // gilt global in dieser Datei
void berechne(int n) {
    using std::cout;                              // gilt lokal in dieser Funktion
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    for(int teiler=1; teiler <= n; ++teiler) {
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}

Listing 4.30: Arithmetische Operatoren in der Anwendung

Book listing lst-0053-book.cpp:

// https://godbolt.org/z/cEGGfoeT7 
#include <iostream>
int main() {
    std::cout << "3+4*5+6=" << 3+4*5+6 << "\n";          // Punkt vor Strich; = 29
    std::cout << "(3+4)*(5+6)=" << (3+4)*(5+6) << "\n";  // Klammern; = 77
    std::cout << "22/7=" << 22/7 << " Rest " << 22%7 << "\n"; // 22/7 = 3 Rest 1
    for(int n=0; n < 10; ++n) {
        std::cout << -2*n*n + 13*n - 4 << " ";           // mit unärem Minus
    }
    std::cout << "\n";
    // Ausgabe: –4 7 14 17 16 11 2 –11 –28 –49
}

Godbolt Listing lst-0053-godb.cpp, https://godbolt.org/z/cEGGfoeT7:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cEGGfoeT7 
#include <iostream>
int main() {
    std::cout << "3+4*5+6=" << 3+4*5+6 << "\n";          // Punkt vor Strich; = 29
    std::cout << "(3+4)*(5+6)=" << (3+4)*(5+6) << "\n";  // Klammern; = 77
    std::cout << "22/7=" << 22/7 << " Rest " << 22%7 << "\n"; // 22/7 = 3 Rest 1
    for(int n=0; n < 10; ++n) {
        std::cout << -2*n*n + 13*n - 4 << " ";           // mit unärem Minus
    }
    std::cout << "\n";
    // Ausgabe: –4 7 14 17 16 11 2 –11 –28 –49
}

Listing 4.31: Programmierbeispiel für die Umwandlung einer Ganzzahl in eine Bitfolge

Book listing lst-0056-book.cpp:

// https://godbolt.org/z/nMcsbxvvv 
#include <iostream>
void printBin(int x) {
    while(x>0) {         // fertig?
        int a = x/2;     // Division durch 2
        int b = x%2;     // Modulo, Rest der Division
        std::cout << x <<" / 2 = " << a << ", Rest " << b<<'\n'; // Ausgabe
        x = a;
    }
}
int main() {
    printBin(412);
}

Godbolt Listing lst-0056-godb.cpp, https://godbolt.org/z/nMcsbxvvv:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nMcsbxvvv 
#include <iostream>
void printBin(int x) {
    while(x>0) {         // fertig?
        int a = x/2;     // Division durch 2
        int b = x%2;     // Modulo, Rest der Division
        std::cout << x <<" / 2 = " << a << ", Rest " << b<<'\n'; // Ausgabe
        x = a;
    }
}
int main() {
    printBin(412);
}

GodboltId:TTjxzrYf3

Book listing lst-0057-book.cpp:

// https://godbolt.org/z/TTjxzrYf3 
#include <iostream>
#include <bitset>
constexpr unsigned n_bits = sizeof(unsigned short)*8; // 8 Bit pro char
auto bits_umdrehen(unsigned val) -> unsigned short {
  unsigned short ret = 0;
  for (unsigned i = 0; i < n_bits; ++i ) {
    ret = (ret << 1) | (val & 1);   // eins zur Seite, unterstes evtl. setzen
    val >>= 1;                      // eins in die andere Richtung
  }
  return ret;
}
void zeig(unsigned short val) {
    std::bitset<n_bits> bits{val};
    std::cout << val << "=" << bits << " -> ";
    auto lav = bits_umdrehen(val);
    std::bitset<n_bits> stib{lav};
    std::cout << lav << "=" << stib << "\n";
}
int main() {
    zeig(36u);  // Ausgabe: 36=0000000000100100 -> 9216=0010010000000000
    zeig(199u); // Ausgabe: 199=0000000011000111 -> 58112=1110001100000000
    zeig(255u); // Ausgabe: 255=0000000011111111 -> 65280=1111111100000000
    zeig(256u); // Ausgabe: 256=0000000100000000 -> 128=0000000010000000
}

Godbolt Listing lst-0057-godb.cpp, https://godbolt.org/z/TTjxzrYf3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TTjxzrYf3 
#include <iostream>
#include <bitset>
constexpr unsigned n_bits = sizeof(unsigned short)*8; // 8 Bit pro char
auto bits_umdrehen(unsigned val) -> unsigned short {
  unsigned short ret = 0;
  for (unsigned i = 0; i < n_bits; ++i ) {
    ret = (ret << 1) | (val & 1);   // eins zur Seite, unterstes evtl. setzen
    val >>= 1;                      // eins in die andere Richtung
  }
  return ret;
}
void zeig(unsigned short val) {
    std::bitset<n_bits> bits{val};
    std::cout << val << "=" << bits << " -> ";
    auto lav = bits_umdrehen(val);
    std::bitset<n_bits> stib{lav};
    std::cout << lav << "=" << stib << "\n";
}
int main() {
    zeig(36u);  // Ausgabe: 36=0000000000100100 -> 9216=0010010000000000
    zeig(199u); // Ausgabe: 199=0000000011000111 -> 58112=1110001100000000
    zeig(255u); // Ausgabe: 255=0000000011111111 -> 65280=1111111100000000
    zeig(256u); // Ausgabe: 256=0000000100000000 -> 128=0000000010000000
}

GodboltId:5hqanTeYh

Book listing lst-0059-book.cpp:

// https://godbolt.org/z/5hqanTeYh 
#include <iostream>
#include <bitset>  // hilft bei der Ausgabe von Zahlen als Bitfolge
int main() {
    int a = 0;
    for(int idx=0; idx<8; idx++) {
        a <<= 2;                       // um zwei Bit nach links schieben: "…100"
        a |= 1;                        // unterstes Bit setzen: "…1"
    }
    std::cout << std::bitset<16>(a) << "\n"; // 0101010101010101
    std::cout << a << "\n";            // 21845
}

Godbolt Listing lst-0059-godb.cpp, https://godbolt.org/z/5hqanTeYh:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5hqanTeYh 
#include <iostream>
#include <bitset>  // hilft bei der Ausgabe von Zahlen als Bitfolge
int main() {
    int a = 0;
    for(int idx=0; idx<8; idx++) {
        a <<= 2;                       // um zwei Bit nach links schieben: "…100"
        a |= 1;                        // unterstes Bit setzen: "…1"
    }
    std::cout << std::bitset<16>(a) << "\n"; // 0101010101010101
    std::cout << a << "\n";            // 21845
}

GodboltId:xrMYz93WP

Book listing lst-0068-book.cpp:

// https://godbolt.org/z/xrMYz93WP 
int main() {
    for(int w1 = 1; w1 <= 6; ++w1) { // 1..6
        for(int w2 = 0; w2 < 10; ++w2) { // 0..9
            int max = w1 > w2 ? w1 : w2;  // ternärer Operator
        }
    }
}

Godbolt Listing lst-0068-godb.cpp, https://godbolt.org/z/xrMYz93WP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xrMYz93WP 
int main() {
    for(int w1 = 1; w1 <= 6; ++w1) { // 1..6
        for(int w2 = 0; w2 < 10; ++w2) { // 0..9
            int max = w1 > w2 ? w1 : w2;  // ternärer Operator
        }
    }
}

Listing 4.32: Mit Kommas in Klammern können Sie mehrere Ausdrücke verketten.

Book listing lst-0069-book.cpp:

// https://godbolt.org/z/rq66cWr3d 
int main() {
    int a = 0;
    int b = 0;
    for(int w1 = 1; w1 <= 6; ++w1) { // 1..6
        for(int w2 = 0; w2 < 10; ++w2) { // 0..9
            int max = w1 > w2 ? (a+=b , w1) :( b+=1 , w2); // Sequenzoperator
        }
    }
}

Godbolt Listing lst-0069-godb.cpp, https://godbolt.org/z/rq66cWr3d:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rq66cWr3d 
int main() {
    int a = 0;
    int b = 0;
    for(int w1 = 1; w1 <= 6; ++w1) { // 1..6
        for(int w2 = 0; w2 < 10; ++w2) { // 0..9
            int max = w1 > w2 ? (a+=b , w1) :( b+=1 , w2); // Sequenzoperator
        }
    }
}

Listing 4.33: In for-Schleifen kann das Sequenzkomma nützlich sein.

Book listing lst-0070-book.cpp:

// https://godbolt.org/z/vd85f7rMj 
#include <iostream>
int main() {
    int arr[] = { 8,3,7,3,11,999,5,6,7 };
    int len = 9;
    for(int i=0, *p=arr; i<len && *p!=999; ++i, ++p) { // erst ++i, dann ++p
        std::cout << i << ":" << *p << " ";
    }
    std::cout << "\n";
    // Ausgabe: 0:8 1:3 2:7 3:3 4:11
}

Godbolt Listing lst-0070-godb.cpp, https://godbolt.org/z/vd85f7rMj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vd85f7rMj 
#include <iostream>
int main() {
    int arr[] = { 8,3,7,3,11,999,5,6,7 };
    int len = 9;
    for(int i=0, *p=arr; i<len && *p!=999; ++i, ++p) { // erst ++i, dann ++p
        std::cout << i << ":" << *p << " ";
    }
    std::cout << "\n";
    // Ausgabe: 0:8 1:3 2:7 3:3 4:11
}

Listing 4.34: Hier werden einige neue Datentypen verwendet.

Book listing lst-0074-book.cpp:

// https://godbolt.org/z/3Y65Ps6G4 
#include <iostream>   // cin, cout für Eingabe und Ausgabe

void eingabe(unsigned &gebTag_,
             unsigned &gebMonat_,
             unsigned &gebJahr_,
             unsigned long long &steuernummer_,
             double &koerperlaenge_) 
{
    /* Eingaben noch ohne gute Fehlerbehandlung... */
    std::cout << "Geb.-Tag: "; std::cin >> gebTag_;
    std::cout << "Geb.-Monat: "; std::cin >> gebMonat_;
    std::cout << "Geb.-Jahr: "; std::cin >> gebJahr_;
    std::cout << "Steuernummer: "; std::cin >> steuernummer_;
    std::cout << "Koerperlaenge: "; std::cin >> koerperlaenge_;
}
int main() {
    /* Daten */
    unsigned gebTag_ = 0;
    unsigned gebMonat_ = 0;
    unsigned gebJahr_ = 0;
    unsigned long long steuernummer_ = 0;
    double koerperlaenge_ = 0.0;
    /* Eingabe */
    eingabe(gebTag_, gebMonat_, gebJahr_, steuernummer_, koerperlaenge_);
    /* Berechnungen */
    // …
}

Godbolt Listing lst-0074-godb.cpp, https://godbolt.org/z/3Y65Ps6G4:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3Y65Ps6G4 
#include <iostream>   // cin, cout für Eingabe und Ausgabe

void eingabe(unsigned &gebTag_,
             unsigned &gebMonat_,
             unsigned &gebJahr_,
             unsigned long long &steuernummer_,
             double &koerperlaenge_) 
{
    /* Eingaben noch ohne gute Fehlerbehandlung... */
    std::cout << "Geb.-Tag: "; std::cin >> gebTag_;
    std::cout << "Geb.-Monat: "; std::cin >> gebMonat_;
    std::cout << "Geb.-Jahr: "; std::cin >> gebJahr_;
    std::cout << "Steuernummer: "; std::cin >> steuernummer_;
    std::cout << "Koerperlaenge: "; std::cin >> koerperlaenge_;
}
int main() {
    /* Daten */
    unsigned gebTag_ = 0;
    unsigned gebMonat_ = 0;
    unsigned gebJahr_ = 0;
    unsigned long long steuernummer_ = 0;
    double koerperlaenge_ = 0.0;
    /* Eingabe */
    eingabe(gebTag_, gebMonat_, gebJahr_, steuernummer_, koerperlaenge_);
    /* Berechnungen */
    // …
}

Listing 4.35: Arithmetik mit Ganzzahlen

Book listing lst-0076-book.cpp:

// https://godbolt.org/z/ebPcdxzvj 
#include <iostream>
int main() {
    std::cout << 3 + 4 * 5 + 6 << "\n";               // 29
    std::cout << 20/7 << " Rest " << 20%7 << "\n";    // 2 Rest 6
}

Godbolt Listing lst-0076-godb.cpp, https://godbolt.org/z/ebPcdxzvj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ebPcdxzvj 
#include <iostream>
int main() {
    std::cout << 3 + 4 * 5 + 6 << "\n";               // 29
    std::cout << 20/7 << " Rest " << 20%7 << "\n";    // 2 Rest 6
}

Listing 4.36: Bitoperationen

Book listing lst-0077-book.cpp:

// https://godbolt.org/z/jeTs5Exqx 
#include <iostream>
int main() {
    unsigned a = 0b1111'0000;       // 240
    unsigned b = 0b0011'1100;       // 60
    std::cout << ( a | b ) << "\n"; // Bit-Oder: 252, in Bits 1111'1100
    std::cout << ( a & b ) << "\n"; // Bit-Und: 48, in Bits 0011'0000
    std::cout << ( a ^ b ) << "\n"; // Exklusiv-Oder: 204, in Bits 1100'1100
    unsigned int c = 170;           // in Bits 0..(24x0)..0'1010'1010
    std::cout << ( ~c ) << "\n";    // Inv.: 4294967125, Bits: 1..(24x1)..1'0101'0101
}

Godbolt Listing lst-0077-godb.cpp, https://godbolt.org/z/jeTs5Exqx:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jeTs5Exqx 
#include <iostream>
int main() {
    unsigned a = 0b1111'0000;       // 240
    unsigned b = 0b0011'1100;       // 60
    std::cout << ( a | b ) << "\n"; // Bit-Oder: 252, in Bits 1111'1100
    std::cout << ( a & b ) << "\n"; // Bit-Und: 48, in Bits 0011'0000
    std::cout << ( a ^ b ) << "\n"; // Exklusiv-Oder: 204, in Bits 1100'1100
    unsigned int c = 170;           // in Bits 0..(24x0)..0'1010'1010
    std::cout << ( ~c ) << "\n";    // Inv.: 4294967125, Bits: 1..(24x1)..1'0101'0101
}

Listing 4.37: Indexvariablen können gut vom Typ »size_t« sein.

Book listing lst-0079-book.cpp:

// https://godbolt.org/z/zGso3xGcj 
#include <vector>
#include <cstddef>  // size_t
int main() {
    std::vector<int> data = {  100, -4, 6'699, 88, 0,  } ;
    int sum = 0;
    for(size_t idx = 0; idx < data.size(); ++idx) { // ein bestimmter int-Typ
        sum += data[idx];
    }
}

Godbolt Listing lst-0079-godb.cpp, https://godbolt.org/z/zGso3xGcj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zGso3xGcj 
#include <vector>
#include <cstddef>  // size_t
int main() {
    std::vector<int> data = {  100, -4, 6'699, 88, 0,  } ;
    int sum = 0;
    for(size_t idx = 0; idx < data.size(); ++idx) { // ein bestimmter int-Typ
        sum += data[idx];
    }
}

Listing 4.41: »double« kann Zahlen nicht immer exakt speichern. Rechnen und Vergleichen mit »==« ist ein Fehler.

Book listing lst-0080-book.cpp:

// https://godbolt.org/z/h86Wh5dbo 
#include <iostream>      // cout
#include <iomanip>       // setprecision, etc.
#include <cmath>         // fabs
using std::cout;         // cout als Abkürzung für std::cout
int main() {
    cout << std::fixed << std::setprecision(25);  // für besser lesbare Ausgabe
    // 0.1 und 0.01 kann double nicht exakt speichern
    double x = 0.1 * 0.1;
    cout << "0.1*0.1: " << x << "\n";
    // Ausgabe: 0.1*0.1: 0.0100000000000000019428903
    if(x == 0.01) {      //                 (ERR)  vergleichen Sie double niemals mit ==
        cout << "Ja! x == 0.01" << "\n";
    } else {
        cout << "Oh-oh! x != 0.01" << "\n";      // Sie sehen diese Ausgabe
    }
    // Achtung vor allem beim Vergleich mit 0.0
    double null = x - 0.01;
    cout << "null: " << null << "\n";
    // Ausgabe: null: 0.0000000000000000017347235
    if(std::fabs(null) < 0.00000001) {           // gegen ein "Epsilon"
        cout << "Ja! null ist nahe 0.0" << "\n"; // Sie sehen diese Ausgabe
    } else {
        cout << "Oh-oh! null nicht nahe 0.0" << "\n";
    }
    // Brüche von 2er-Potenzen sind weniger kritisch
    double y = 0.5 * 0.5; 
    cout << "0.5*0.5: " <<  y << "\n";
    // Ausgabe: 0.5*0.5: 0.2500000000000000000000000
    if(y == 0.25) {    // hier klappt der gefährliche Vergleich ausnahmsweise
        cout << "Ja! y == 0.25" << "\n";         // Sie sehen diese Ausgabe
    } else {
        cout << "Oh-oh! y != 0.25" << "\n";
    }
    //
    return 0;
}

Godbolt Listing lst-0080-godb.cpp, https://godbolt.org/z/h86Wh5dbo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h86Wh5dbo 
#include <iostream>      // cout
#include <iomanip>       // setprecision, etc.
#include <cmath>         // fabs
using std::cout;         // cout als Abkürzung für std::cout
int main() {
    cout << std::fixed << std::setprecision(25);  // für besser lesbare Ausgabe
    // 0.1 und 0.01 kann double nicht exakt speichern
    double x = 0.1 * 0.1;
    cout << "0.1*0.1: " << x << "\n";
    // Ausgabe: 0.1*0.1: 0.0100000000000000019428903
    if(x == 0.01) {      //                 (ERR)  vergleichen Sie double niemals mit ==
        cout << "Ja! x == 0.01" << "\n";
    } else {
        cout << "Oh-oh! x != 0.01" << "\n";      // Sie sehen diese Ausgabe
    }
    // Achtung vor allem beim Vergleich mit 0.0
    double null = x - 0.01;
    cout << "null: " << null << "\n";
    // Ausgabe: null: 0.0000000000000000017347235
    if(std::fabs(null) < 0.00000001) {           // gegen ein "Epsilon"
        cout << "Ja! null ist nahe 0.0" << "\n"; // Sie sehen diese Ausgabe
    } else {
        cout << "Oh-oh! null nicht nahe 0.0" << "\n";
    }
    // Brüche von 2er-Potenzen sind weniger kritisch
    double y = 0.5 * 0.5; 
    cout << "0.5*0.5: " <<  y << "\n";
    // Ausgabe: 0.5*0.5: 0.2500000000000000000000000
    if(y == 0.25) {    // hier klappt der gefährliche Vergleich ausnahmsweise
        cout << "Ja! y == 0.25" << "\n";         // Sie sehen diese Ausgabe
    } else {
        cout << "Oh-oh! y != 0.25" << "\n";
    }
    //
    return 0;
}

Listing 4.39: Mehrere Möglichkeiten, um »double«-Literale zu kennzeichnen

Book listing lst-0081-book.cpp:

// https://godbolt.org/z/f7T5Y6sd3 
#include <iostream>
#include <iomanip>                              // fixed, setprecision
using std::cout;                                // abgekürzt cout
int main() {
    cout << std::setprecision(2) << std::fixed; // zwei Nachkommastellen
    cout << "1/4: " << 0.25 << "\n";            // Kommaschreibweise für double
    // Ausgabe: 1/4: 0.25

    cout << "2/4: " << 0.5 << "\n";
    // Ausgabe: 2/4: 0.50
    cout << "3/4: " << 0.75 << "\n";
    // Ausgabe: 3/4: 0.75
    cout << "4/4: " << 1 << " oder " << 1.0 << "\n"; //                     (ERR)  erkennt 1 als int
    // Ausgabe 4/4: 1 oder 1.00
    cout << "1e0: " << 1e0 << "\n";             // wissenschaftliche Schreibweise
    // Ausgabe: 1e0: 1.00
    cout << "0x10.1p0: " << 0x10.1p0 << "\n";   // hexadezimale Schreibweise
    // Ausgabe: 0x10.1p0: 16.06
}

Godbolt Listing lst-0081-godb.cpp, https://godbolt.org/z/f7T5Y6sd3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/f7T5Y6sd3 
#include <iostream>
#include <iomanip>                              // fixed, setprecision
using std::cout;                                // abgekürzt cout
int main() {
    cout << std::setprecision(2) << std::fixed; // zwei Nachkommastellen
    cout << "1/4: " << 0.25 << "\n";            // Kommaschreibweise für double
    // Ausgabe: 1/4: 0.25

    cout << "2/4: " << 0.5 << "\n";
    // Ausgabe: 2/4: 0.50
    cout << "3/4: " << 0.75 << "\n";
    // Ausgabe: 3/4: 0.75
    cout << "4/4: " << 1 << " oder " << 1.0 << "\n"; //                     (ERR)  erkennt 1 als int
    // Ausgabe 4/4: 1 oder 1.00
    cout << "1e0: " << 1e0 << "\n";             // wissenschaftliche Schreibweise
    // Ausgabe: 1e0: 1.00
    cout << "0x10.1p0: " << 0x10.1p0 << "\n";   // hexadezimale Schreibweise
    // Ausgabe: 0x10.1p0: 16.06
}

Listing 4.43: Fließkommaliterale werden irgendwann ungenau.

Book listing lst-0082-book.cpp:

// https://godbolt.org/z/6qfo4oYnr 
#include <iostream>
#include <iomanip> // fixed, setprecision
int main() {
    std::cout << std::setprecision(30) << std::fixed;     // immer 30 Stellen
                                                          // ausgeben
    std::cout <<  1.111222333444555666777888999f << "\n"; // float-Literal
    // Ausgabe: 1.111222386360168457031250000000
    std::cout <<  1.111222333444555666777888999 << "\n";  // double ist Default
    // Ausgabe: 1.111222333444555676607023997349
    std::cout <<  1.111222333444555666777888999d << "\n"; // double-Literal
    // Ausgabe: 1.111222333444555676607023997349
    std::cout <<  1.111222333444555666777888999L << "\n"; // long double
    // Ausgabe: 1.111222333444555666740784227731
}

Godbolt Listing lst-0082-godb.cpp, https://godbolt.org/z/6qfo4oYnr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6qfo4oYnr 
#include <iostream>
#include <iomanip> // fixed, setprecision
int main() {
    std::cout << std::setprecision(30) << std::fixed;     // immer 30 Stellen
                                                          // ausgeben
    std::cout <<  1.111222333444555666777888999f << "\n"; // float-Literal
    // Ausgabe: 1.111222386360168457031250000000
    std::cout <<  1.111222333444555666777888999 << "\n";  // double ist Default
    // Ausgabe: 1.111222333444555676607023997349
    std::cout <<  1.111222333444555666777888999d << "\n"; // double-Literal
    // Ausgabe: 1.111222333444555676607023997349
    std::cout <<  1.111222333444555666777888999L << "\n"; // long double
    // Ausgabe: 1.111222333444555666740784227731
}

Listing 4.44: Unter anderem können Sie mit »fpclassify« besondere Werte entdecken.

Book listing lst-0083-book.cpp:

// https://godbolt.org/z/v98fWc49E 
#include <iostream>
#include <cmath>  // fpclassify
#include <limits> // numeric_limits
#include <string>
std::string fpklass(double x) {
    switch(std::fpclassify(x)) {
        case FP_INFINITE:  return "unendlich";
        case FP_NAN:       return "NaN";
        case FP_NORMAL:    return "normal";
        case FP_SUBNORMAL: return "subnormal";
        case FP_ZERO:      return "Null";
        default:           return "unbekannt";
    }
}
int main() {
    const auto dmin = std::numeric_limits<double>::min();
    std::cout
      <<"1.0/0.0 ist "<<fpklass(1/0.0)<<'\n'   // Ausgabe: 1.0/0.0 ist unendlich
      <<"0.0/0.0 ist "<<fpklass(0.0/0.0)<<'\n' // Ausgabe: 0.0/0.0 ist NaN
      <<"dmin/2 ist "<<fpklass(dmin/2)<<'\n'   // Ausgabe: dmin/2 ist subnormal
      <<"-0.0 ist "<<fpklass(-0.0)<<'\n'       // Ausgabe: –0.0 ist null
      <<"1.0 ist "<<fpklass(1.0)<<'\n';        // Ausgabe: 1.0 ist normal
}

Godbolt Listing lst-0083-godb.cpp, https://godbolt.org/z/v98fWc49E:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/v98fWc49E 
#include <iostream>
#include <cmath>  // fpclassify
#include <limits> // numeric_limits
#include <string>
std::string fpklass(double x) {
    switch(std::fpclassify(x)) {
        case FP_INFINITE:  return "unendlich";
        case FP_NAN:       return "NaN";
        case FP_NORMAL:    return "normal";
        case FP_SUBNORMAL: return "subnormal";
        case FP_ZERO:      return "Null";
        default:           return "unbekannt";
    }
}
int main() {
    const auto dmin = std::numeric_limits<double>::min();
    std::cout
      <<"1.0/0.0 ist "<<fpklass(1/0.0)<<'\n'   // Ausgabe: 1.0/0.0 ist unendlich
      <<"0.0/0.0 ist "<<fpklass(0.0/0.0)<<'\n' // Ausgabe: 0.0/0.0 ist NaN
      <<"dmin/2 ist "<<fpklass(dmin/2)<<'\n'   // Ausgabe: dmin/2 ist subnormal
      <<"-0.0 ist "<<fpklass(-0.0)<<'\n'       // Ausgabe: –0.0 ist null
      <<"1.0 ist "<<fpklass(1.0)<<'\n';        // Ausgabe: 1.0 ist normal
}

GodboltId:We3oWrcWW

Book listing lst-0086-book.cpp:

// https://godbolt.org/z/We3oWrcWW 
#include <iostream>
#include <cmath>     // sqrt
#include <concepts>  // floating_point
using std::min; using std::max; using std::floating_point;

template<floating_point T> T heron(T a, T b, T c) {
    auto s = (a+b+c) / 2;
    return sqrt(s*(s-a)*(s-b)*(s-c));
}

template<floating_point T> T kahan(T a, T b, T c) {
   auto x = max(a,max(b,c));
   auto y = max(min(a,b), min(max(a,b),c));
   auto z = min(a,min(b,c));
   return sqrt( (x+(y+z))*(z-(x-y))*(z+(x-y))*(x+(y-z)) )/4 ;
}

template<floating_point T> void dreieck(T a, T b, T c) {
   std::cout << "heron: " << heron(a,b,c) << '\n';
   std::cout << "kahan: " << kahan(a,b,c) << '\n';
}

int main() {
   dreieck(3.0f, 4.0f, 5.0f);
}

Godbolt Listing lst-0086-godb.cpp, https://godbolt.org/z/We3oWrcWW:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/We3oWrcWW 
#include <iostream>
#include <cmath>     // sqrt
#include <concepts>  // floating_point
using std::min; using std::max; using std::floating_point;

template<floating_point T> T heron(T a, T b, T c) {
    auto s = (a+b+c) / 2;
    return sqrt(s*(s-a)*(s-b)*(s-c));
}

template<floating_point T> T kahan(T a, T b, T c) {
   auto x = max(a,max(b,c));
   auto y = max(min(a,b), min(max(a,b),c));
   auto z = min(a,min(b,c));
   return sqrt( (x+(y+z))*(z-(x-y))*(z+(x-y))*(x+(y-z)) )/4 ;
}

template<floating_point T> void dreieck(T a, T b, T c) {
   std::cout << "heron: " << heron(a,b,c) << '\n';
   std::cout << "kahan: " << kahan(a,b,c) << '\n';
}

int main() {
   dreieck(3.0f, 4.0f, 5.0f);
}

GodboltId:863b1z4GY

Book listing lst-0087-book.cpp:

// https://godbolt.org/z/863b1z4GY 
int main() {
   std::cout << std::setprecision(15) << std::fixed;
   dreieck(100'000.0f, 99'999.999'79f, 0.000'29f);
   dreieck(100'000.0,  99'999.999'79,  0.000'29);
}

Godbolt Listing lst-0087-godb.cpp, https://godbolt.org/z/863b1z4GY:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/863b1z4GY 
int main() {
   std::cout << std::setprecision(15) << std::fixed;
   dreieck(100'000.0f, 99'999.999'79f, 0.000'29f);
   dreieck(100'000.0,  99'999.999'79,  0.000'29);
}

Listing 4.45: Akkumulierte Zeitmessung

Book listing lst-0088-book.cpp:

// https://godbolt.org/z/drz7fzohh 
#include <iostream>
#include <iomanip> // setprecision, fixed
constexpr int bilderProSek = 25;
constexpr int laufZeitInSek = 3600;
constexpr int bilderInsg = laufZeitInSek * bilderProSek;
constexpr float bildzeit = 1.0f / bilderProSek;

int main() {
    float filmzeit = 0.f;
    for(int n=1; n <= bilderInsg; ++n) { // 1 .. bilderInsg
        filmzeit += bildzeit;// akkumulieren
        // … hier Code für dieses Frame …
    }
    std::cout << std::setprecision(10) << std::fixed
        << filmzeit << '\n'; // Ausgabe: 3602.2695312500
}

Godbolt Listing lst-0088-godb.cpp, https://godbolt.org/z/drz7fzohh:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/drz7fzohh 
#include <iostream>
#include <iomanip> // setprecision, fixed
constexpr int bilderProSek = 25;
constexpr int laufZeitInSek = 3600;
constexpr int bilderInsg = laufZeitInSek * bilderProSek;
constexpr float bildzeit = 1.0f / bilderProSek;

int main() {
    float filmzeit = 0.f;
    for(int n=1; n <= bilderInsg; ++n) { // 1 .. bilderInsg
        filmzeit += bildzeit;// akkumulieren
        // … hier Code für dieses Frame …
    }
    std::cout << std::setprecision(10) << std::fixed
        << filmzeit << '\n'; // Ausgabe: 3602.2695312500
}

Listing 4.46: Geschlossene Zeitberechnung

Book listing lst-0089-book.cpp:

// https://godbolt.org/z/xz6TGdc19 
#include <iostream>
#include <iomanip> // setprecision, fixed
constexpr int bilderProSek = 25;
constexpr int laufZeitInSek = 3600;
constexpr int bilderInsg = laufZeitInSek * bilderProSek;
constexpr float bildzeit = 1.0f / bilderProSek;
int main() {
    float filmzeit = 0.f;
    for(int n=1; n <= bilderInsg; ++n) { // 1 .. bilderInsg, wegen Formel
        filmzeit = bildzeit * n; // skalieren
        // … hier Code für dieses Frame …
    }
    std::cout << std::setprecision(10) << std::fixed
        << filmzeit << '\n';     // Ausgabe: 3600.0000000000
}

Godbolt Listing lst-0089-godb.cpp, https://godbolt.org/z/xz6TGdc19:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xz6TGdc19 
#include <iostream>
#include <iomanip> // setprecision, fixed
constexpr int bilderProSek = 25;
constexpr int laufZeitInSek = 3600;
constexpr int bilderInsg = laufZeitInSek * bilderProSek;
constexpr float bildzeit = 1.0f / bilderProSek;
int main() {
    float filmzeit = 0.f;
    for(int n=1; n <= bilderInsg; ++n) { // 1 .. bilderInsg, wegen Formel
        filmzeit = bildzeit * n; // skalieren
        // … hier Code für dieses Frame …
    }
    std::cout << std::setprecision(10) << std::fixed
        << filmzeit << '\n';     // Ausgabe: 3600.0000000000
}

Listing 4.47: Mit komplexen Zahlen können Sie arithmetisch rechnen.

Book listing lst-0093-book.cpp:

// https://godbolt.org/z/43rYYeKx9 
#include <iostream>
#include <iomanip>    // setprecision, fixed
#include <complex>
using std::cout; using std::complex;

int main() {
    using namespace std::complex_literals;   // für i-Suffix
    cout << std::fixed << std::setprecision(1);
    complex<double> z1 = 1i * 1i;            // i mal i
    cout << z1 << '\n';                      // Ausgabe: (–1.0,0.0)
    complex<double> z2 = std::pow(1i, 2);    // i-Quadrat
    cout << z2 << '\n';                      // Ausgabe: (–1.0,0.0)
    double PI = std::acos(-1);               // Länge eines halben Einheitskreises
    complex<double> z3 = std::exp(1i * PI);  // Euler-Formel
    cout << z3 << '\n';                      // Ausgabe: (–1.0,0.0)
    complex<double> a(3, 4);                 // gewohnt als Konstruktor
    complex<double> b = 1. - 2i;             // praktisch als Literal

    // Berechnungen:
    cout << "a + b = " << a + b << "\n";     // Ausgabe: a + b = (4.0,2.0)
    cout << "a * b = " << a * b << "\n";     // Ausgabe: a * b = (11.0,–2.0)
    cout << "a / b = " << a / b << "\n";     // Ausgabe: a / b = (–1.0,2.0)
    cout << "|a| = "   << abs(a) << "\n";    // Ausgabe: |a| = 5.0
    cout << "conj(a) = " << conj(a) << "\n"; // Ausgabe: conj(a) = (3.0,–4.0)
    cout << "norm(a) = " << norm(a) << "\n"; // Ausgabe: norm(a) = 25.0
    cout << "abs(a) = " << abs(a) << "\n";   // Ausgabe: abs(a) = 5.0
    cout << "exp(a) = " << exp(a) << "\n";   // Ausgabe: exp(a) = (–13.1,–15.2)
}

Godbolt Listing lst-0093-godb.cpp, https://godbolt.org/z/43rYYeKx9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/43rYYeKx9 
#include <iostream>
#include <iomanip>    // setprecision, fixed
#include <complex>
using std::cout; using std::complex;

int main() {
    using namespace std::complex_literals;   // für i-Suffix
    cout << std::fixed << std::setprecision(1);
    complex<double> z1 = 1i * 1i;            // i mal i
    cout << z1 << '\n';                      // Ausgabe: (–1.0,0.0)
    complex<double> z2 = std::pow(1i, 2);    // i-Quadrat
    cout << z2 << '\n';                      // Ausgabe: (–1.0,0.0)
    double PI = std::acos(-1);               // Länge eines halben Einheitskreises
    complex<double> z3 = std::exp(1i * PI);  // Euler-Formel
    cout << z3 << '\n';                      // Ausgabe: (–1.0,0.0)
    complex<double> a(3, 4);                 // gewohnt als Konstruktor
    complex<double> b = 1. - 2i;             // praktisch als Literal

    // Berechnungen:
    cout << "a + b = " << a + b << "\n";     // Ausgabe: a + b = (4.0,2.0)
    cout << "a * b = " << a * b << "\n";     // Ausgabe: a * b = (11.0,–2.0)
    cout << "a / b = " << a / b << "\n";     // Ausgabe: a / b = (–1.0,2.0)
    cout << "|a| = "   << abs(a) << "\n";    // Ausgabe: |a| = 5.0
    cout << "conj(a) = " << conj(a) << "\n"; // Ausgabe: conj(a) = (3.0,–4.0)
    cout << "norm(a) = " << norm(a) << "\n"; // Ausgabe: norm(a) = 25.0
    cout << "abs(a) = " << abs(a) << "\n";   // Ausgabe: abs(a) = 5.0
    cout << "exp(a) = " << exp(a) << "\n";   // Ausgabe: exp(a) = (–13.1,–15.2)
}

Listing 4.48: Ausgabe in unspezifizierter Reihenfolge

Book listing lst-0095-book.cpp:

// https://godbolt.org/z/eW1cfYcGs 
#include <iostream>
void ausgabe(int a, int b) {
    std::cout << a << ' ' << b << '\n';
}
int zahl() {
    static int val = 0;
    return ++val;
}
int main() {
    ausgabe(zahl(), zahl()); // in welcher Reihenfolge?
}

Godbolt Listing lst-0095-godb.cpp, https://godbolt.org/z/eW1cfYcGs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eW1cfYcGs 
#include <iostream>
void ausgabe(int a, int b) {
    std::cout << a << ' ' << b << '\n';
}
int zahl() {
    static int val = 0;
    return ++val;
}
int main() {
    ausgabe(zahl(), zahl()); // in welcher Reihenfolge?
}

Listing 5.1: Einrückung vier, Klammern in Zeile mit Schlüsselwort, wenige Leerzeichen

Book listing lst-0097-book.cpp:

// https://godbolt.org/z/eP77v498E 
#include <iostream>
int func(int arg1, int arg2) {
    if(arg1 > arg2) {
        return arg1-arg2;
    } else {
        return arg2-arg1;
    }
}
int main(int argc, const char* argv[]) {
    for(int x=0; x<10; ++x) {
        for(int y=0; y<10; ++y) {
            std::cout << func(x,y) << " ";
        }
        std::cout << "\n";
    }
}

Godbolt Listing lst-0097-godb.cpp, https://godbolt.org/z/eP77v498E:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eP77v498E 
#include <iostream>
int func(int arg1, int arg2) {
    if(arg1 > arg2) {
        return arg1-arg2;
    } else {
        return arg2-arg1;
    }
}
int main(int argc, const char* argv[]) {
    for(int x=0; x<10; ++x) {
        for(int y=0; y<10; ++y) {
            std::cout << func(x,y) << " ";
        }
        std::cout << "\n";
    }
}

Listing 5.2: Einrückung zwei, Klammern nur wenn nötig und in eigener Zeile, mehr Leerzeichen

Book listing lst-0098-book.cpp:

// https://godbolt.org/z/4TMn37qhE 
#include <iostream>
int func ( int arg1, int arg2 )
{
  if (arg1 > arg2)
    return arg1 - arg2;
  else
    return arg2 - arg1;
}
int main ( int argc, const char *argv[] )
{
  for ( int x = 0 ; x < 10 ; ++x )
  {
    for ( int y = 0 ; y < 10 ; ++y )
      std::cout << func ( x, y ) << " ";
    std::cout << "\n";
  }
}

Godbolt Listing lst-0098-godb.cpp, https://godbolt.org/z/4TMn37qhE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4TMn37qhE 
#include <iostream>
int func ( int arg1, int arg2 )
{
  if (arg1 > arg2)
    return arg1 - arg2;
  else
    return arg2 - arg1;
}
int main ( int argc, const char *argv[] )
{
  for ( int x = 0 ; x < 10 ; ++x )
  {
    for ( int y = 0 ; y < 10 ; ++y )
      std::cout << func ( x, y ) << " ";
    std::cout << "\n";
  }
}

Listing 6.1: Einige Verwendungsmöglichkeiten von Strings

Book listing lst-0099-book.cpp:

// https://godbolt.org/z/vMvs47nfs 
#include <iostream>       // cin, cout für Eingabe und Ausgabe
#include <string>         // Sie benötigen diesen Header der Standardbibliothek

void eingabe(
    std::string &name,    // als Parameter
    unsigned &gebJahr)
{
    /* Eingaben noch ohne gute Fehlerbehandlung... */
    std::cout << "Name: ";
    std::getline(std::cin, name); // getline liest in einen String ein
    if(name.length() == 0) {      // length ist eine Methode von string
        std::cout << "Sie haben einen leeren Namen eingegeben.\n";
        exit(1);
    }
    std::cout << "Geb.-Jahr: ";
    std::cin >> gebJahr;
}
int main() {
    /* Daten */
    std::string name;             // definiert und initialisiert eine string-Variable
    unsigned gebJahr = 0;
    /* Eingabe */
    eingabe(name, gebJahr);
    /* Berechnungen */
    // …
}

Godbolt Listing lst-0099-godb.cpp, https://godbolt.org/z/vMvs47nfs:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vMvs47nfs 
#include <iostream>       // cin, cout für Eingabe und Ausgabe
#include <string>         // Sie benötigen diesen Header der Standardbibliothek

void eingabe(
    std::string &name,    // als Parameter
    unsigned &gebJahr)
{
    /* Eingaben noch ohne gute Fehlerbehandlung... */
    std::cout << "Name: ";
    std::getline(std::cin, name); // getline liest in einen String ein
    if(name.length() == 0) {      // length ist eine Methode von string
        std::cout << "Sie haben einen leeren Namen eingegeben.\n";
        exit(1);
    }
    std::cout << "Geb.-Jahr: ";
    std::cin >> gebJahr;
}
int main() {
    /* Daten */
    std::string name;             // definiert und initialisiert eine string-Variable
    unsigned gebJahr = 0;
    /* Eingabe */
    eingabe(name, gebJahr);
    /* Berechnungen */
    // …
}

Listing 6.2: Eine string_view lässt sich aus einen string leicht erzeugen.

Book listing lst-0102-book.cpp:

// https://godbolt/.org/z/bdaE5nf5T 
#include <iostream>
#include <string>
#include <string_view>
void zeige_mitte(std::string_view msg) {     // string_view ist ein guter Parameter
   auto mitte = msg.substr(2, msg.size()-4); // substr liefert string_view zurück
   std::cout << mitte << "\n";
}
int main() {
    using namespace std::literals;
    const std::string aaa = "##Etwas Text##"s;
    zeige_mitte(aaa);                        // Umwandlung in string_view
    auto bbb = "++Mehr Text++"sv;            // string_view als Literal
    zeige_mitte(bbb);
}

Listing 6.3: Der Fehlerstream ist von der Standardausgabe getrennt.

Book listing lst-0103-book.cpp:

// https://godbolt/.org/z/raYaeY357 
// Rufen Sie dieses Programm zum Beispiel mit 'prog.exe > datei.txt' auf.
#include <iostream>  // cout, cerr
int main() {
    std::cout << "Ausgabe nach cout\n";      // wird nach 'datei.txt' ausgegeben
    std::cerr << "Fehlermeldung!\n";         // erscheint trotzdem auf der Konsole
    std::cout << "Wieder normale Ausgabe\n"; // wieder in die Datei
}

Listing 6.4: Eine Funktion mit Ein- und Ausgabe

Book listing lst-0104-book.cpp:

// https://godbolt/.org/z/Gbe7aM4o4 
#include <iostream>                      // cin, cout für Eingabe und Ausgabe
#include <string>
#include <array>
using std::cin; using std::cout;         // Abkürzungen cin und cout
void eingabe(
    std::string &name,
    unsigned &gebTag,
    unsigned &gebMonat,
    unsigned &gebJahr,
    long long &steuernummer,
    std::array<int,12> &monatseinkommen) // array ist ein Container
{
    /* Eingaben noch ohne gute Fehlerbehandlung… */
    cout << "Name: ";
    std::getline(cin, name);   // getline nimmt Eingabestrom und String
    if(name.length() == 0) {
        cout << "Sie haben einen leeren Namen eingegeben.\n";
        exit(1);
    }
    cout << "Geb.-Tag: "; cin >> gebTag;
    cout << "Geb.-Monat: "; cin >> gebMonat;
    cout << "Geb.-Jahr: "; cin >> gebJahr;
    cout << "Steuernummer: "; cin >> steuernummer;
    for(int m=0; m<12; ++m) {
        cout << "Einkommen Monat " << m+1 << ": "; // mehrere Ausgaben
        cin >> monatseinkommen[m];                 // Einlesen mit Operator
    }
    cout << std::endl;
}
int main() {
    std::string name{};
    unsigned tag = 0;
    unsigned monat = 0;
    unsigned jahr = 0;
    long long stNr = 0;
    std::array<int,12> einkommen{};
    eingabe(name, tag, monat, jahr, stNr, einkommen);
    // … Berechnungen …
}

GodboltId:a6qqbWKMs

Book listing lst-0105-book.cpp:

//https://godbolt.org/z/a6qqbWKMs 
#include <cstdlib>
#include <iostream>

int main(int argc, char* argv[]) {
    for(int i=1; i<argc; ++i) {                // Start bei 1
        for(char* p=argv[i]; *p!='\0'; ++p) {
            char c = toupper(*p);
            std::cout << c;
        }
        std::cout << ' ';
    }
    std::cout << '\n';
}

Godbolt Listing lst-0105-godb.cpp, https://godbolt.org/z/a6qqbWKMs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/a6qqbWKMs 
#include <cstdlib>
#include <iostream>

int main(int argc, char* argv[]) {
    for(int i=1; i<argc; ++i) {                // Start bei 1
        for(char* p=argv[i]; *p!='\0'; ++p) {
            char c = toupper(*p);
            std::cout << c;
        }
        std::cout << ' ';
    }
    std::cout << '\n';
}

GodboltId:McqfcWb8j

Book listing lst-0106-book.cpp:

//https://godbolt.org/z/McqfcWb8j 
#include <fstream>
int main(int argc, char* argv[]) {
    std::ofstream meineAusgabe{"output1.txt"};
    meineAusgabe << "Zeile 1\n";
    meineAusgabe << "Zeile 2\n";
}

Godbolt Listing lst-0106-godb.cpp, https://godbolt.org/z/McqfcWb8j:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/McqfcWb8j 
#include <fstream>
int main(int argc, char* argv[]) {
    std::ofstream meineAusgabe{"output1.txt"};
    meineAusgabe << "Zeile 1\n";
    meineAusgabe << "Zeile 2\n";
}

GodboltId:P9z8n8v16

Book listing lst-0107-book.cpp:

//https://godbolt.org/z/P9z8n8v16 
#include <fstream>
int main(int argc, char* argv[]) {
    int wert = 0;
    std::ifstream meineEingabe{"input1.txt"};
    meineEingabe >> wert;
}

Godbolt Listing lst-0107-godb.cpp, https://godbolt.org/z/P9z8n8v16:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/P9z8n8v16 
#include <fstream>
int main(int argc, char* argv[]) {
    int wert = 0;
    std::ifstream meineEingabe{"input1.txt"};
    meineEingabe >> wert;
}

Listing 6.5: Verwenden Sie den !-Operator, um den Zustand des Streams zu prüfen.

Book listing lst-0108-book.cpp:

//https://godbolt.org/z/ssW3eKEGq 
#include <iostream> // cerr
#include <fstream>
int main(int argc, char* argv[]) {
    int wert;
    std::ifstream meineEingabe{"input1.txt"};
    if(!meineEingabe) {
        std::cerr << "Fehler beim Öffnen der Datei!\n";
    } else {
        meineEingabe >> wert;
    }
}

Godbolt Listing lst-0108-godb.cpp, https://godbolt.org/z/ssW3eKEGq:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/ssW3eKEGq 
#include <iostream> // cerr
#include <fstream>
int main(int argc, char* argv[]) {
    int wert;
    std::ifstream meineEingabe{"input1.txt"};
    if(!meineEingabe) {
        std::cerr << "Fehler beim Öffnen der Datei!\n";
    } else {
        meineEingabe >> wert;
    }
}

Listing 6.6: Verwenden Sie Streammanipulatoren aus , um das Format der Ausgabe zu beeinflussen.

Book listing lst-0109-book.cpp:

//https://godbolt.org/z/EcnWz3r3j 
#include <iostream>
#include <iomanip>                   // fixed, setprecision
#include <format>                    // C++20
using std::cout; using std::format;  // Abkürzung cout, format
int main() {
    cout << std::fixed               // Punktschreibweise, nicht wissenschaftlich
         << std::setprecision(15);   // 15 Nachkommastellen
    cout << 0.5 << "\n";             // Ausgabe: 0.500000000000000*
    cout << std::setprecision(5);    // 5 Nachkommastellen
    cout << 0.25 << "\n";            // Ausgabe: 0.25000
    cout << format("{:0.4f}", 0.75) << "\n"; // (C++20) Ausgabe: 0.7500
    return 0;
}

Godbolt Listing lst-0109-godb.cpp, https://godbolt.org/z/EcnWz3r3j:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
//https://godbolt.org/z/EcnWz3r3j 
#include <iostream>
#include <iomanip>                   // fixed, setprecision
#include <format>                    // C++20
using std::cout; using std::format;  // Abkürzung cout, format
int main() {
    cout << std::fixed               // Punktschreibweise, nicht wissenschaftlich
         << std::setprecision(15);   // 15 Nachkommastellen
    cout << 0.5 << "\n";             // Ausgabe: 0.500000000000000*
    cout << std::setprecision(5);    // 5 Nachkommastellen
    cout << 0.25 << "\n";            // Ausgabe: 0.25000
    cout << format("{:0.4f}", 0.75) << "\n"; // (C++20) Ausgabe: 0.7500
    return 0;
}

Listing 6.7: In einem »array« speichern Sie eine feste Anzahl Elemente.

Book listing lst-0112-book.cpp:

// https://godbolt.org/z/cd1d1W7T1 
#include <array>
#include <iostream>
using std::cout; using std::array; using std::string;
int main() {
  array<string,7> wotag = { "Montag", "Dienstag",        // definieren
      "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag" };
  cout << "Die Woche beginnt mit " << wotag[0] << ".\n"; // Werte lesen
  cout << "Sie endet mit " << wotag.at(6) << ".\n";      // sicheres Werte lesen
  /* nordisch? */
  wotag[5] = "Sonnabend";                                // Werte verändern
}

Godbolt Listing lst-0112-godb.cpp, https://godbolt.org/z/cd1d1W7T1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cd1d1W7T1 
#include <array>
#include <iostream>
using std::cout; using std::array; using std::string;
int main() {
  array<string,7> wotag = { "Montag", "Dienstag",        // definieren
      "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag" };
  cout << "Die Woche beginnt mit " << wotag[0] << ".\n"; // Werte lesen
  cout << "Sie endet mit " << wotag.at(6) << ".\n";      // sicheres Werte lesen
  /* nordisch? */
  wotag[5] = "Sonnabend";                                // Werte verändern
}

Listing 6.8: Die Arraygröße muss konstant sein.

Book listing lst-0113-book.cpp:

// https://godbolt.org/z/zfe7dM4ex 
#include <array>
#include <iostream>
constexpr size_t MONATE = 12; /* Monate im Jahr */
int main() {
    std::array<unsigned,MONATE> mtage = {     // okay mit einer Konstante
        31,28,31,30,31,30,31,31,30,31,30,31};
    unsigned alter = 0;
    std::cout << "Wie alt sind Sie? "; std::cin >> alter;
    std::array<int,alter> lebensjahre;       // Arraygröße geht nicht per Variable
}

Godbolt Listing lst-0113-godb.cpp, https://godbolt.org/z/zfe7dM4ex:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zfe7dM4ex 
#include <array>
#include <iostream>
constexpr size_t MONATE = 12; /* Monate im Jahr */
int main() {
    std::array<unsigned,MONATE> mtage = {     // okay mit einer Konstante
        31,28,31,30,31,30,31,31,30,31,30,31};
    unsigned alter = 0;
    std::cout << "Wie alt sind Sie? "; std::cin >> alter;
    std::array<int,alter> lebensjahre;       // Arraygröße geht nicht per Variable
}

Listing 6.9: Wenn Sie eine Arraydefinition mehrfach verwenden müssen, dann verwenden Sie »using«.

Book listing lst-0114-book.cpp:

// https://godbolt.org/z/a4zxbd99z 
#include <array>
#include <algorithm>                    // accumulate
#include <numeric>                      // iota
using Januar = std::array<int,31>;      // Alias für wiederholte Verwendung

void initJanuar(Januar& jan) {          // das genaue Array als Parameter
    std::iota(begin(jan), end(jan), 1); // füllt mit  1, 2, 3 … 31
}
int sumJanuar(const Januar& jan) {      // das genaue Array als Parameter
    return std::accumulate(begin(jan), end(jan), 0); // Hilfsfunktion für Summe
}
int main() {
    Januar jan;                         // deklariert ein array<int,31>
    initJanuar( jan );
    int sum = sumJanuar( jan );
}

Godbolt Listing lst-0114-godb.cpp, https://godbolt.org/z/a4zxbd99z:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a4zxbd99z 
#include <array>
#include <algorithm>                    // accumulate
#include <numeric>                      // iota
using Januar = std::array<int,31>;      // Alias für wiederholte Verwendung

void initJanuar(Januar& jan) {          // das genaue Array als Parameter
    std::iota(begin(jan), end(jan), 1); // füllt mit  1, 2, 3 … 31
}
int sumJanuar(const Januar& jan) {      // das genaue Array als Parameter
    return std::accumulate(begin(jan), end(jan), 0); // Hilfsfunktion für Summe
}
int main() {
    Januar jan;                         // deklariert ein array<int,31>
    initJanuar( jan );
    int sum = sumJanuar( jan );
}

GodboltId:T9jsEoMj4

Book listing lst-0115-book.cpp:

// https://godbolt.org/z/T9jsEoMj4 
#include <vector>                    // Sie benötigen diesen Header
int main() {
    std::vector<int> quadrate{};     // leer initialisieren
    for(int idx = 0; idx<100; ++idx) {
        quadrate.push_back(idx*idx); // Anfügen eines Elements
    }
}

Godbolt Listing lst-0115-godb.cpp, https://godbolt.org/z/T9jsEoMj4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/T9jsEoMj4 
#include <vector>                    // Sie benötigen diesen Header
int main() {
    std::vector<int> quadrate{};     // leer initialisieren
    for(int idx = 0; idx<100; ++idx) {
        quadrate.push_back(idx*idx); // Anfügen eines Elements
    }
}

Listing 6.10: Die einfachste Iteration benutzt eine bereichsbasierte »for«-Schleife.

Book listing lst-0116-book.cpp:

// https://godbolt.org/z/hhhavG5he 
#include <vector>
#include <iostream>                     // cout, endl
int main() {
    std::vector quadrate{1,4,9,16,25};  // gefüllt initialisieren
    for(int zahl : quadrate)  // zahl ist ein Quadrat nach dem anderen
        std::cout << zahl << " ";
    std::cout << std::endl;
}

Godbolt Listing lst-0116-godb.cpp, https://godbolt.org/z/hhhavG5he:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hhhavG5he 
#include <vector>
#include <iostream>                     // cout, endl
int main() {
    std::vector quadrate{1,4,9,16,25};  // gefüllt initialisieren
    for(int zahl : quadrate)  // zahl ist ein Quadrat nach dem anderen
        std::cout << zahl << " ";
    std::cout << std::endl;
}

Listing 6.11: Der Zugriff auf die Elemente per Index

Book listing lst-0117-book.cpp:

// https://godbolt.org/z/xcKM7v1Eo 
#include <vector>
#include <iostream>                           // cout, endl
int main() {
  std::vector qus{1,4,9,16,25};
  for(unsigned idx=0; idx<qus.size(); ++idx)  // size enthält die Anzahl
    std::cout << qus[idx] << " ";             // [idx] oder at(idx) holt ein Element
  std::cout << std::endl;
}

Godbolt Listing lst-0117-godb.cpp, https://godbolt.org/z/xcKM7v1Eo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xcKM7v1Eo 
#include <vector>
#include <iostream>                           // cout, endl
int main() {
  std::vector qus{1,4,9,16,25};
  for(unsigned idx=0; idx<qus.size(); ++idx)  // size enthält die Anzahl
    std::cout << qus[idx] << " ";             // [idx] oder at(idx) holt ein Element
  std::cout << std::endl;
}

Listing 6.12: Der Einsatz von Iteratoren für eine Schleife

Book listing lst-0118-book.cpp:

// https://godbolt.org/z/1WG8zvhYe 
#include <vector>
#include <iostream>                  // cout, endl
int main() {
  std::vector qus{1,4,9,16,25};
  for(auto it = qus.begin(); it!=qus.end(); ++it) // zwischen begin() und end()
    std::cout << *it << " ";         // mit *it kommen Sie vom Iterator zum Element
  std::cout << std::endl;
}

Godbolt Listing lst-0118-godb.cpp, https://godbolt.org/z/1WG8zvhYe:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1WG8zvhYe 
#include <vector>
#include <iostream>                  // cout, endl
int main() {
  std::vector qus{1,4,9,16,25};
  for(auto it = qus.begin(); it!=qus.end(); ++it) // zwischen begin() und end()
    std::cout << *it << " ";         // mit *it kommen Sie vom Iterator zum Element
  std::cout << std::endl;
}

Listing 6.13: Zählen mit einem Algorithmus

Book listing lst-0119-book.cpp:

// https://godbolt.org/z/4G67rso8T 
#include <vector>
#include <algorithm>                           // count_if
#include <numeric>                             // iota
#include <iostream>
bool even(int n) { return n%2==0; }            // Test auf gerade
int main() {
    std::vector<int> data(100);                // 100 x null
    std::iota(data.begin(), data.end(), 0);    // 0, 1, 2, … 99
    // zählt gerade Zahlen
    std::cout << std::count_if(data.begin(), data.end(), even);
}

Godbolt Listing lst-0119-godb.cpp, https://godbolt.org/z/4G67rso8T:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4G67rso8T 
#include <vector>
#include <algorithm>                           // count_if
#include <numeric>                             // iota
#include <iostream>
bool even(int n) { return n%2==0; }            // Test auf gerade
int main() {
    std::vector<int> data(100);                // 100 x null
    std::iota(data.begin(), data.end(), 0);    // 0, 1, 2, … 99
    // zählt gerade Zahlen
    std::cout << std::count_if(data.begin(), data.end(), even);
}

Listing 7.1: Funktionen verwenden

Book listing lst-0127-book.cpp:

// https://godbolt.org/z/5ssc6W5o6 
#include <iostream>              // cout
#include <cmath>                 // sin
#include <string>
#include <vector>
using std::sin;
int main() {
    std::cout << "sin(0.0): " << sin(0.0) << "\n";  // Aufruf von sin() mit Literal
    double winkel = 3.1415/2;
    std::cout << "sin("<<winkel<<"): "<<sin(winkel)<<"\n"; // Aufruf mit Variable
    std::string name = "Han Solo";
    std::cout << name.length() << "\n"; // Aufruf einer Methode
                                        // … konzeptionell wie length(name)
    std::vector<int> data{};
    data.push_back(5);                 // weiterer Methodenaufruf mit Parameter
    data.push_back(10);
    std::cout << data.back() << " ";
    data.pop_back();
    std::cout << data.back() << "\n";
    data.pop_back();
}

Godbolt Listing lst-0127-godb.cpp, https://godbolt.org/z/5ssc6W5o6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5ssc6W5o6 
#include <iostream>              // cout
#include <cmath>                 // sin
#include <string>
#include <vector>
using std::sin;
int main() {
    std::cout << "sin(0.0): " << sin(0.0) << "\n";  // Aufruf von sin() mit Literal
    double winkel = 3.1415/2;
    std::cout << "sin("<<winkel<<"): "<<sin(winkel)<<"\n"; // Aufruf mit Variable
    std::string name = "Han Solo";
    std::cout << name.length() << "\n"; // Aufruf einer Methode
                                        // … konzeptionell wie length(name)
    std::vector<int> data{};
    data.push_back(5);                 // weiterer Methodenaufruf mit Parameter
    data.push_back(10);
    std::cout << data.back() << " ";
    data.pop_back();
    std::cout << data.back() << "\n";
    data.pop_back();
}

Listing 7.2: Verschiedene Rückgabetypen von Funktionen

Book listing lst-0128-book.cpp:

int func();                        // liefert einen int zurück
std::string func();                // eine Zeichenkette aus der Standardbibliothek
void func();                       // kein Rückgabewert
std::pair<int,std::string> func(); // zusammengesetzter Typ aus der Stdlib
vector<int> func();                // liefert einen neuen Container zurück
vector<int>& func();               // Verweis auf anderen Container
const vector<int>& func();         // ebenso, aber Sie können ihn nicht verändern

Listing 7.3: Parameter werden zunächst als Wert übergeben.

Book listing lst-0129-book.cpp:

// https://godbolt.org/z/8zcvMdM3b 
#include <iostream>

void print_val8(int n) {            // Parameter als Wert
    std::cout << n << " ";
    n = 8;                          // setzt Parameter auf 8
    std::cout << n << "\n";
}

int main() {
    int x = 5;
    print_val8(x);                  // x als Wert: druckt 5, dann 8
    std::cout << x << "\n";         // x ist unverändert 5
    print_val8(42);                 // 42 als Wert: druckt 42, dann 8
}

Godbolt Listing lst-0129-godb.cpp, https://godbolt.org/z/8zcvMdM3b:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8zcvMdM3b 
#include <iostream>

void print_val8(int n) {            // Parameter als Wert
    std::cout << n << " ";
    n = 8;                          // setzt Parameter auf 8
    std::cout << n << "\n";
}

int main() {
    int x = 5;
    print_val8(x);                  // x als Wert: druckt 5, dann 8
    std::cout << x << "\n";         // x ist unverändert 5
    print_val8(42);                 // 42 als Wert: druckt 42, dann 8
}

Listing 7.4: Als Referenzparameter fügen Sie ein »&« hinzu.

Book listing lst-0130-book.cpp:

// https://godbolt.org/z/63dTshz3Y 
#include <iostream>
void print_ref8(int& n) {           // Parameter als Referenz
    std::cout << n << " ";
    n = 8;                          // setzt Parameter auf 8
    std::cout << n << "\n";
}
int main() {
    int x = 5;
    print_ref8(x);                  // x als Referenz: druckt 5, dann 8
    std::cout << x << "\n";         // x ist nun 8
}

Godbolt Listing lst-0130-godb.cpp, https://godbolt.org/z/63dTshz3Y:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/63dTshz3Y 
#include <iostream>
void print_ref8(int& n) {           // Parameter als Referenz
    std::cout << n << " ";
    n = 8;                          // setzt Parameter auf 8
    std::cout << n << "\n";
}
int main() {
    int x = 5;
    print_ref8(x);                  // x als Referenz: druckt 5, dann 8
    std::cout << x << "\n";         // x ist nun 8
}

Listing 7.5: Konstante Referenzen als Parameter können Sie für jeden Aufruf verwenden.

Book listing lst-0131-book.cpp:

// https://godbolt.org/z/dcKnx3Pno 
#include <iostream>
void print_cref(const int& n) {     // Parameter als konstante Referenz
    std::cout << n << " ";
}

int main() {
    int x = 5;
    print_cref(x);                  // Aufruf mit einer Variablen
    print_cref(42);                 // Aufruf mit einem konstanten Literal
}

Godbolt Listing lst-0131-godb.cpp, https://godbolt.org/z/dcKnx3Pno:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dcKnx3Pno 
#include <iostream>
void print_cref(const int& n) {     // Parameter als konstante Referenz
    std::cout << n << " ";
}

int main() {
    int x = 5;
    print_cref(x);                  // Aufruf mit einer Variablen
    print_cref(42);                 // Aufruf mit einem konstanten Literal
}

GodboltId:fTvT5sKqY

Book listing lst-0133-book.cpp:

// https://godbolt.org/z/fTvT5sKqY 
#include <iostream>
void verdopple(double &zahl) {     // Ausgabeparameter als veränderbare Referenz
    zahl *= 2.0;
}

int main() {
    double zahl = 7.25;
    verdopple(zahl);
    std::cout << zahl << "\n";     // nun 14.5
}

Godbolt Listing lst-0133-godb.cpp, https://godbolt.org/z/fTvT5sKqY:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fTvT5sKqY 
#include <iostream>
void verdopple(double &zahl) {     // Ausgabeparameter als veränderbare Referenz
    zahl *= 2.0;
}

int main() {
    double zahl = 7.25;
    verdopple(zahl);
    std::cout << zahl << "\n";     // nun 14.5
}

GodboltId:caExoc36Y

Book listing lst-0134-book.cpp:

// https://godbolt.org/z/caExoc36Y 
#include <iostream>
double verdopple(double zahl) {    // Wertparameter und Rückgabewert
    return zahl * 2.0;
}
int main() {
    double zahl = 7.25;
    zahl = verdopple(zahl);        // Änderung ausgedrückt durch Rückgabewert
    std::cout << zahl << "\n";     // auch 14.5
}

Godbolt Listing lst-0134-godb.cpp, https://godbolt.org/z/caExoc36Y:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/caExoc36Y 
#include <iostream>
double verdopple(double zahl) {    // Wertparameter und Rückgabewert
    return zahl * 2.0;
}
int main() {
    double zahl = 7.25;
    zahl = verdopple(zahl);        // Änderung ausgedrückt durch Rückgabewert
    std::cout << zahl << "\n";     // auch 14.5
}

Listing 7.6: Verschiedene Definitionen von Funktionen

Book listing lst-0135-book.cpp:

std::vector<int> prims = {2};        // globale Variable
bool testeObPrim(int n) {            // eigene Funktion
    for(int teil : prims) {          // Zugriff auf globale Variable
        if(teil*teil > n)            // Zugriff auf Parameter
            return true;
        if(n%teil==0)
            return false;
    }
    return true;
}
void berechnePrimsBis(int bis) {     // noch eine eigene Funktion
    for(int n=3; n<bis; n=n+2) {
        if(testeObPrim(n)) {         // eigene Funktion verwenden
            prims.push_back(n);
        }
    }
}

Listing 7.7: Eine Vorwärtsdeklaration ohne Funktionskörper

Book listing lst-0136-book.cpp:

// … Auszug …
bool testeObPrim(int n);           // Deklaration der später definierten Funktion
void berechnePrimsBis(int bis) {
    for(int n=3; n<bis; n=n+2) {
        if(testeObPrim(n)) {       // Verwendung der später definierten Funktion
            prims.push_back(n);
        }
    }
}
bool testeObPrim(int n) {          // Definition erst nach der Verwendung
    // … wie zuvor …
}

Listing 7.8: Hier finden einige Umwandlungen statt. Die Umwandlungen können auf Ihrem System anders aussehen.

Book listing lst-0138-book.cpp:

// https://godbolt.org/z/6hWvqhY7W 
#include <iostream>
#include <format>
void prints(short s, int i, float f, double d) {
  std::cout << std::format("short: {} int: {} float: {:.2f} double: {:.2f}\n",
    s, i, f, d);
}
int main() {
  int mill = 1000*1000;                // 1 Million
  prints(mill, mill, mill, mill);      // short läuft über
  // Ausgabe: short: 16960 int: 1000000 float: 1000000.00 double: 1000000.00
  long bill = 1000L*1000L*1000L*1000L; // 1 Billion
  prints(bill, bill, bill, bill);      // sogar int läuft über, float wird ungenau
  // Ausgabe: short: 4096 int: –727379968 
  // float: 999999995904.00 double: 1000000000000.00
  float drei = 3.75f;
  prints(drei, drei, drei, drei);     // Nachkommastellen gehen verloren
  // Ausgabe: short: 3 int: 3 float: 3.75 double: 3.75
}

Godbolt Listing lst-0138-godb.cpp, https://godbolt.org/z/6hWvqhY7W:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6hWvqhY7W 
#include <iostream>
#include <format>
void prints(short s, int i, float f, double d) {
  std::cout << std::format("short: {} int: {} float: {:.2f} double: {:.2f}\n",
    s, i, f, d);
}
int main() {
  int mill = 1000*1000;                // 1 Million
  prints(mill, mill, mill, mill);      // short läuft über
  // Ausgabe: short: 16960 int: 1000000 float: 1000000.00 double: 1000000.00
  long bill = 1000L*1000L*1000L*1000L; // 1 Billion
  prints(bill, bill, bill, bill);      // sogar int läuft über, float wird ungenau
  // Ausgabe: short: 4096 int: –727379968 
  // float: 999999995904.00 double: 1000000000000.00
  float drei = 3.75f;
  prints(drei, drei, drei, drei);     // Nachkommastellen gehen verloren
  // Ausgabe: short: 3 int: 3 float: 3.75 double: 3.75
}

Listing 7.9: Die Funktionen »print« und »add« wurden für mehrere Typen überladen.

Book listing lst-0140-book.cpp:

// https://godbolt.org/z/9YcPraT15 
#include <iostream>
void print(int wert) { std::cout << "int-Wert: " << wert << "\n"; }
void print(double wert) { std::cout << "double-Wert: " << wert << "\n"; }
void print(int w1, double w2) { std::cout << "Werte: "<<w1<<", "<<w2<<"\n"; }
int add(int n, int m) { return n + m; }
double add(double a, double b) { return a + b; }
int main() {
    print( add(3, 4) );        // add(int, int) und print(int)
    print( add(3.25f, 1.5f) ); // add(double, double) und print(double)
    print( 7, 3.25 );          // print(int, double)
}

Godbolt Listing lst-0140-godb.cpp, https://godbolt.org/z/9YcPraT15:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9YcPraT15 
#include <iostream>
void print(int wert) { std::cout << "int-Wert: " << wert << "\n"; }
void print(double wert) { std::cout << "double-Wert: " << wert << "\n"; }
void print(int w1, double w2) { std::cout << "Werte: "<<w1<<", "<<w2<<"\n"; }
int add(int n, int m) { return n + m; }
double add(double a, double b) { return a + b; }
int main() {
    print( add(3, 4) );        // add(int, int) und print(int)
    print( add(3.25f, 1.5f) ); // add(double, double) und print(double)
    print( 7, 3.25 );          // print(int, double)
}

GodboltId:58cTfvYhe

Book listing lst-0143-book.cpp:

// https://godbolt.org/z/58cTfvYhe 
int zwei() { return 2; }      //             (ERR)  einmal int als Rückgabetyp…
double zwei() { return 2.0; } //             (ERR)  … und einmal double
int main() {
    int x = zwei();
    double y = zwei();
}

Godbolt Listing lst-0143-godb.cpp, https://godbolt.org/z/58cTfvYhe:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/58cTfvYhe 
int zwei() { return 2; }      //             (ERR)  einmal int als Rückgabetyp…
double zwei() { return 2.0; } //             (ERR)  … und einmal double
int main() {
    int x = zwei();
    double y = zwei();
}

GodboltId:evGqG1oqa

Book listing lst-0144-book.cpp:

// https://godbolt.org/z/evGqG1oqa 
int verdopple(int a) { return a * 2; }
double verdopple(double a) { return a * 2.0; }
int main() {
    int x = verdopple(7);
    double y = verdopple(7.0);
}

Godbolt Listing lst-0144-godb.cpp, https://godbolt.org/z/evGqG1oqa:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/evGqG1oqa 
int verdopple(int a) { return a * 2; }
double verdopple(double a) { return a * 2.0; }
int main() {
    int x = verdopple(7);
    double y = verdopple(7.0);
}

Listing 7.10: Defaultparameter wirken wie mehrere Überladungen.

Book listing lst-0147-book.cpp:

// https://godbolt.org/z/fjc37rvEr 
int add(int n=0, int m=0, int o=0, int p=0, int q=0) {
    return n+m+o+p+q;
}
int main() {
    std::cout << add(1,2,3,4,5) << "\n";
    std::cout << add(1,2,3,4) << "\n"; // wie add(1,2,3,4,0)
    std::cout << add(1,2,3) << "\n";   // wie add(1,2,3,0,0)
    std::cout << add(1,2) << "\n";     // wie add(1,2,0,0,0)
    std::cout << add(1) << "\n";       // wie add(1,0,0,0,0)
    std::cout << add() << "\n";        // wie add(0,0,0,0,0)
}

Godbolt Listing lst-0147-godb.cpp, https://godbolt.org/z/fjc37rvEr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fjc37rvEr 
int add(int n=0, int m=0, int o=0, int p=0, int q=0) {
    return n+m+o+p+q;
}
int main() {
    std::cout << add(1,2,3,4,5) << "\n";
    std::cout << add(1,2,3,4) << "\n"; // wie add(1,2,3,4,0)
    std::cout << add(1,2,3) << "\n";   // wie add(1,2,3,0,0)
    std::cout << add(1,2) << "\n";     // wie add(1,2,0,0,0)
    std::cout << add(1) << "\n";       // wie add(1,0,0,0,0)
    std::cout << add() << "\n";        // wie add(0,0,0,0,0)
}

Listing 7.11: Alternative Syntax für Funktionsdeklarationen mit nachgestelltem Rückgabetyp

Book listing lst-0152-book.cpp:

auto func() -> int;
auto func() -> std::string;
auto func() -> void;
auto func() -> std::pair<int,std::string>;
auto func() -> vector<int>;
auto func() -> vector<int>&;
auto func() -> const vector<int>&;

Listing 7.12: Seit C++14 können Sie den Rückgabetyp durch den Compiler ermitteln lassen.

Book listing lst-0153-book.cpp:

// https://godbolt.org/z/6d5fxn9ed 
auto maxOf2(int a, int b) {
    return a<b ? b : a;   // ein return: der Compiler ermittelt int
}
auto minOf3(int a, int b, int c) {
     if(a<b) return a<c ? a : c;
     else return b<c ? b : c;
}
auto medianOf3(int a, int b, int c) {
     // komplexer, aber kein Problem für den Compiler
     return minOf3(maxOf2(a,b), maxOf2(b,c), maxOf2(a,c));
}

Godbolt Listing lst-0153-godb.cpp, https://godbolt.org/z/6d5fxn9ed:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6d5fxn9ed 
auto maxOf2(int a, int b) {
    return a<b ? b : a;   // ein return: der Compiler ermittelt int
}
auto minOf3(int a, int b, int c) {
     if(a<b) return a<c ? a : c;
     else return b<c ? b : c;
}
auto medianOf3(int a, int b, int c) {
     // komplexer, aber kein Problem für den Compiler
     return minOf3(maxOf2(a,b), maxOf2(b,c), maxOf2(a,c));
}

GodboltId:dMvqG85fr

Book listing lst-0157-book.cpp:

// https://godbolt.org/z/dMvqG85fr 
double add(double a, double b) { return a + b; }
double add(int, int) = delete;   // add(3,4) verbieten

Godbolt Listing lst-0157-godb.cpp, https://godbolt.org/z/dMvqG85fr:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dMvqG85fr 
double add(double a, double b) { return a + b; }
double add(int, int) = delete;   // add(3,4) verbieten

GodboltId:8Gdso36zf

Book listing lst-0158-book.cpp:

// https://godbolt.org/z/8Gdso36zf 
class Widget : public Base {
    explicit Widget(int);     // keine automatische Konvertierung von int
    ~Widget();                // Destruktor mit ~ vor dem Namen
    virtual void update();    // vorangestelltes virtual
    void calc1() override;    // nachgestelltes override
    void calc2() final;       // nachgestelltes final
    void draw() const;        // nachgestelltes const
    virtual void paint() = 0; // abstrakte Methode
};

Godbolt Listing lst-0158-godb.cpp, https://godbolt.org/z/8Gdso36zf:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8Gdso36zf 
class Widget : public Base {
    explicit Widget(int);     // keine automatische Konvertierung von int
    ~Widget();                // Destruktor mit ~ vor dem Namen
    virtual void update();    // vorangestelltes virtual
    void calc1() override;    // nachgestelltes override
    void calc2() final;       // nachgestelltes final
    void draw() const;        // nachgestelltes const
    virtual void paint() = 0; // abstrakte Methode
};

Listing 8.1: Berechnet alle Primzahlen in einem von Benutzern bestimmten Bereich

Book listing lst-0159-book.cpp:

// https://godbolt.org/z/3hf7h67Pe 
#include <iostream>                   // cout
#include <vector>                     // Container vector
#include <string>                     // stoi
int eingabeBis(int argc, const char* argv[]) {
    /* Zahl ermitteln */
    int bis = 0;                      // neue Variable einführen
    if(argc<=1) {                     // if-Anweisung mit then- und else-Block
        std::cout << "Bis wohin wollen Sie Primzahlen berechnen? ";
        if(!(std::cin >> bis)) {      // Prüfen des Rückgabewerts
            return -1;                // Fehler bei Benutzereingabe
        }
    } else {                          // else-Teil der if-Anweisung
        bis = std::stoi(argv[1]);
    }
    return bis;                       // Eingabe zurückliefern
}
std::vector prims{2};                 // neuer vector<int> mit Initialisierung
bool testeObPrim(int n) {
    /* prims muss aufsteigend sortiert sein */
    for(int teil : prims) {           // bereichsbasierte for-Schleife
        if(teil*teil > n)             // zu groß, um überhaupt Teiler zu sein?
            return true;              // … dann innere Schleife vorzeitig beenden
        if(n%teil==0)                 // ist Teiler?
            return false;             // … dann raus
    }
    return true;                      // kein Teiler gefunden
}
void berechnePrimsBis(int bis) {
    /* Prims-Berechnung */
    /* vector muss an dieser Stelle {2} enthalten */
    for(int n=3; n<bis; n=n+2) {      // Standard-for-Schleife
        if(testeObPrim(n)) {
            prims.push_back(n);       // ist prim – merken als Teiler und Ergebnis
        }
    }
}
void ausgabePrims() {
    for(int prim : prims) {           // bereichsbasiert, über alle Elemente
        std::cout << prim << " ";
    }
    std::cout << "\n";
}
int main(int argc, const char* argv[]) {
    int bis = eingabeBis(argc, argv); // deklariert Variable
    if(bis < 2) { return 1; }         // Raus aus main mit Nicht-okay-Wert.
    berechnePrimsBis(bis);
    ausgabePrims();
    return 0;
}

Godbolt Listing lst-0159-godb.cpp, https://godbolt.org/z/3hf7h67Pe:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3hf7h67Pe 
#include <iostream>                   // cout
#include <vector>                     // Container vector
#include <string>                     // stoi
int eingabeBis(int argc, const char* argv[]) {
    /* Zahl ermitteln */
    int bis = 0;                      // neue Variable einführen
    if(argc<=1) {                     // if-Anweisung mit then- und else-Block
        std::cout << "Bis wohin wollen Sie Primzahlen berechnen? ";
        if(!(std::cin >> bis)) {      // Prüfen des Rückgabewerts
            return -1;                // Fehler bei Benutzereingabe
        }
    } else {                          // else-Teil der if-Anweisung
        bis = std::stoi(argv[1]);
    }
    return bis;                       // Eingabe zurückliefern
}
std::vector prims{2};                 // neuer vector<int> mit Initialisierung
bool testeObPrim(int n) {
    /* prims muss aufsteigend sortiert sein */
    for(int teil : prims) {           // bereichsbasierte for-Schleife
        if(teil*teil > n)             // zu groß, um überhaupt Teiler zu sein?
            return true;              // … dann innere Schleife vorzeitig beenden
        if(n%teil==0)                 // ist Teiler?
            return false;             // … dann raus
    }
    return true;                      // kein Teiler gefunden
}
void berechnePrimsBis(int bis) {
    /* Prims-Berechnung */
    /* vector muss an dieser Stelle {2} enthalten */
    for(int n=3; n<bis; n=n+2) {      // Standard-for-Schleife
        if(testeObPrim(n)) {
            prims.push_back(n);       // ist prim – merken als Teiler und Ergebnis
        }
    }
}
void ausgabePrims() {
    for(int prim : prims) {           // bereichsbasiert, über alle Elemente
        std::cout << prim << " ";
    }
    std::cout << "\n";
}
int main(int argc, const char* argv[]) {
    int bis = eingabeBis(argc, argv); // deklariert Variable
    if(bis < 2) { return 1; }         // Raus aus main mit Nicht-okay-Wert.
    berechnePrimsBis(bis);
    ausgabePrims();
    return 0;
}

Listing 8.2: Dieses »for« bezieht sich auf nur eine Anweisung.

Book listing lst-0160-book.cpp:

for(int prim : prims)               // for gefolgt von einer Anweisung
    std::cout << prim << " ";
std::cout << "\n";                  // nicht mehr Teil von for

Listing 8.3: Ein Anweisungsblock wird in { und } eingeschlossen.

Book listing lst-0161-book.cpp:

for(int prim : prims) {             // Beginn des Blocks
    std::cout << prim;
    std::cout << " ";
}                                   // Ende des Blocks
std::cout << "\n";

Listing 8.4: Wo Anweisungen erlaubt sind, können Sie auch einen Block erstellen.

Book listing lst-0162-book.cpp:

if(zahl > 50) {                     // äußerer Block
    {                               // 1. innerer Block
        int ergebnis = zahl*zahl;
        std::cout << "Quadrat: " << ergebnis << std::endl;
    }
    {                               // 2. innerer Block
        int ergebnis = zahl+zahl;
        std::cout << "Verdoppelt: " << ergebnis << std::endl;
    }
}

Listing 8.5: Zweimal »ergebnis« als neue Variable in einem Block geht nicht.

Book listing lst-0163-book.cpp:

if(zahl > 50) {
    int ergebnis = zahl*zahl;           // Definition von ergebnis
    std::cout << "Quadrat: " << ergebnis << std::endl;
    int ergebnis = zahl+zahl;           //             (ERR)  Fehler: ergebnis wurde schon definiert
    std::cout << "Verdoppelt: " << ergebnis << std::endl;
}

Listing 8.6: Sehr viele Variablen sind auch nicht gut.

Book listing lst-0164-book.cpp:

if(zahl > 50) {
    int ergebnis1 = zahl*zahl;          // ein Ergebnis
    std::cout << "Quadrat: " << ergebnis << std::endl;
    int ergebnis2 = zahl+zahl;          // noch ein Ergebnis
    std::cout << "Verdoppelt: " << ergebnis << std::endl;
    int ergebnis3 = zahl+zahl+zahl;     // und noch ein Ergebnis
    // … viele Zeilen Code dazwischen …
    // und hier?
    // … noch mehr Programmzeilen …
}

Listing 8.7: Leere Anweisungen, wohin das Auge schaut

Book listing lst-0165-book.cpp:

int main() {  ;;;              // 3 leere Anweisungen
    int zahl = 12 ; ;          // 1 leere Anweisung
    ; int q = zahl*zahl ;      // 1 leere Anweisung
    if(q>50) {
        q = q - 50;
    } ;                        // 1 leere Anweisung
    std::cout << q << std::endl;
}

Listing 8.8: Mit auto können Sie auch mehrere Variablen gleichzeitig initialisieren.

Book listing lst-0172-book.cpp:

// https://godbolt.org/z/G7P4ErTE1 
#include <iostream>
#include <tuple> // make_tuple
auto mkTpl() {
    return std::make_tuple(2, 'b', 3.14); // tuple<int,char,double>
}
struct Point {
    int x, y;
};
int main() {
    // Strukuriertes Binden eines C-Arrays
    int ungerade[5] = { 1,3,7,9,11 };
    auto [ eins, zwei, drei, vier, fuenf ] = ungerade;
    // Strukuriertes Binden eines Tupels
    auto [ two, bee, pi ] = mkTpl();
    // Strukuriertes Binden einer Struktur
    Point p0{  10, 15 };
    auto [ the_x, the_y ] = p0;
}

Godbolt Listing lst-0172-godb.cpp, https://godbolt.org/z/G7P4ErTE1:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/G7P4ErTE1 
#include <iostream>
#include <tuple> // make_tuple
auto mkTpl() {
    return std::make_tuple(2, 'b', 3.14); // tuple<int,char,double>
}
struct Point {
    int x, y;
};
int main() {
    // Strukuriertes Binden eines C-Arrays
    int ungerade[5] = { 1,3,7,9,11 };
    auto [ eins, zwei, drei, vier, fuenf ] = ungerade;
    // Strukuriertes Binden eines Tupels
    auto [ two, bee, pi ] = mkTpl();
    // Strukuriertes Binden einer Struktur
    Point p0{  10, 15 };
    auto [ the_x, the_y ] = p0;
}

GodboltId:YTTE96rfc

Book listing lst-0173-book.cpp:

// https://godbolt.org/z/YTTE96rfc 
int main() {
    int ungerade[5] = { 1,3,7,9,11 };
    auto &[ eins, zwei, drei, vier, fuenf ] = ungerade;
    auto &[ two, bee, pi ] = mkTpl(); //             (ERR)  kein &-Binden an Tempwerte
    Point p0{  10, 15 };
    auto &[ the_x, the_y ] = p0;
}

Godbolt Listing lst-0173-godb.cpp, https://godbolt.org/z/YTTE96rfc:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YTTE96rfc 
int main() {
    int ungerade[5] = { 1,3,7,9,11 };
    auto &[ eins, zwei, drei, vier, fuenf ] = ungerade;
    auto &[ two, bee, pi ] = mkTpl(); //             (ERR)  kein &-Binden an Tempwerte
    Point p0{  10, 15 };
    auto &[ the_x, the_y ] = p0;
}

Listing 8.9: Dies sind alles Ausdrücke, die als Anweisung eingesetzt werden.

Book listing lst-0174-book.cpp:

bis = 99;                     // eine Zuweisung ist ein Ausdruck
bis = bis * 2 + 1;            // Zuweisung mit einer Berechnung verbinden
berechnePrimsBis(bis);        // ein Funktionsaufruf ist ein Ausdruck
std::cout << "Friedrich III"; // der Ausgabeoperator

Listing 8.10: Diese if-Anweisungen enthalten Initialisierer.

Book listing lst-0180-book.cpp:

// https://godbolt.org/z/d6PscKx4M 
#include <map>
#include <string>
#include <algorithm> // any_of
#include <iostream>  // cerr
std::map<int, std::string> m;
int main() {
   if(auto it = m.find(10); it != m.end()) { return it->second.size(); }
   if(char buf[10]={0}; std::fgets(buf, 10, stdin)) { m[0] += buf; }
   std::string s;
   if(auto keywords = {"if", "for", "while"};
       std::any_of(keywords.begin(), keywords.end(),
       [&s](const char* kw) { return s == kw; })) {
           std::cerr << "Fehler\n";
   }
}

Godbolt Listing lst-0180-godb.cpp, https://godbolt.org/z/d6PscKx4M:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/d6PscKx4M 
#include <map>
#include <string>
#include <algorithm> // any_of
#include <iostream>  // cerr
std::map<int, std::string> m;
int main() {
   if(auto it = m.find(10); it != m.end()) { return it->second.size(); }
   if(char buf[10]={0}; std::fgets(buf, 10, stdin)) { m[0] += buf; }
   std::string s;
   if(auto keywords = {"if", "for", "while"};
       std::any_of(keywords.begin(), keywords.end(),
       [&s](const char* kw) { return s == kw; })) {
           std::cerr << "Fehler\n";
   }
}

Listing 8.11: Der Compiler kann die Bedingung zur Compilezeit berechnen.

Book listing lst-0181-book.cpp:

// https://godbolt.org/z/Ycse4EWav 
#include <iostream> // cout

template<typename T>
void speicher(T x) {
    if constexpr(sizeof(T) > 4) {
       std::cout << "Braucht viel Speicher: " << x << " \n";
    }
}

constexpr auto DEBUG = true;
int main() {
    if constexpr(DEBUG) {
        std::cout << "Debug ist an.\n";
    }
    speicher<long long>(44LL);
}

Godbolt Listing lst-0181-godb.cpp, https://godbolt.org/z/Ycse4EWav:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ycse4EWav 
#include <iostream> // cout

template<typename T>
void speicher(T x) {
    if constexpr(sizeof(T) > 4) {
       std::cout << "Braucht viel Speicher: " << x << " \n";
    }
}

constexpr auto DEBUG = true;
int main() {
    if constexpr(DEBUG) {
        std::cout << "Debug ist an.\n";
    }
    speicher<long long>(44LL);
}

Listing 8.12: Die Schleife wird 100-mal durchlaufen.

Book listing lst-0182-book.cpp:

// https://godbolt.org/z/Gc53z6K1W 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    int zahl = 1;
    while(zahl <= 100)       // Bedingung
    {                        // Block, der wiederholt ausgeführt wird
        summe += zahl;       // fürs Ergebnis
        zahl += 1;           // nächste Zahl
    }                        // Ende des wiederholten Blocks
    std::cout << summe << std::endl;
}

Godbolt Listing lst-0182-godb.cpp, https://godbolt.org/z/Gc53z6K1W:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gc53z6K1W 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    int zahl = 1;
    while(zahl <= 100)       // Bedingung
    {                        // Block, der wiederholt ausgeführt wird
        summe += zahl;       // fürs Ergebnis
        zahl += 1;           // nächste Zahl
    }                        // Ende des wiederholten Blocks
    std::cout << summe << std::endl;
}

Listing 8.13: Der Rumpf einer »do-while«-Schleife wird mindestens einmal ausgeführt.

Book listing lst-0184-book.cpp:

// https://godbolt.org/z/6hh5KhExM 
#include <iostream>                 // cin
#include <string>
int main() {
    std::string line;
    do {                            // mindestens einmal getline ausführen
       std::getline(std::cin, line);
       if(!std::cin) break;         // Fehler oder Dateiende
    } while(line != "quit");        // Ende bei bestimmter Eingabe
}

Godbolt Listing lst-0184-godb.cpp, https://godbolt.org/z/6hh5KhExM:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6hh5KhExM 
#include <iostream>                 // cin
#include <string>
int main() {
    std::string line;
    do {                            // mindestens einmal getline ausführen
       std::getline(std::cin, line);
       if(!std::cin) break;         // Fehler oder Dateiende
    } while(line != "quit");        // Ende bei bestimmter Eingabe
}

Listing 8.14: Summe mit einer »for«-Schleife

Book listing lst-0185-book.cpp:

// https://godbolt.org/z/7foYcMMaz 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    for(int zahl=1; zahl <= 100; zahl+=1) {   // kompakt
        summe += zahl;                        // fürs Ergebnis
    }
    std::cout << summe << std::endl;
}

Godbolt Listing lst-0185-godb.cpp, https://godbolt.org/z/7foYcMMaz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7foYcMMaz 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    for(int zahl=1; zahl <= 100; zahl+=1) {   // kompakt
        summe += zahl;                        // fürs Ergebnis
    }
    std::cout << summe << std::endl;
}

Listing 8.15: »for«-Schleife mit leerem Initialisierungsteil

Book listing lst-0186-book.cpp:

// https://godbolt.org/z/185ha3q3f 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    int zahl = 1;                         // Initialisierung vor der Schleife
    for(  ; zahl <= 100; zahl=zahl+1) {   // leere Initialisierung
        summe = summe + zahl;
    }
    std::cout << zahl << std::endl;       // zahl gibt es nun noch außerhalb
}

Godbolt Listing lst-0186-godb.cpp, https://godbolt.org/z/185ha3q3f:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/185ha3q3f 
#include <iostream>
int main() {
    /* Summiere 1 bis 100 auf */
    int summe = 0;
    int zahl = 1;                         // Initialisierung vor der Schleife
    for(  ; zahl <= 100; zahl=zahl+1) {   // leere Initialisierung
        summe = summe + zahl;
    }
    std::cout << zahl << std::endl;       // zahl gibt es nun noch außerhalb
}

Listing 8.16: Schleifen ohne Bedingung müssen irgendwie anders beendet werden.

Book listing lst-0187-book.cpp:

int main() {
    for( ; ; ) {  // kein Init, keine Bedingung, kein Update – also für immer
        /* ... Benutzereingabe */
        /* ... falls Benutzer Quit wählt, Programmende */
        /* ... ansonsten, Berechnung und Ausgabe */
    }
}

Listing 8.17: Die bereichsbasierte »for«-Schleife erkennen Sie an dem Doppelpunkt.

Book listing lst-0188-book.cpp:

// Auszug
std::vector<int> prims{2};   // vector ist ein Container, bereit für Ranged For
void testeObPrim(int n) {
    /* prims muss aufsteigend sortiert sein */
    for(int teil : prims) {   // bereichsbasierte for-Schleife
        if(teil*teil > n)
            return true;
        if(n%teil==0)
            return false;
    }
    return true;
}
// …

void ausgabePrims() {
    for(int i=1; int prim : prims) {   // bereichsbasierte for-Schleife
        std::cout << i++ << ". Primzahl: " <<prim << " ";
    }
    std::cout << "\n";
}
// …

Listing 8.18: Jeder »case« deckt einen Fall ab, und nirgendwo wurde das »break« vergessen.

Book listing lst-0189-book.cpp:

// https://godbolt.org/z/5oe38obPr 
#include <string>
#include <vector>
#include <iostream>       // cout

void rechner(std::ostream& out, std::string input) {
    std::vector<int> stapel {};
    for(char c : input) {
        if(c>='0' && c<='9') {
            stapel.push_back( c-'0' ); // Zahlenwert des Zeichens
            continue;     // nächste Schleifeniteration
        }
        int top = 0;
        int second = 0;
        switch(c) {       // Bedingung auf zeichen
        case '+':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second + top);
            break;
        case '-':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second - top);
            break;
        case '*':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second * top);
            break;
        case '=':
            for(int elem : stapel) { out << elem; }
            out << "\n";
            break;
        case ' ':
            break;
        default:
            out << "\n'" << c << "' verstehe ich nicht.\n";
        } /* switch */
    } /* for c */
}
int main(int argc, const char* argv[]) {
    if(argc > 1) {
        rechner(std::cout, argv[1]);
    } else {
        // 3 + 4 * 5 + 6 mit Punkt- vor Strichrechnung ergibt 29
        rechner(std::cout, "345*+6+=");
    }
}

Godbolt Listing lst-0189-godb.cpp, https://godbolt.org/z/5oe38obPr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5oe38obPr 
#include <string>
#include <vector>
#include <iostream>       // cout

void rechner(std::ostream& out, std::string input) {
    std::vector<int> stapel {};
    for(char c : input) {
        if(c>='0' && c<='9') {
            stapel.push_back( c-'0' ); // Zahlenwert des Zeichens
            continue;     // nächste Schleifeniteration
        }
        int top = 0;
        int second = 0;
        switch(c) {       // Bedingung auf zeichen
        case '+':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second + top);
            break;
        case '-':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second - top);
            break;
        case '*':
            top = stapel.back(); stapel.pop_back();
            second = stapel.back(); stapel.pop_back();
            stapel.push_back(second * top);
            break;
        case '=':
            for(int elem : stapel) { out << elem; }
            out << "\n";
            break;
        case ' ':
            break;
        default:
            out << "\n'" << c << "' verstehe ich nicht.\n";
        } /* switch */
    } /* for c */
}
int main(int argc, const char* argv[]) {
    if(argc > 1) {
        rechner(std::cout, argv[1]);
    } else {
        // 3 + 4 * 5 + 6 mit Punkt- vor Strichrechnung ergibt 29
        rechner(std::cout, "345*+6+=");
    }
}

Listing 8.19: Sehr selten gibt es »case«-Blöcke ohne »break«, noch seltener sinnvolle.

Book listing lst-0190-book.cpp:

// https://godbolt.org/z/jaMTcshEf 
#include <iostream>
#include <string>

using std::string; using std::cout;

void rateMonat(unsigned welchenTagHabenwirHeute) {
    switch(welchenTagHabenwirHeute) {
    /* fehlende break-Anweisungen: Fall-through beabsichtigt */
    default:
        if(welchenTagHabenwirHeute>31) {
            cout << "Sie schummeln";
            break;
        }
    case 28:
    case 29:
        cout << "Feb ";
    case 30:
        cout << "Apr Jun Sep Nov ";
    case 31:
        cout << "Jan Mar Mai Jul Aug Okt Dez ";
    }

    cout << ".\n";
}
int main() {
    rateMonat(31); // wenn wir heute den 31. hätten?
    // Ausgabe: Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(30); // wenn es der 30. wäre?
    // Ausgabe: Apr Jun Sep Nov Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(4);
    // Ausgabe: Feb Apr Jun Sep Nov Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(77);
    // Ausgabe: Sie schummeln.
}

Godbolt Listing lst-0190-godb.cpp, https://godbolt.org/z/jaMTcshEf:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jaMTcshEf 
#include <iostream>
#include <string>

using std::string; using std::cout;

void rateMonat(unsigned welchenTagHabenwirHeute) {
    switch(welchenTagHabenwirHeute) {
    /* fehlende break-Anweisungen: Fall-through beabsichtigt */
    default:
        if(welchenTagHabenwirHeute>31) {
            cout << "Sie schummeln";
            break;
        }
    case 28:
    case 29:
        cout << "Feb ";
    case 30:
        cout << "Apr Jun Sep Nov ";
    case 31:
        cout << "Jan Mar Mai Jul Aug Okt Dez ";
    }

    cout << ".\n";
}
int main() {
    rateMonat(31); // wenn wir heute den 31. hätten?
    // Ausgabe: Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(30); // wenn es der 30. wäre?
    // Ausgabe: Apr Jun Sep Nov Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(4);
    // Ausgabe: Feb Apr Jun Sep Nov Jan Mar Mai Jul Aug Okt Dez .
    rateMonat(77);
    // Ausgabe: Sie schummeln.
}

Listing 8.20: Mit break beenden Sie eine Schleife vorzeitig.

Book listing lst-0191-book.cpp:

// https://godbolt.org/z/75h9Y95vf 
#include <iostream>                // cout
int main() {
    for(int x=1; x<20; x+=1) {     // äußere for-Schleife
        for(int y=1; y<20; y+=1) { // innere for-Schleife
            int prod = x*y;
            if(prod>=100) {
                break;             // raus aus innerer y-Schleife
            }
            std::cout << prod << " ";
        } /* Ende for y */
        // Ziel von break
    } /* Ende for x */                // erste wirkliche Zeile nach break
    std::cout << "\n";
}

Godbolt Listing lst-0191-godb.cpp, https://godbolt.org/z/75h9Y95vf:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/75h9Y95vf 
#include <iostream>                // cout
int main() {
    for(int x=1; x<20; x+=1) {     // äußere for-Schleife
        for(int y=1; y<20; y+=1) { // innere for-Schleife
            int prod = x*y;
            if(prod>=100) {
                break;             // raus aus innerer y-Schleife
            }
            std::cout << prod << " ";
        } /* Ende for y */
        // Ziel von break
    } /* Ende for x */                // erste wirkliche Zeile nach break
    std::cout << "\n";
}

Listing 8.21: Mit »return« wird die aktuelle Funktion verlassen. Falls nötig, geben Sie einen Wert für die Rückgabe mit an.

Book listing lst-0192-book.cpp:

// https://godbolt.org/z/5ddxa9v1j 
#include <iostream>                      // cout
int min3(int x, int y, int z) {          // Funktion liefert einen int zurück
    if(x<y) {
        if(x<z) return x;
        else return z;
    } else if(y<z) {
        return y;
    }
    else return z;
}
void printMin(int x, int y, int z) {     // Funktion liefert nichts zurück
    if(x<0 || y<0 || z<0) {
        std::cout << "Bitte nur Zahlen groesser 0\n";
        return;
    }
    std::cout << min3(x,y,z) << "\n";
}                                        // hier steht kein return
int main() {
    printMin(3, -4, 8);
    printMin(6, 77, 4);
    return;                              // besonderes return in main
}

Godbolt Listing lst-0192-godb.cpp, https://godbolt.org/z/5ddxa9v1j:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5ddxa9v1j 
#include <iostream>                      // cout
int min3(int x, int y, int z) {          // Funktion liefert einen int zurück
    if(x<y) {
        if(x<z) return x;
        else return z;
    } else if(y<z) {
        return y;
    }
    else return z;
}
void printMin(int x, int y, int z) {     // Funktion liefert nichts zurück
    if(x<0 || y<0 || z<0) {
        std::cout << "Bitte nur Zahlen groesser 0\n";
        return;
    }
    std::cout << min3(x,y,z) << "\n";
}                                        // hier steht kein return
int main() {
    printMin(3, -4, 8);
    printMin(6, 77, 4);
    return;                              // besonderes return in main
}

Listing 8.22: Vermeiden Sie goto-Anweisungen.

Book listing lst-0193-book.cpp:

// https://godbolt.org/z/ohd5Pr8fb 
#include <iostream>
int main() {
    int idx = 4;
    goto mehr;                      // springe zu Label mehr
  drucke:                           // Label für die nächste Anweisung
    std::cout << idx << std::endl;
    idx = idx * 2;
  mehr:
    idx = idx + 3;
    if(idx < 20)
        goto drucke;                // goto kann auch in einem if stehen
  ende:                             // dies ist ein Label, wird aber nicht verwendet
    return 0;
}

Godbolt Listing lst-0193-godb.cpp, https://godbolt.org/z/ohd5Pr8fb:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ohd5Pr8fb 
#include <iostream>
int main() {
    int idx = 4;
    goto mehr;                      // springe zu Label mehr
  drucke:                           // Label für die nächste Anweisung
    std::cout << idx << std::endl;
    idx = idx * 2;
  mehr:
    idx = idx + 3;
    if(idx < 20)
        goto drucke;                // goto kann auch in einem if stehen
  ende:                             // dies ist ein Label, wird aber nicht verwendet
    return 0;
}

Listing 8.23: Eine Funktion weniger, aber ein Label und zwei »goto«-Anweisungen mehr.

Book listing lst-0194-book.cpp:

// https://godbolt.org/z/b361eeba3 
// #includes, prims, eingabeBis(), ausgabePrims() und main() wie zuvor 
std::vector<int> prims{2};
void berechnePrimsBis(int bis) {
    /* Prims-Berechnung */
    /* vector muss an dieser Stelle {2} enthalten */
    for(int n=3; n<bis; n=n+2) {
        for(int teil: prims) {
            if(teil*teil > n)
                goto prim;     // mit goto, weil ein break …
            if(n%teil==0)
                goto nichtPrim;// … über zwei Schleifen nicht geht.
        }
      prim: ;                  // Ziel des Sprungs vor push_back
        prims.push_back(n);    // n ist prim! Merken als Teiler und Ergebnis
      nichtPrim: ;             // Ziel des Sprungs hinter push_back
    }
}

Godbolt Listing lst-0194-godb.cpp, https://godbolt.org/z/b361eeba3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/b361eeba3 
// #includes, prims, eingabeBis(), ausgabePrims() und main() wie zuvor 
std::vector<int> prims{2};
void berechnePrimsBis(int bis) {
    /* Prims-Berechnung */
    /* vector muss an dieser Stelle {2} enthalten */
    for(int n=3; n<bis; n=n+2) {
        for(int teil: prims) {
            if(teil*teil > n)
                goto prim;     // mit goto, weil ein break …
            if(n%teil==0)
                goto nichtPrim;// … über zwei Schleifen nicht geht.
        }
      prim: ;                  // Ziel des Sprungs vor push_back
        prims.push_back(n);    // n ist prim! Merken als Teiler und Ergebnis
      nichtPrim: ;             // Ziel des Sprungs hinter push_back
    }
}

Listing 8.24: Als Ausblick hier Ihre erste Exception-Behandlung mit »try« und »catch«

Book listing lst-0195-book.cpp:

// https://godbolt.org/z/cjfG7bc33 
#include <iostream>
int main() {
    try {                                       // Beginn des try-Blocks
        for(int n=1; ; n=n*2) {
            if(n < 0) {
                throw "Es gab einen Ueberlauf";  // Fehler auslösen
            }
        }
    }                                            // Ende des try-Blocks
    catch(const char *fehler) {                  // falls dieser Fehler auftritt, …
      std::cout << "Fehler: " << fehler << "\n"; // … behandle ihn so
    }
}

Godbolt Listing lst-0195-godb.cpp, https://godbolt.org/z/cjfG7bc33:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cjfG7bc33 
#include <iostream>
int main() {
    try {                                       // Beginn des try-Blocks
        for(int n=1; ; n=n*2) {
            if(n < 0) {
                throw "Es gab einen Ueberlauf";  // Fehler auslösen
            }
        }
    }                                            // Ende des try-Blocks
    catch(const char *fehler) {                  // falls dieser Fehler auftritt, …
      std::cout << "Fehler: " << fehler << "\n"; // … behandle ihn so
    }
}

Listing 9.1: Typen von Ausdrücken sind wichtig, weil damit entschieden wird, wie es weitergeht.

Book listing lst-0196-book.cpp:

// https://godbolt.org/z/E1aGdox6q 
#include <iostream>           // cout
#include <string>
void drucke(int n) {          // Funktion drucke für Typ int
    std::cout << "Zahl:" << n << "\n";
}
void drucke(std::string s) {  // gleicher Name, anderer Typ
    std::cout << "Zeichenkette:" << s << "\n";
}
int main() {
    int zahl = 10;
    std::string name = "Bilbo";
    drucke(zahl);              // ruft drucke(int) auf, zahl ist int
    drucke(name);              // ruft drucke(string) auf, name ist string
    drucke(11 + 22);           // Ausdruck ist int
    drucke(name + " Baggins"); // Ausdruck ist string
}

Godbolt Listing lst-0196-godb.cpp, https://godbolt.org/z/E1aGdox6q:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/E1aGdox6q 
#include <iostream>           // cout
#include <string>
void drucke(int n) {          // Funktion drucke für Typ int
    std::cout << "Zahl:" << n << "\n";
}
void drucke(std::string s) {  // gleicher Name, anderer Typ
    std::cout << "Zeichenkette:" << s << "\n";
}
int main() {
    int zahl = 10;
    std::string name = "Bilbo";
    drucke(zahl);              // ruft drucke(int) auf, zahl ist int
    drucke(name);              // ruft drucke(string) auf, name ist string
    drucke(11 + 22);           // Ausdruck ist int
    drucke(name + " Baggins"); // Ausdruck ist string
}

GodboltId:EY5K6Wsr3

Book listing lst-0203-book.cpp:

// https://godbolt.org/z/EY5K6Wsr3 
std::vector<int> data(10);     // 10 mal 0 in einem vector
data.front() = 666;            // schreibt 666 an die vorderste Stelle

Godbolt Listing lst-0203-godb.cpp, https://godbolt.org/z/EY5K6Wsr3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EY5K6Wsr3 
std::vector<int> data(10);     // 10 mal 0 in einem vector
data.front() = 666;            // schreibt 666 an die vorderste Stelle

GodboltId:K9c913had

Book listing lst-0204-book.cpp:

// https://godbolt.org/z/K9c913had 
if(int result;  (result = read(buffer, 100)) != 0) {
    std::cerr << "Es trat Fehler Nummer "<< result << " auf.\n";
}

Godbolt Listing lst-0204-godb.cpp, https://godbolt.org/z/K9c913had:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/K9c913had 
if(int result;  (result = read(buffer, 100)) != 0) {
    std::cerr << "Es trat Fehler Nummer "<< result << " auf.\n";
}

Listing 10.1: Reagieren Sie auf viele Zustände mit Rückgabewerten unterschiedlicher Art.

Book listing lst-0210-book.cpp:

// https://godbolt.org/z/K37fMW8fE 
#include <iostream> // cout, cerr
#include <fstream>
#include <vector>
#include <string>
using std::vector; using std::string; using std::cout; using std::cerr;

int zaehleWoerter(const string& filename) { // Rückgabe kleiner 0 bei Fehler
    std::ifstream file{filename};
    if(!file) {     // Gab es einen Fehler beim Öffnen der Datei?
        cerr << "Fehler beim Oeffnen von " << filename << "\n";
        return -1;  // dem Aufrufer einen Fehler mittels besonderem Wert melden
    }
    int count = 0;
    string wort;
    while(!file.eof()) {    // noch nicht am Ende?
        file >> wort;
        ++count;
    }
    return count-1;         // –1: am EOF wurde noch ein Wort gelesen
}
bool process(const vector<string>& args) { // Rückgabe true bei alles okay
    if(args.size() == 0) {  // erwarten Parameter
        cerr << "Kommandozeilenargument fehlt\n";
        return false;       // mittels Rückgabe einen Fehler mitteilen
    } else {
        bool result = true; // fürs Endergebnis
        for(const string filename : args) {
            cout << filename << ": ";
            int count = zaehleWoerter(filename);
            if(count < 0) { // besondere Rückgabe zeigt Fehler an
                cout << "Fehler!\n";
                result = false;         // mindestens ein Fehler
            } else {
                cout << count << "\n";  // normales Ergebnis ausgeben
            }
        }
        return result;                  // Gesamtergebnis zurückgeben
    }
}

int main(int argc, const char* argv[]) {
    bool result = process(              // Rückgabewert enthält Fehlerindikator
        {argv+1, argv+argc} );          // const char*[] nach vector<string>
    if(result) {                        // Rückgabewert auswerten
        return 0;
    } else {
        cerr << "Es trat ein Fehler auf.\n";
        return 1;   // außen Fehler anzeigen
    }
}

Godbolt Listing lst-0210-godb.cpp, https://godbolt.org/z/K37fMW8fE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/K37fMW8fE 
#include <iostream> // cout, cerr
#include <fstream>
#include <vector>
#include <string>
using std::vector; using std::string; using std::cout; using std::cerr;

int zaehleWoerter(const string& filename) { // Rückgabe kleiner 0 bei Fehler
    std::ifstream file{filename};
    if(!file) {     // Gab es einen Fehler beim Öffnen der Datei?
        cerr << "Fehler beim Oeffnen von " << filename << "\n";
        return -1;  // dem Aufrufer einen Fehler mittels besonderem Wert melden
    }
    int count = 0;
    string wort;
    while(!file.eof()) {    // noch nicht am Ende?
        file >> wort;
        ++count;
    }
    return count-1;         // –1: am EOF wurde noch ein Wort gelesen
}
bool process(const vector<string>& args) { // Rückgabe true bei alles okay
    if(args.size() == 0) {  // erwarten Parameter
        cerr << "Kommandozeilenargument fehlt\n";
        return false;       // mittels Rückgabe einen Fehler mitteilen
    } else {
        bool result = true; // fürs Endergebnis
        for(const string filename : args) {
            cout << filename << ": ";
            int count = zaehleWoerter(filename);
            if(count < 0) { // besondere Rückgabe zeigt Fehler an
                cout << "Fehler!\n";
                result = false;         // mindestens ein Fehler
            } else {
                cout << count << "\n";  // normales Ergebnis ausgeben
            }
        }
        return result;                  // Gesamtergebnis zurückgeben
    }
}

int main(int argc, const char* argv[]) {
    bool result = process(              // Rückgabewert enthält Fehlerindikator
        {argv+1, argv+argc} );          // const char*[] nach vector<string>
    if(result) {                        // Rückgabewert auswerten
        return 0;
    } else {
        cerr << "Es trat ein Fehler auf.\n";
        return 1;   // außen Fehler anzeigen
    }
}

Listing 10.2: Exceptions werden mit »throw« ausgelöst und mit »try-catch« behandelt.

Book listing lst-0211-book.cpp:

// https://godbolt.org/z/sz9hxKozf 
#include <iostream>            // cout, cerr
#include <vector>
#include <string>
#include <fstream>             // ifstream
#include <stdexcept>           // invalid_argument
using std::vector; using std::string; using std::cout; using std::ifstream;
size_t zaehleWoerter(const string& filename) { // 0 oder größer
    std::ifstream file{};      // ungeöffnet erzeugen
    // anmelden für Exceptions:
    file.exceptions(ifstream::failbit | ifstream::badbit);
    file.open(filename);       // könnte eine Exception auslösen
    size_t count = 0;
    string wort;
    file.exceptions(ifstream::badbit); // EOF keine Exception mehr
    while(!file.eof()) {       // noch nicht am Ende?
        file >> wort;   ++count;
    }
    return count-1;            // –1: am EOF wurde noch ein Wort gelesen
}
void process(const vector<string>& args) {
    if(args.size() == 0) {     // process erwartet Parameter
        throw std::invalid_argument{"Kommandozeilenarg. fehlt"}; // auslösen
    } else {
        for(const string filename : args) {
            cout << filename << ": " << zaehleWoerter(filename) << std::endl;
        }
    }
}
int main(int argc, const char* argv[]) {
    try {                                      // Block mit Fehlerbehandlungen
        process(
          vector<string>{argv+1, argv+argc} ); // const char*[] nach vector<string>
        return 0;
    } catch(std::exception &exc) {  // Fehlerbehandlung
        std::cerr << "Es trat ein Fehler auf: " << exc.what() << "\n";
        return 1;
    }
}

Godbolt Listing lst-0211-godb.cpp, https://godbolt.org/z/sz9hxKozf:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sz9hxKozf 
#include <iostream>            // cout, cerr
#include <vector>
#include <string>
#include <fstream>             // ifstream
#include <stdexcept>           // invalid_argument
using std::vector; using std::string; using std::cout; using std::ifstream;
size_t zaehleWoerter(const string& filename) { // 0 oder größer
    std::ifstream file{};      // ungeöffnet erzeugen
    // anmelden für Exceptions:
    file.exceptions(ifstream::failbit | ifstream::badbit);
    file.open(filename);       // könnte eine Exception auslösen
    size_t count = 0;
    string wort;
    file.exceptions(ifstream::badbit); // EOF keine Exception mehr
    while(!file.eof()) {       // noch nicht am Ende?
        file >> wort;   ++count;
    }
    return count-1;            // –1: am EOF wurde noch ein Wort gelesen
}
void process(const vector<string>& args) {
    if(args.size() == 0) {     // process erwartet Parameter
        throw std::invalid_argument{"Kommandozeilenarg. fehlt"}; // auslösen
    } else {
        for(const string filename : args) {
            cout << filename << ": " << zaehleWoerter(filename) << std::endl;
        }
    }
}
int main(int argc, const char* argv[]) {
    try {                                      // Block mit Fehlerbehandlungen
        process(
          vector<string>{argv+1, argv+argc} ); // const char*[] nach vector<string>
        return 0;
    } catch(std::exception &exc) {  // Fehlerbehandlung
        std::cerr << "Es trat ein Fehler auf: " << exc.what() << "\n";
        return 1;
    }
}

Listing 10.3: Ein »catch« kann auch innerhalb einer Schleife stehen.

Book listing lst-0212-book.cpp:

void process(const vector<string>& args) {
    if(args.size() == 0) {                 // erwarte Parameter
        throw std::invalid_argument{"Kommandozeilenargument fehlt"};
    } else {
        for(const string filename : args) {
            cout << filename << ": ";
            try {
                cout << zaehleWoerter(filename) << "\n";
            } catch(std::exception &exc) {
                cout << "Fehler: " << exc.what() << "\n";
            }
        }
    }
}

Listing 10.4: Mit »throw« ohne Parameter werfen Sie die gerade behandelte Ausnahme weiter.

Book listing lst-0213-book.cpp:

try {
    cout << zaehleWoerter(filename) << "\n";
} catch(std::exception &exc) {
    cout << "Fehler: " << exc.what() << "\n";
    throw; // weiterwerfen
}

Listing 10.5: Sie können auch andere Typen als Ausnahme auslösen.

Book listing lst-0215-book.cpp:

// https://godbolt.org/z/67cd5bhhE 
#include <string>
#include <iostream> // cout
using std::string; using std::to_string; using std::cout;
void fehlerAusloesen(int fehlerfall) {
   try {
       if(fehlerfall < 10) throw (int)fehlerfall;
       else if(fehlerfall < 20) throw 1.0/(fehlerfall-10.0);
       else throw string{"Fehler " + to_string(fehlerfall)};
   } catch(int eval) {
       cout << "int-fehler: " << eval << "\n";
   } catch(double eval) {
       cout << "double-fehler: " << eval << "\n";
   } catch(string eval) {
       cout << "string-fehler: " << eval << "\n";
   }
}
int main() {
    fehlerAusloesen(3);  // int-fehler: 3
    fehlerAusloesen(14); // Ausgabe: double-fehler: 0.25
    fehlerAusloesen(50); // Ausgabe: string-fehler: Fehler 50
}

Godbolt Listing lst-0215-godb.cpp, https://godbolt.org/z/67cd5bhhE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/67cd5bhhE 
#include <string>
#include <iostream> // cout
using std::string; using std::to_string; using std::cout;
void fehlerAusloesen(int fehlerfall) {
   try {
       if(fehlerfall < 10) throw (int)fehlerfall;
       else if(fehlerfall < 20) throw 1.0/(fehlerfall-10.0);
       else throw string{"Fehler " + to_string(fehlerfall)};
   } catch(int eval) {
       cout << "int-fehler: " << eval << "\n";
   } catch(double eval) {
       cout << "double-fehler: " << eval << "\n";
   } catch(string eval) {
       cout << "string-fehler: " << eval << "\n";
   }
}
int main() {
    fehlerAusloesen(3);  // int-fehler: 3
    fehlerAusloesen(14); // Ausgabe: double-fehler: 0.25
    fehlerAusloesen(50); // Ausgabe: string-fehler: Fehler 50
}

Listing 10.6: Lassen Sie sich wenigstens den Fehlertyp und -text ausgeben, anstatt Ihr Programm aus »main« herauspurzeln zu lassen.

Book listing lst-0216-book.cpp:

// https://godbolt.org/z/TsP33njar 
#include <iostream>
#include <stdexcept> // exception

int main() {
    try {
        // … Ihr sonstiger Code …
    } catch(std::exception& exc) {
        std::cerr << "main: " << exc.what() << "\n";
    }
}

Godbolt Listing lst-0216-godb.cpp, https://godbolt.org/z/TsP33njar:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TsP33njar 
#include <iostream>
#include <stdexcept> // exception

int main() {
    try {
        // … Ihr sonstiger Code …
    } catch(std::exception& exc) {
        std::cerr << "main: " << exc.what() << "\n";
    }
}

Listing 11.1: Die Haupt-Headerdatei der Bibliothek qwort.hpp

Book listing lst-0217-book.cpp:

// https://godbolt.org/z/7nasGjGq6 
#ifndef QWORT_H // Header-Guard
#define QWORT_H
#include <string>
#include <memory> // unique_ptr
namespace qw { // Namensraum der Bibliothek
    int version();
    namespace impl_multimap {
        class index_impl;
    }
    class index {
        using index_impl = impl_multimap::index_impl;
    public:
        index();
        ~index() noexcept; // wird für pimpl benötigt
        index(const index&) = default;
        index(index&&) noexcept;
        index& operator=(const index&) = default;
        index& operator=(index&&) = default;
    public:
        void add(const std::string &arg);
        size_t size() const;
        std::string getBestMatch(const std::string& query) const;
    public:          // public für Tests
        std::string normalize(std::string arg) const;
    private:
        const std::unique_ptr<index_impl> pimpl;
    };
} // namespace qw
#endif // Header-Guard

Godbolt Listing lst-0217-godb.cpp, https://godbolt.org/z/7nasGjGq6:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7nasGjGq6 
#ifndef QWORT_H // Header-Guard
#define QWORT_H
#include <string>
#include <memory> // unique_ptr
namespace qw { // Namensraum der Bibliothek
    int version();
    namespace impl_multimap {
        class index_impl;
    }
    class index {
        using index_impl = impl_multimap::index_impl;
    public:
        index();
        ~index() noexcept; // wird für pimpl benötigt
        index(const index&) = default;
        index(index&&) noexcept;
        index& operator=(const index&) = default;
        index& operator=(index&&) = default;
    public:
        void add(const std::string &arg);
        size_t size() const;
        std::string getBestMatch(const std::string& query) const;
    public:          // public für Tests
        std::string normalize(std::string arg) const;
    private:
        const std::unique_ptr<index_impl> pimpl;
    };
} // namespace qw
#endif // Header-Guard

Listing 11.2: Die Schnittstellenklasse leitet alle Aufrufe an die Implementierungsklasse weiter.

Book listing lst-0218-book.cpp:

// https://godbolt.org/z/zbcdd1jha 
#include "qwort/qwort.hpp" // selbst
#include <map>
#include <algorithm>       // transform
#include <cctype>          // toupper
#include "impl_multimap.hpp"
using std::map; using std::string;

namespace qw {
    int version() {
        return 1;
    }
    // Verwaltung
    index::index()
        : pimpl{ new index_impl{} }
        { }
    index::~index() noexcept = default;
    index::index(index&&) noexcept = default;
    // Schnittstelle
    void index::add(const string &arg) {
        pimpl->add(normalize(arg), arg);
    }
    size_t index::size() const {
        return pimpl->size();
    }
    string index::getBestMatch(const string& query) const {
        return pimpl->getBestMatch(normalize(query));
    }
    string index::normalize(string str) const {
        using namespace std; // begin, end
        transform(begin(str), end(str), begin(str), [](char c) {
                return ::isalpha(c) ? ::toupper(c) : '#';
            });
        return str;
    }
} // namespace qw

Godbolt Listing lst-0218-godb.cpp, https://godbolt.org/z/zbcdd1jha:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zbcdd1jha 
#include "qwort/qwort.hpp" // selbst
#include <map>
#include <algorithm>       // transform
#include <cctype>          // toupper
#include "impl_multimap.hpp"
using std::map; using std::string;

namespace qw {
    int version() {
        return 1;
    }
    // Verwaltung
    index::index()
        : pimpl{ new index_impl{} }
        { }
    index::~index() noexcept = default;
    index::index(index&&) noexcept = default;
    // Schnittstelle
    void index::add(const string &arg) {
        pimpl->add(normalize(arg), arg);
    }
    size_t index::size() const {
        return pimpl->size();
    }
    string index::getBestMatch(const string& query) const {
        return pimpl->getBestMatch(normalize(query));
    }
    string index::normalize(string str) const {
        using namespace std; // begin, end
        transform(begin(str), end(str), begin(str), [](char c) {
                return ::isalpha(c) ? ::toupper(c) : '#';
            });
        return str;
    }
} // namespace qw

Listing 11.3: Header der Implementierungsklasse

Book listing lst-0219-book.cpp:

// https://godbolt.org/z/5Tfr6xxa5 
#include <string>
#include <string_view>
#include <vector>
#include <map> // multimap
namespace qw::impl_multimap {
using std::vector; using std::multimap; 
using std::string; using std::string_view;
class index_impl {
    vector<string> entries;
    multimap<string,size_t> qindex;
public:
    void add(string_view normalized, string_view original);
    string getBestMatch(string_view normalized) const;
    size_t size() const {
        return entries.size();
    }
private:
    vector<string> qgramify(string_view normalized) const;
    static constexpr size_t Q = 3;
    static const std::string PREFIX;
    static const std::string SUFFIX;
public: // test interface
    vector<string> _qgramify(string_view n) const { return qgramify(n); }
    static size_t _q() { return Q; }
    static std::string _prefix() { return PREFIX; }
    static std::string _suffix() { return SUFFIX; }
};
} // namespace qw::impl_multimap

Godbolt Listing lst-0219-godb.cpp, https://godbolt.org/z/5Tfr6xxa5:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5Tfr6xxa5 
#include <string>
#include <string_view>
#include <vector>
#include <map> // multimap
namespace qw::impl_multimap {
using std::vector; using std::multimap; 
using std::string; using std::string_view;
class index_impl {
    vector<string> entries;
    multimap<string,size_t> qindex;
public:
    void add(string_view normalized, string_view original);
    string getBestMatch(string_view normalized) const;
    size_t size() const {
        return entries.size();
    }
private:
    vector<string> qgramify(string_view normalized) const;
    static constexpr size_t Q = 3;
    static const std::string PREFIX;
    static const std::string SUFFIX;
public: // test interface
    vector<string> _qgramify(string_view n) const { return qgramify(n); }
    static size_t _q() { return Q; }
    static std::string _prefix() { return PREFIX; }
    static std::string _suffix() { return SUFFIX; }
};
} // namespace qw::impl_multimap

Listing 11.4: Der Header der Implementierungsklasse

Book listing lst-0220-book.cpp:

// https://godbolt.org/z/41sPszG1G 
#include "impl_multimap.hpp" // Header zu dieser Datei
#include <map>
#include <string>
#include <string_view>

namespace qw::impl_multimap {

using std::vector; using std::multimap; using std::map; using std::string;
using std::string_view; using namespace std::literals::string_literals;

void index_impl::add(string_view normalized, string_view original) {
    /* TODO: Vorhandensein in 'entries' prüfen */
    const auto pos = entries.size(); // Index des neuen Eintrags
    entries.push_back(string(original));
    auto qgrams = qgramify(normalized);
    for(const auto& qgram : qgrams) {
        qindex.insert( make_pair(qgram, pos) );
    }
}
string index_impl::getBestMatch(string_view normalized) const {
    auto qgrams = qgramify(normalized);
    /* hits speichert, welche Wörter wie oft getroffen wurden */
    map<size_t, size_t> hits; /* 'entries-index' zu 'hit-count' */
    size_t maxhits = 0z; /* immer: max(hits.second) */
    for(const auto& qgram : qgrams) {
        auto [beg, end] = qindex.equal_range(qgram);
        for(auto it=beg; it!=end; ++it) {
            hits[it->second] += 1z; /* hit-count des Eintrags */
            if(hits[it->second] > maxhits) { /* max-Suche einfacher */
                maxhits = hits[it->second];
            }
        }
    }
    /* Suche ersten Eintrag mit maxhits. Bessere Implementierung mit PrioQueue möglich */
    for(auto const &hit : hits) {
        if(hit.second == maxhits) {
            return entries[hit.first];
        }
    }
    /* nur erreicht, wenn entries leer ist */
    return ""s;
}
const string index_impl::PREFIX = string(Q-1, '^');
const string index_impl::SUFFIX = string(Q-1, '$');

vector<string> index_impl::qgramify(string_view normalized) const {
    auto word = PREFIX + string(normalized)+SUFFIX; /* Trick für bessere QGramme */
    vector<string> result {};
    auto left = word.cbegin();
    auto right = std::next(word.cbegin(), Q); /* okay: |"^^"|+|"$$"| => 3 */
    for( ; right <= word.end(); ++left, ++right) {
        result.emplace_back(left, right);
    }
    return result;
}
} // namespace qw::impl_multimap

Godbolt Listing lst-0220-godb.cpp, https://godbolt.org/z/41sPszG1G:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/41sPszG1G 
#include "impl_multimap.hpp" // Header zu dieser Datei
#include <map>
#include <string>
#include <string_view>

namespace qw::impl_multimap {

using std::vector; using std::multimap; using std::map; using std::string;
using std::string_view; using namespace std::literals::string_literals;

void index_impl::add(string_view normalized, string_view original) {
    /* TODO: Vorhandensein in 'entries' prüfen */
    const auto pos = entries.size(); // Index des neuen Eintrags
    entries.push_back(string(original));
    auto qgrams = qgramify(normalized);
    for(const auto& qgram : qgrams) {
        qindex.insert( make_pair(qgram, pos) );
    }
}
string index_impl::getBestMatch(string_view normalized) const {
    auto qgrams = qgramify(normalized);
    /* hits speichert, welche Wörter wie oft getroffen wurden */
    map<size_t, size_t> hits; /* 'entries-index' zu 'hit-count' */
    size_t maxhits = 0z; /* immer: max(hits.second) */
    for(const auto& qgram : qgrams) {
        auto [beg, end] = qindex.equal_range(qgram);
        for(auto it=beg; it!=end; ++it) {
            hits[it->second] += 1z; /* hit-count des Eintrags */
            if(hits[it->second] > maxhits) { /* max-Suche einfacher */
                maxhits = hits[it->second];
            }
        }
    }
    /* Suche ersten Eintrag mit maxhits. Bessere Implementierung mit PrioQueue möglich */
    for(auto const &hit : hits) {
        if(hit.second == maxhits) {
            return entries[hit.first];
        }
    }
    /* nur erreicht, wenn entries leer ist */
    return ""s;
}
const string index_impl::PREFIX = string(Q-1, '^');
const string index_impl::SUFFIX = string(Q-1, '$');

vector<string> index_impl::qgramify(string_view normalized) const {
    auto word = PREFIX + string(normalized)+SUFFIX; /* Trick für bessere QGramme */
    vector<string> result {};
    auto left = word.cbegin();
    auto right = std::next(word.cbegin(), Q); /* okay: |"^^"|+|"$$"| => 3 */
    for( ; right <= word.end(); ++left, ++right) {
        result.emplace_back(left, right);
    }
    return result;
}
} // namespace qw::impl_multimap

Listing 11.5: So ziemlich das einfachste Beispielprogramm der Bibliothek

Book listing lst-0221-book.cpp:

// https://godbolt.org/z/Gvcj6hhYf 
#include <cstdlib>  // EXIT_SUCCESS
#include <iostream> // cout
#include <vector>
#include <string>
#include "qwort/qwort.hpp"
using std::cout; using std::vector; using std::string;
int main(int argc, const char* argv[]) {
    cout << "qwort version " << qw::version() << "\n";

    /* Index bauen */
    qw::index myindex{};

    /* - Demodaten */
    myindex.add("Deutschland");
    myindex.add("Griechenland");

    /* Abfragen erzeugen */
    vector<string> args(argv+1, argv+argc); // iteratorbasierte Initialisierung
    for(auto &querystring : args) {
        cout << "Suche '" << querystring << "'... ";
        const auto match = myindex.getBestMatch(querystring);
        cout << match << "\n";
    }
    return EXIT_SUCCESS;
}

Godbolt Listing lst-0221-godb.cpp, https://godbolt.org/z/Gvcj6hhYf:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gvcj6hhYf 
#include <cstdlib>  // EXIT_SUCCESS
#include <iostream> // cout
#include <vector>
#include <string>
#include "qwort/qwort.hpp"
using std::cout; using std::vector; using std::string;
int main(int argc, const char* argv[]) {
    cout << "qwort version " << qw::version() << "\n";

    /* Index bauen */
    qw::index myindex{};

    /* - Demodaten */
    myindex.add("Deutschland");
    myindex.add("Griechenland");

    /* Abfragen erzeugen */
    vector<string> args(argv+1, argv+argc); // iteratorbasierte Initialisierung
    for(auto &querystring : args) {
        cout << "Suche '" << querystring << "'... ";
        const auto match = myindex.getBestMatch(querystring);
        cout << match << "\n";
    }
    return EXIT_SUCCESS;
}

Listing 12.1: Listing 12.1 Einen eigenen Datentyp erzeugen Sie mit »struct«.

Book listing lst-0222-book.cpp:

// https://godbolt.org/z/8YqoTEx58 
#include <string>
#include <iostream>                     // cout
#include <format>
using std::string; using std::cout; using std::format;
struct Person {                         // definiert den neuen Typ Person
    string name_;
    int alter_;
    string ort_;
};                                      // abschließendes Semikolon
void drucke(Person p) {                 // ganze Person als ein Parameter
    cout << format("{} ({}) aus {}\n",
      p.name_, p.alter_, p.ort_);       // Zugriff per Punkt
}
int main() {
    Person otto {"Otto", 45, "Kassel" }; // Initialisierung
    drucke(otto);                        // Aufruf als Einheit
}

Godbolt Listing lst-0222-godb.cpp, https://godbolt.org/z/8YqoTEx58:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8YqoTEx58 
#include <string>
#include <iostream>                     // cout
#include <format>
using std::string; using std::cout; using std::format;
struct Person {                         // definiert den neuen Typ Person
    string name_;
    int alter_;
    string ort_;
};                                      // abschließendes Semikolon
void drucke(Person p) {                 // ganze Person als ein Parameter
    cout << format("{} ({}) aus {}\n",
      p.name_, p.alter_, p.ort_);       // Zugriff per Punkt
}
int main() {
    Person otto {"Otto", 45, "Kassel" }; // Initialisierung
    drucke(otto);                        // Aufruf als Einheit
}

Listing 12.2: Listing 12.2 Die Deklaration einer Klasse nennt erst mal nur ihren Namen, die Definition enthält alle ihre Elemente.

Book listing lst-0223-book.cpp:

// https://godbolt.org/z/jPqn7c3T8 
#include <memory>                      // shared_ptr
#include <vector>                      // vector
struct Mitarbeiter;                    // Klassendeklaration
struct Chef;                           // Klassendeklaration
struct Mitarbeiter {                   // Klassendefinition
    std::shared_ptr<Chef> chef_;       // Zeiger auf Chef
    void print() const;                // Methodendeklaration
};
struct Chef {                           // Definition
    std::vector<std::shared_ptr<Mitarbeiter>> mitarbeiter_; // Zeiger auf Mitarbeiter
    void print() const;                 // Methodendeklaration
};
void Mitarbeiter::print() const {       // Methodendefinition
    // …
}
void Chef::print() const {              // Methodendefinition
    // …
}

Godbolt Listing lst-0223-godb.cpp, https://godbolt.org/z/jPqn7c3T8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jPqn7c3T8 
#include <memory>                      // shared_ptr
#include <vector>                      // vector
struct Mitarbeiter;                    // Klassendeklaration
struct Chef;                           // Klassendeklaration
struct Mitarbeiter {                   // Klassendefinition
    std::shared_ptr<Chef> chef_;       // Zeiger auf Chef
    void print() const;                // Methodendeklaration
};
struct Chef {                           // Definition
    std::vector<std::shared_ptr<Mitarbeiter>> mitarbeiter_; // Zeiger auf Mitarbeiter
    void print() const;                 // Methodendeklaration
};
void Mitarbeiter::print() const {       // Methodendefinition
    // …
}
void Chef::print() const {              // Methodendefinition
    // …
}

Listing 12.3: Listing 12.3 Mit designierten Initialisierern geben Sie die zu setzenden Elemente an.

Book listing lst-0226-book.cpp:

// https://godbolt.org/z/e9Wshbx3q 
Person otto1 {"Otto", 45, "Kassel" }; // korrekt
Person otto2 {"Kassel", 45, "Otto" }; // oje, vertauscht, und keiner merkt's
Person hans { .name_ = "Hans", .alter_ = 23, .ort_ = "Berlin" }; // okay
Person willi { .name_ = "Willi", .alter_ = 48  }; // okay, nicht alle angegeben
Person karl { "Karl", .alter_ = 53  }; //             (ERR)  alle designiert oder keiner
Person paul { .alter_ = 34, .name_ = "Paul", .ort = "Bonn" }; //             (ERR)  vertauscht
Person pit(.name_="Pit", .alter_=34, .ort_="Wyk"); //             (ERR)  nicht mit runden Klammern

Godbolt Listing lst-0226-godb.cpp, https://godbolt.org/z/e9Wshbx3q:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/e9Wshbx3q 
Person otto1 {"Otto", 45, "Kassel" }; // korrekt
Person otto2 {"Kassel", 45, "Otto" }; // oje, vertauscht, und keiner merkt's
Person hans { .name_ = "Hans", .alter_ = 23, .ort_ = "Berlin" }; // okay
Person willi { .name_ = "Willi", .alter_ = 48  }; // okay, nicht alle angegeben
Person karl { "Karl", .alter_ = 53  }; //             (ERR)  alle designiert oder keiner
Person paul { .alter_ = 34, .name_ = "Paul", .ort = "Bonn" }; //             (ERR)  vertauscht
Person pit(.name_="Pit", .alter_=34, .ort_="Wyk"); //             (ERR)  nicht mit runden Klammern

GodboltId:xnT7voqen

Book listing lst-0227-book.cpp:

// https://godbolt.org/z/xnT7voqen 
// Ausschnitt
Person erzeuge(string name, int alter, string ort) { // Rückgabetyp
    Person result {name, alter, ort};
    return result;
}
int main() {
    Person otto = erzeuge("Otto", 45, "Kassel"); // Rückgabe speichern
    drucke(otto);
}

Godbolt Listing lst-0227-godb.cpp, https://godbolt.org/z/xnT7voqen:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xnT7voqen 
// Ausschnitt
Person erzeuge(string name, int alter, string ort) { // Rückgabetyp
    Person result {name, alter, ort};
    return result;
}
int main() {
    Person otto = erzeuge("Otto", 45, "Kassel"); // Rückgabe speichern
    drucke(otto);
}

GodboltId:YYfxMdfP8

Book listing lst-0228-book.cpp:

// https://godbolt.org/z/YYfxMdfP8 
Person erzeuge(string name, int alter, string ort) {
    return Person{name, alter, ort};       // direkt zurückgegeben
}
int main() {
    drucke(erzeuge("Otto", 45, "Kassel")); // Rückgabe direkt verwendet
}

Godbolt Listing lst-0228-godb.cpp, https://godbolt.org/z/YYfxMdfP8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YYfxMdfP8 
Person erzeuge(string name, int alter, string ort) {
    return Person{name, alter, ort};       // direkt zurückgegeben
}
int main() {
    drucke(erzeuge("Otto", 45, "Kassel")); // Rückgabe direkt verwendet
}

Listing 12.4: Listing 12.4 Hier ist die Angabe von Person beim return nötig.

Book listing lst-0231-book.cpp:

// https://godbolt.org/z/KvTx3rPs5 
auto erzeuge(string name, int alter, string ort) {
    return Person{name, alter, ort};  // auto verlangt Konstruktornamen
}
auto erzeuge2(string name, int alter, string ort) {
    return {name, alter, ort};       //             (ERR)  auto mit initializer_list geht nicht
}

Godbolt Listing lst-0231-godb.cpp, https://godbolt.org/z/KvTx3rPs5:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KvTx3rPs5 
auto erzeuge(string name, int alter, string ort) {
    return Person{name, alter, ort};  // auto verlangt Konstruktornamen
}
auto erzeuge2(string name, int alter, string ort) {
    return {name, alter, ort};       //             (ERR)  auto mit initializer_list geht nicht
}

Listing 12.5: Listing 12.5 Methoden packen Daten und Verhalten zusammen.

Book listing lst-0232-book.cpp:

// https://godbolt.org/z/M1ozTorEz 
#include <string>
#include <iostream>
#include <format>
using std::string; using std::cout; using std::format;
struct Person {
  string name_;
  int alter_;
  string ort_;
  void drucke();            // Funktion als Methode des Typs
};
void Person::drucke() {     // Name der Methode wird um Person:: erweitert
  cout << format("{} ({}) aus {}\n",
    name_, alter_, ort_);   // in einer Methode können Sie direkt auf Felder zugreifen
}
int main() {
  Person otto {"Otto", 45, "Kassel" };
  otto.drucke();            // Aufruf der Methode für eine Variable des Typs
}

Godbolt Listing lst-0232-godb.cpp, https://godbolt.org/z/M1ozTorEz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M1ozTorEz 
#include <string>
#include <iostream>
#include <format>
using std::string; using std::cout; using std::format;
struct Person {
  string name_;
  int alter_;
  string ort_;
  void drucke();            // Funktion als Methode des Typs
};
void Person::drucke() {     // Name der Methode wird um Person:: erweitert
  cout << format("{} ({}) aus {}\n",
    name_, alter_, ort_);   // in einer Methode können Sie direkt auf Felder zugreifen
}
int main() {
  Person otto {"Otto", 45, "Kassel" };
  otto.drucke();            // Aufruf der Methode für eine Variable des Typs
}

Listing 12.6: Listing 12.6 Die Methode »gruss()« verwendet Felder — mittels »this« ist es immer das zum aufgerufenen Objekt gehörende Feld.

Book listing lst-0233-book.cpp:

struct Person {
    //… Rest wie zuvor …
    string gruss();
};
string Person::gruss() {
    return format("Hallo {} aus {}", this->name_, this->ort_);
}
int main() {
    Person anna { "Anna", 33, "Hof" };
    Person nina { "Nina", 22, "Wyk" };
    anna.gruss();
    nina.gruss();
}

Listing 12.7: Listing 12.7 So trennen Sie Methoden und Daten voneinander.

Book listing lst-0235-book.cpp:

string gruss(Person * const p) {  // impliziter Parameter explizit gemacht
    return format("Hallo {} aus {}", p->name_, p->ort_);
}

GodboltId:hEvqWqqc6

Book listing lst-0236-book.cpp:

// https://godbolt.org/z/hEvqWqqc6 
int wert = 5;                         // globale Variable
struct Wrap {
    int wert = 3;                     // Datenfeld
    void setze(int wert) {            // Parameter
        this->wert = wert + ::wert;
    }
};

Godbolt Listing lst-0236-godb.cpp, https://godbolt.org/z/hEvqWqqc6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hEvqWqqc6 
int wert = 5;                         // globale Variable
struct Wrap {
    int wert = 3;                     // Datenfeld
    void setze(int wert) {            // Parameter
        this->wert = wert + ::wert;
    }
};

Listing 12.8: Listing 12.8 »drucke« nimmt einen Stream als Argument.

Book listing lst-0239-book.cpp:

// https://godbolt.org/z/bjWKjaeaK 
// Ausschnitt. Person wie zuvor
void Person::drucke(std::ostream& os) {
    os << format("{} ({}) aus {}", name_, alter_,  ort_);
}
int main() {
    Person karl {"Karl", 12, "Stetten"};
    karl.drucke(cout);        // auf dem Bildschirm
    cout << "\n";
    std::ofstream datei {"personen.txt"};
    karl.drucke(datei);       // in eine Datei
    // automatischer Test:
    std::ostringstream oss{}; // schreibt in einen string
    karl.drucke(oss);
    if(oss.str() == "Karl (12) aus Stetten") {
        cout << "ok\n";
    } else {
        cout << "Fehler in Person::drucke!\n";
        return 1;             // Fehler nach außen weiterleiten
    }
}

Godbolt Listing lst-0239-godb.cpp, https://godbolt.org/z/bjWKjaeaK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bjWKjaeaK 
// Ausschnitt. Person wie zuvor
void Person::drucke(std::ostream& os) {
    os << format("{} ({}) aus {}", name_, alter_,  ort_);
}
int main() {
    Person karl {"Karl", 12, "Stetten"};
    karl.drucke(cout);        // auf dem Bildschirm
    cout << "\n";
    std::ofstream datei {"personen.txt"};
    karl.drucke(datei);       // in eine Datei
    // automatischer Test:
    std::ostringstream oss{}; // schreibt in einen string
    karl.drucke(oss);
    if(oss.str() == "Karl (12) aus Stetten") {
        cout << "ok\n";
    } else {
        cout << "Fehler in Person::drucke!\n";
        return 1;             // Fehler nach außen weiterleiten
    }
}

Listing 12.9: Listing 12.9 Sie können den Standardoperator für die Ausgabe überladen.

Book listing lst-0240-book.cpp:

std::ostream& Person::drucke(std::ostream& os) {
    return os << format("{} ({}) aus {}", name_, alter_,  ort_);
}
std::ostream& operator<<(std::ostream& os, Person p) {
    return p.drucke(os);
}

Listing 12.10: Listing 12.10 Die Ausgabe mit << erreichen Sie durch Überladung einer freien Funktion.

Book listing lst-0242-book.cpp:

// https://godbolt.org/z/bEdfWqqnn 
// Ausschnitt …
    std::ostream& drucke(std::ostream& os);
};
std::ostream& Person::drucke(std::ostream& os) {
    return os << format("{} ({}) aus {}", p.name_, p.alter_,  p.ort_);
}
std::ostream& operator<<(std::ostream& os, Person p) {
    return p.drucke(os);
}
int main() {
    Person paul {"Paul", 23, "Dresden"};
    cout << "Sie sind " << paul << ", richtig?\n";
}

Godbolt Listing lst-0242-godb.cpp, https://godbolt.org/z/bEdfWqqnn:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bEdfWqqnn 
// Ausschnitt …
    std::ostream& drucke(std::ostream& os);
};
std::ostream& Person::drucke(std::ostream& os) {
    return os << format("{} ({}) aus {}", p.name_, p.alter_,  p.ort_);
}
std::ostream& operator<<(std::ostream& os, Person p) {
    return p.drucke(os);
}
int main() {
    Person paul {"Paul", 23, "Dresden"};
    cout << "Sie sind " << paul << ", richtig?\n";
}

Listing 12.11: Listing 12.11 Methoden können auch inline definiert werden.

Book listing lst-0243-book.cpp:

// https://godbolt.org/z/zf9Tc4ahs 
#include <string>
#include <iostream>    // ostream

using std::string; using std::ostream;

struct Person {
  string name_;
  int alter_;
  string ort_;
  ostream& drucke(ostream& os) {  // Methode inline definiert
    return os << format("{} ({}) aus {}", p.name_, p.alter_,  p.ort_);
  }
};

Godbolt Listing lst-0243-godb.cpp, https://godbolt.org/z/zf9Tc4ahs:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zf9Tc4ahs 
#include <string>
#include <iostream>    // ostream

using std::string; using std::ostream;

struct Person {
  string name_;
  int alter_;
  string ort_;
  ostream& drucke(ostream& os) {  // Methode inline definiert
    return os << format("{} ({}) aus {}", p.name_, p.alter_,  p.ort_);
  }
};

Listing 12.12: Listing 12.12 So definieren Sie einen Konstruktor.

Book listing lst-0248-book.cpp:

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person();          // Konstruktor deklarieren
};
Person::Person()
  : name_{"kein Name"} // Initialisierungswert für name_
  , alter_{-1}         // Initialisierungswert für alter_
  , ort_{"kein Ort"}   // Initialisierungswert für ort_
{ }                    // leerer Funktionskörper

Listing 12.13: Listing 12.13 Auch mehrere Konstruktoren sind möglich.

Book listing lst-0250-book.cpp:

// https://godbolt.org/z/cqoTsWbhW 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person();                         // Konstruktor ohne Argumente
    Person(sview n, int a, sview o);  // Konstruktor mit drei Argumenten
    Person(sview n, int a);           // Konstruktor mit zwei Argumenten
    Person(sview n);                  // Konstruktor mit einem Argument
};

Person::Person() 
  : name_{"kein Name"}, alter_{-1}, ort_{"kein Ort"} { } 
Person::Person(sview n, int a, sview o) 
  : name_{n}, alter_{a}, ort_{o} { } 
Person::Person(sview n, int a)
  : name_{n}, alter_{a}, ort_{"kein Ort"} { }
Person::Person(sview n)
  : name_{n}, alter_{-1}, ort_{"kein Ort"} { }

Godbolt Listing lst-0250-godb.cpp, https://godbolt.org/z/cqoTsWbhW:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cqoTsWbhW 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person();                         // Konstruktor ohne Argumente
    Person(sview n, int a, sview o);  // Konstruktor mit drei Argumenten
    Person(sview n, int a);           // Konstruktor mit zwei Argumenten
    Person(sview n);                  // Konstruktor mit einem Argument
};

Person::Person() 
  : name_{"kein Name"}, alter_{-1}, ort_{"kein Ort"} { } 
Person::Person(sview n, int a, sview o) 
  : name_{n}, alter_{a}, ort_{o} { } 
Person::Person(sview n, int a)
  : name_{n}, alter_{a}, ort_{"kein Ort"} { }
Person::Person(sview n)
  : name_{n}, alter_{-1}, ort_{"kein Ort"} { }

Listing 12.14: Listing 12.14 Membervariablen können mit Defaultwerten ausgestattet werden.

Book listing lst-0251-book.cpp:

// https://godbolt.org/z/vzneMWW9r 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;
struct Person {
    string name_ = "kein Name";
    int alter_ = -1;
    string ort_ = "kein Ort";
    Person() {}
    Person(sview n, int a, sview o)
      : name_{n}, alter_{a}, ort_{o} { }
    Person(sview n, int a)
      : name_{n}, alter_{a} { }
    Person(sview n)
      : name_{n} { }
};

Godbolt Listing lst-0251-godb.cpp, https://godbolt.org/z/vzneMWW9r:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vzneMWW9r 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;
struct Person {
    string name_ = "kein Name";
    int alter_ = -1;
    string ort_ = "kein Ort";
    Person() {}
    Person(sview n, int a, sview o)
      : name_{n}, alter_{a}, ort_{o} { }
    Person(sview n, int a)
      : name_{n}, alter_{a} { }
    Person(sview n)
      : name_{n} { }
};

Listing 12.15: Listing 12.15 Ein Konstruktor kann einen Teil der Initialisierung an einen anderen Konstruktor weiterreichen.

Book listing lst-0252-book.cpp:

// https://godbolt.org/z/83efx7Gex 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;

    Person(sview n, int a, sview o)                   // delegierter Konstruktor
      : name_(n), alter_(a), ort_(o) { }              // … ausimplementiert
    Person() : Person{"kein Name",-1,"kein Ort"} { }  // delegierend
    Person(sview n, int a) : Person{n, a, "kein Ort"} { } // delegierend
    Person(sview n) : Person{n, -1, "kein Ort"} { }       // delegierend
};

Godbolt Listing lst-0252-godb.cpp, https://godbolt.org/z/83efx7Gex:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/83efx7Gex 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;

    Person(sview n, int a, sview o)                   // delegierter Konstruktor
      : name_(n), alter_(a), ort_(o) { }              // … ausimplementiert
    Person() : Person{"kein Name",-1,"kein Ort"} { }  // delegierend
    Person(sview n, int a) : Person{n, a, "kein Ort"} { } // delegierend
    Person(sview n) : Person{n, -1, "kein Ort"} { }       // delegierend
};

Listing 12.16: Listing 12.16 Auch ein Konstruktor kann mit Defaultparametern überladen werden.

Book listing lst-0253-book.cpp:

// https://godbolt.org/z/Exh4PnMTE 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;

    Person(sview n = "N.N.", int a = 18, sview o = "Berlin")
      : name_(n), alter_(a), ort_(o) { }
};

Godbolt Listing lst-0253-godb.cpp, https://godbolt.org/z/Exh4PnMTE:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Exh4PnMTE 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;

    Person(sview n = "N.N.", int a = 18, sview o = "Berlin")
      : name_(n), alter_(a), ort_(o) { }
};

Listing 12.17: Listing 12.17 Ein Konstruktor mit allen vorbesetzten Argumenten wird zum Defaultkonstruktor.

Book listing lst-0255-book.cpp:

// https://godbolt.org/z/vb1Wsr5d3 
#include <vector>
#include <string>
#include <string_view>
#include <iostream>
using std::string; using std::cout; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    // fungiert als Defaultkonstruktor:
    Person(sview n = "N.N.", int a = 18, sview o = "Berlin")
      : name_(n), alter_(a), ort_(o) { }
};

int main() {
    std::vector<Person> personen{}; // zunächst leer
    personen.resize(5); // auf fünf »leere« Personen erweitern
    cout << personen[3].ort_ << "\n"; // Ausgabe: Berlin
}

Godbolt Listing lst-0255-godb.cpp, https://godbolt.org/z/vb1Wsr5d3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vb1Wsr5d3 
#include <vector>
#include <string>
#include <string_view>
#include <iostream>
using std::string; using std::cout; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    // fungiert als Defaultkonstruktor:
    Person(sview n = "N.N.", int a = 18, sview o = "Berlin")
      : name_(n), alter_(a), ort_(o) { }
};

int main() {
    std::vector<Person> personen{}; // zunächst leer
    personen.resize(5); // auf fünf »leere« Personen erweitern
    cout << personen[3].ort_ << "\n"; // Ausgabe: Berlin
}

Listing 12.18: Listing 12.18 Rufen Sie keine initialisierende Methode im Konstruktorkörper auf.

Book listing lst-0256-book.cpp:

// https://godbolt.org/z/osM9ncPzr 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person(sview n, int a, sview o)
    {                   //                 (ERR)  Initialisierungsliste fehlt
        init(n, a, o);  //                 (ERR)  fragwürdiger »Initialisierungsaufruf«
    }
    void init(sview n, int a, sview o) {
      name_ = n; alter_ = a; ort_ = o;
    }
};

Godbolt Listing lst-0256-godb.cpp, https://godbolt.org/z/osM9ncPzr:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/osM9ncPzr 
#include <string>
#include <string_view>
using std::string; using sview = std::string_view;

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person(sview n, int a, sview o)
    {                   //                 (ERR)  Initialisierungsliste fehlt
        init(n, a, o);  //                 (ERR)  fragwürdiger »Initialisierungsaufruf«
    }
    void init(sview n, int a, sview o) {
      name_ = n; alter_ = a; ort_ = o;
    }
};

Listing 12.19: Listing 12.19 Zugriff von außen auf die Datenfelder eines Typs

Book listing lst-0258-book.cpp:

ostream& operator<<(ostream& os, Person p) {
    return os << format("{} ({}) aus {}", p.name_, p.alter_, p.ort_);
}

Listing 12.20: Listing 12.20 Teilen Sie einen Typ mit »public« und »private« in mehrere Bereiche auf.

Book listing lst-0259-book.cpp:

// https://godbolt.org/z/zrE55vWq3 
#include <string>
#include <string_view>
using std::string; using std::string_view;

struct Person {
private: // alles ab hier kann von außen nicht benutzt werden
    string name_;
    int alter_;
    string ort_;
public:  // alles ab hier darf von außen verwendet werden
    Person(string_view n, int a, string_view o)
      : name_{n}, alter_{a}, ort_{o} { }
    void drucke();
};

Godbolt Listing lst-0259-godb.cpp, https://godbolt.org/z/zrE55vWq3:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zrE55vWq3 
#include <string>
#include <string_view>
using std::string; using std::string_view;

struct Person {
private: // alles ab hier kann von außen nicht benutzt werden
    string name_;
    int alter_;
    string ort_;
public:  // alles ab hier darf von außen verwendet werden
    Person(string_view n, int a, string_view o)
      : name_{n}, alter_{a}, ort_{o} { }
    void drucke();
};

Listing 12.21: Listing 12.21 »class« beginnt mit privater Sichtbarkeit.

Book listing lst-0260-book.cpp:

// https://godbolt.org/z/e6rqbq3bE 
#include <string>
#include <string_view>
using std::string; using std::string_view;

class Person { // eine Klasse beginnt mit privater Sichtbarkeit
    string name_;
    int alter_;
    string ort_;
public:  // alles ab hier darf von außen verwendet werden
    Person(string_view n, int a, string_view o)
      : name_{n}, alter_{a}, ort_{o} { }
    void drucke();
};

Godbolt Listing lst-0260-godb.cpp, https://godbolt.org/z/e6rqbq3bE:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/e6rqbq3bE 
#include <string>
#include <string_view>
using std::string; using std::string_view;

class Person { // eine Klasse beginnt mit privater Sichtbarkeit
    string name_;
    int alter_;
    string ort_;
public:  // alles ab hier darf von außen verwendet werden
    Person(string_view n, int a, string_view o)
      : name_{n}, alter_{a}, ort_{o} { }
    void drucke();
};

Listing 12.22: Listing 12.22 Teile der Daten sind privat.

Book listing lst-0261-book.cpp:

// https://godbolt.org/z/Pr76Y55P4 
class Rect {
    int area_;  // private Daten
public:
    int x_, y_;
    void set(int x, int y) { x_=x; y_=y; area_=x_*y_; }
    int calc() { return area_; }
};

Godbolt Listing lst-0261-godb.cpp, https://godbolt.org/z/Pr76Y55P4:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Pr76Y55P4 
class Rect {
    int area_;  // private Daten
public:
    int x_, y_;
    void set(int x, int y) { x_=x; y_=y; area_=x_*y_; }
    int calc() { return area_; }
};

Listing 12.23: Listing 12.23 Mit »= default« lassen Sie den Compiler Code erzeugen.

Book listing lst-0262-book.cpp:

// https://godbolt.org/z/PaG9nTs7s 
class Rect {
    int area_;         // private Daten

public:
    int x_, y_;
    void set(int x, int y) { x_=x; y_=y; area_=x_*y_; }
    int calc() { return area_; }
    Rect() = default;  // den Compiler einen Konstruktor generieren lassen
};
class Pow {
    int result_;       // private Daten; hält 'base' hoch 'exp'
public:
    int base_, exp_;
    void set(int b, int e) { /* ... */ }
    int calc() { return result_; }
    Pow() : result_{1},base_{1},exp_{1} {} // sinnvoll initialisieren
};

Godbolt Listing lst-0262-godb.cpp, https://godbolt.org/z/PaG9nTs7s:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PaG9nTs7s 
class Rect {
    int area_;         // private Daten

public:
    int x_, y_;
    void set(int x, int y) { x_=x; y_=y; area_=x_*y_; }
    int calc() { return area_; }
    Rect() = default;  // den Compiler einen Konstruktor generieren lassen
};
class Pow {
    int result_;       // private Daten; hält 'base' hoch 'exp'
public:
    int base_, exp_;
    void set(int b, int e) { /* ... */ }
    int calc() { return result_; }
    Pow() : result_{1},base_{1},exp_{1} {} // sinnvoll initialisieren
};

Listing 12.24: Listing 12.24 Eigene Datentypen können vor Fehlern schützen — dies ist der erste Schritt dazu.

Book listing lst-0263-book.cpp:

// https://godbolt.org/z/r5EsnnsEG 
#include <string>       // string, stoi
#include <iostream>     // cin, cout, ostream
#include <format>
using std::ostream; using std::format;
class Year {  /* Hilfstypen für sicheres Datum */
    int value_; // z. B. 2024
public:
    Year(int v) : value_{v} {}
    int value() { return value_; }
};
class Month {
    int value_; // 1..12
public:
    Month(int v) : value_{v} {}
    int value() { return value_; }
};
class Day {
    int value_; // 1..31
public:
    Day(int v) : value_{v} {}
    int value() { return value_; }
};
/* typsicher konstruierendes Datum */
class Date {
    Year year_;
    Month month_ = 1;
    Day day_ = 1;
public:
    Date(int y) : year_{y}           // 1-Argument-Konstruktor
        {}                           // setzt 1. Januar des angegebenen Jahres
    Date(Year y, Month m, Day d)     // 3-Argument-Konstruktor
        : year_{y}, month_{m}, day_{d}
        {}
    ostream& print(ostream& os);     // z. B. 2024-04-20
};
ostream& Date::print(ostream& os) {  // z. B. 2024-04-20
    return os << format("{}-{:02}-{:02}",
        year_.value(), month_.value(), day_.value());
}
ostream& operator<<(ostream& os, Date d) {
    return d.print(os);
}
// http://codegolf.stackexchange.com/a/11146/1405, user Fors, 2014-02-25
Date ostern(Year year) {
    const int y = year.value();
    int a = y/100*1483 - y/400*2225 + 2613;
    int b = (y%19*3510 + a/25*319)/330%29;
    b = 148 - b - (y*5/4 + a - b)%7;
    return Date{Year{y}, Month{b/31}, Day{b%31 + 1}}; // Datum erzeugen
}
int main(int argc, const char *argv[] ) {
    /* Eingabe */
    int zahl {};
    if(argc > 1) {
        zahl = std::stoi(argv[1]);
    } else {
        std::cout << "Jahr? "; std::cin >> zahl;
    }
    /* Berechnung */
    Date date = ostern(zahl);  // implizite Konvertierung nach Year
    /* Ausgabe */
    std::cout << "Ostern: " << date << "\n";
}

Godbolt Listing lst-0263-godb.cpp, https://godbolt.org/z/r5EsnnsEG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r5EsnnsEG 
#include <string>       // string, stoi
#include <iostream>     // cin, cout, ostream
#include <format>
using std::ostream; using std::format;
class Year {  /* Hilfstypen für sicheres Datum */
    int value_; // z. B. 2024
public:
    Year(int v) : value_{v} {}
    int value() { return value_; }
};
class Month {
    int value_; // 1..12
public:
    Month(int v) : value_{v} {}
    int value() { return value_; }
};
class Day {
    int value_; // 1..31
public:
    Day(int v) : value_{v} {}
    int value() { return value_; }
};
/* typsicher konstruierendes Datum */
class Date {
    Year year_;
    Month month_ = 1;
    Day day_ = 1;
public:
    Date(int y) : year_{y}           // 1-Argument-Konstruktor
        {}                           // setzt 1. Januar des angegebenen Jahres
    Date(Year y, Month m, Day d)     // 3-Argument-Konstruktor
        : year_{y}, month_{m}, day_{d}
        {}
    ostream& print(ostream& os);     // z. B. 2024-04-20
};
ostream& Date::print(ostream& os) {  // z. B. 2024-04-20
    return os << format("{}-{:02}-{:02}",
        year_.value(), month_.value(), day_.value());
}
ostream& operator<<(ostream& os, Date d) {
    return d.print(os);
}
// http://codegolf.stackexchange.com/a/11146/1405, user Fors, 2014-02-25
Date ostern(Year year) {
    const int y = year.value();
    int a = y/100*1483 - y/400*2225 + 2613;
    int b = (y%19*3510 + a/25*319)/330%29;
    b = 148 - b - (y*5/4 + a - b)%7;
    return Date{Year{y}, Month{b/31}, Day{b%31 + 1}}; // Datum erzeugen
}
int main(int argc, const char *argv[] ) {
    /* Eingabe */
    int zahl {};
    if(argc > 1) {
        zahl = std::stoi(argv[1]);
    } else {
        std::cout << "Jahr? "; std::cin >> zahl;
    }
    /* Berechnung */
    Date date = ostern(zahl);  // implizite Konvertierung nach Year
    /* Ausgabe */
    std::cout << "Ostern: " << date << "\n";
}

Listing 12.25: Listing 12.25 Wenn alle »return«-Anweisungen dieselbe Variable zurückliefern, kann der Compiler eine Kopie immer vermeiden.

Book listing lst-0272-book.cpp:

// https://godbolt.org/z/T7afh4vxz 
#include <vector>
std::vector<int> createData(unsigned size) {
    std::vector<int> result{};
    for(int idx=0; idx<size; ++idx) {
        result.push_back(idx);
    }
    return result;
}

Godbolt Listing lst-0272-godb.cpp, https://godbolt.org/z/T7afh4vxz:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/T7afh4vxz 
#include <vector>
std::vector<int> createData(unsigned size) {
    std::vector<int> result{};
    for(int idx=0; idx<size; ++idx) {
        result.push_back(idx);
    }
    return result;
}

Listing 12.26: Listing 12.26 Mit »explicit« verhindern Sie automatische Typumwandlung.

Book listing lst-0281-book.cpp:

// jeweils nur Auszüge
class Year {
    explicit Year(int v) : value_{v} {}
};
class Month {
    explicit Month(int v) : value_{v} {}
};
class Day {
    explicit Day(int v) : value_{v} {}
};
class Date {
    explicit Date(int y) : year_{y} {}
};

Listing 12.27: Listing 12.27 »Year« hat nun kein »value()« mehr und benötigt dafür andere Methoden.

Book listing lst-0291-book.cpp:

// https://godbolt.org/z/EPz4Kd6jP 
class Year {
    int value_;
public:
    explicit Year(int v) : value_{v} {}
    std::ostream& print(std::ostream& os) const;
    Year& advance(const Year& other);
    bool equals(const Year& other) const;
    bool less_than(const Year& other) const;
};
std::ostream& Year::print(std::ostream& os) const {
    return os << value_;
}
std::ostream& operator<<(std::ostream& os, const Year& year) {
    return year.print(os);
}
Year& Year::advance(const Year& other) {
    value_ += other.value_;
    return *this;
}
bool Year::equals(const Year& other) const {
    return value_ == other.value_;
}
bool Year::less_than(const Year& other) const {
    return value_ < other.value_;
}

Godbolt Listing lst-0291-godb.cpp, https://godbolt.org/z/EPz4Kd6jP:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EPz4Kd6jP 
class Year {
    int value_;
public:
    explicit Year(int v) : value_{v} {}
    std::ostream& print(std::ostream& os) const;
    Year& advance(const Year& other);
    bool equals(const Year& other) const;
    bool less_than(const Year& other) const;
};
std::ostream& Year::print(std::ostream& os) const {
    return os << value_;
}
std::ostream& operator<<(std::ostream& os, const Year& year) {
    return year.print(os);
}
Year& Year::advance(const Year& other) {
    value_ += other.value_;
    return *this;
}
bool Year::equals(const Year& other) const {
    return value_ == other.value_;
}
bool Year::less_than(const Year& other) const {
    return value_ < other.value_;
}

Listing 12.28: Listing 12.28 Gibt »advance« das Objekt selbst zurück, können Sie danach eine weitere Methode aufrufen.

Book listing lst-0292-book.cpp:

Year year{2024};
year.advance(Year{1}).advance(Year{3});
cout << year; // Ausgabe: 2028

Listing 12.29: Listing 12.29 Eine fließende Programmierschnittstelle erlaubt zuweilen übersichtlichen Code.

Book listing lst-0293-book.cpp:

Page page = Html().body()
    .h1("Ueberschrift")
    .table().border(0)
      .tr()
        .td().css("head").text("Hunderasse").end()
        .td().text("Pudel").end()
      .end()
    .end()
    .toPage();

Listing 12.30: Listing 12.30 Der eigentlich interne Typ »int« ist Teil der Schnittstelle der Klasse geworden.

Book listing lst-0294-book.cpp:

// https://godbolt.org/z/sP3W8jx6E 
class Year {
    int value_;                         // eigentlich intern verwendeter Typ
public:
    explicit Year(int v) : value_{v} {} // Typ wird Teil des Interface
    int value() { return value_; }      // auch bei der Rückgabe
};
int main() {
   Year year{ 2024 };                   // Typ int
   int val = year.value();              // passender Typ
}

Godbolt Listing lst-0294-godb.cpp, https://godbolt.org/z/sP3W8jx6E:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sP3W8jx6E 
class Year {
    int value_;                         // eigentlich intern verwendeter Typ
public:
    explicit Year(int v) : value_{v} {} // Typ wird Teil des Interface
    int value() { return value_; }      // auch bei der Rückgabe
};
int main() {
   Year year{ 2024 };                   // Typ int
   int val = year.value();              // passender Typ
}

Listing 12.31: Listing 12.31 Mit »using« können Sie Typaliase einführen, mit denen sich Interfaces leichter pflegen lassen als mit den Typen selbst.

Book listing lst-0295-book.cpp:

// https://godbolt.org/z/r3xaPv5Mr 
class Year {
public:
    using value_type = int;             // Typalias einführen
    value_type value_;                  // eigentlich intern verwendeter Typ
public:
    explicit Year(value_type v) : value_{v} {}
    value_type value() { return value_; }
};
int main() {
   Year year{ 2024 };                   // hier auf Compilerkonvertierung zählen
   Year::value_type val = year.value(); // verwenden Sie ::
}

Godbolt Listing lst-0295-godb.cpp, https://godbolt.org/z/r3xaPv5Mr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r3xaPv5Mr 
class Year {
public:
    using value_type = int;             // Typalias einführen
    value_type value_;                  // eigentlich intern verwendeter Typ
public:
    explicit Year(value_type v) : value_{v} {}
    value_type value() { return value_; }
};
int main() {
   Year year{ 2024 };                   // hier auf Compilerkonvertierung zählen
   Year::value_type val = year.value(); // verwenden Sie ::
}

Listing 12.32: Listing 12.32 Auch die Standardbibliothek enthält viele praktische Typaliase.

Book listing lst-0296-book.cpp:

// https://godbolt.org/z/vjTWjfKKz 
#include <vector>
#include <set>
#include <iostream>
using std::vector; using std::set; using std::cout;
using vector_t = vector<unsigned long long>; // Ihr eigener Typalias
int main() {
    vector_t huge{ 12ULL, 10'000'000'000ULL, 9ULL, 0ULL,  };
    vector_t::size_type sz = huge.size();
    vector_t::value_type uiuiui = huge[1];
    for(vector_t::iterator it = huge.begin(); it != huge.end(); ++it)
        *it *= 2; // verdoppeln
    /* sortieren per set */
    set<vector_t::value_type> sortiert{huge.begin(), huge.end()};
    for(vector_t::value_type val : sortiert)
        cout << val << " ";
    cout << "\n";
}

Godbolt Listing lst-0296-godb.cpp, https://godbolt.org/z/vjTWjfKKz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vjTWjfKKz 
#include <vector>
#include <set>
#include <iostream>
using std::vector; using std::set; using std::cout;
using vector_t = vector<unsigned long long>; // Ihr eigener Typalias
int main() {
    vector_t huge{ 12ULL, 10'000'000'000ULL, 9ULL, 0ULL,  };
    vector_t::size_type sz = huge.size();
    vector_t::value_type uiuiui = huge[1];
    for(vector_t::iterator it = huge.begin(); it != huge.end(); ++it)
        *it *= 2; // verdoppeln
    /* sortieren per set */
    set<vector_t::value_type> sortiert{huge.begin(), huge.end()};
    for(vector_t::value_type val : sortiert)
        cout << val << " ";
    cout << "\n";
}

Listing 12.33: Listing 12.33 Bei der Initialisierung einer Variablen kann der Compiler den Typ ermitteln.

Book listing lst-0300-book.cpp:

// https://godbolt.org/z/Wh71cf7j1 
#include <vector>
#include <set>
#include <iostream> // cout
using std::vector; using std::set; using std::cout;
using vector_t = vector<unsigned long long>; // Ihr eigener Typalias
int main() {
    vector_t huge{ 12ULL, 10000000000ULL, 9ULL, 0ULL,  };
    auto sz = huge.size();
    auto uiuiui = huge[1];
    for(auto it = huge.begin(); it != huge.end(); ++it)
        *it *= 2; // verdoppeln
    /* sortieren per set */
    set sortiert(huge.begin(), huge.end());  // set<vector_t::value_type>
    for(auto val : sortiert)
        cout << val << " ";
    cout << "\n";
}

Godbolt Listing lst-0300-godb.cpp, https://godbolt.org/z/Wh71cf7j1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Wh71cf7j1 
#include <vector>
#include <set>
#include <iostream> // cout
using std::vector; using std::set; using std::cout;
using vector_t = vector<unsigned long long>; // Ihr eigener Typalias
int main() {
    vector_t huge{ 12ULL, 10000000000ULL, 9ULL, 0ULL,  };
    auto sz = huge.size();
    auto uiuiui = huge[1];
    for(auto it = huge.begin(); it != huge.end(); ++it)
        *it *= 2; // verdoppeln
    /* sortieren per set */
    set sortiert(huge.begin(), huge.end());  // set<vector_t::value_type>
    for(auto val : sortiert)
        cout << val << " ";
    cout << "\n";
}

Listing 12.34: Listing 12.34 Typ-Deduktion mit »auto« können Sie mit einem Concept weiter einschränken.

Book listing lst-0301-book.cpp:

// https://godbolt.org/z/hT8o3dqrK 
#include <vector>
#include <set>
#include <iostream> // cout
#include <concepts> // integral
#include <iterator> // output_iterator, input_iterator
using namespace std;
using vector_t = vector<unsigned long long>;        // Ihr eigener Typalias
int main() {
  vector_t huge{ 12ULL, 10000000000ULL, 9ULL, 0ULL,  };
  unsigned_integral auto sz = huge.size();
  unsigned_integral auto uiuiui = huge[1];
  signed_integral auto meh = huge[1];               //             (ERR)  Concept nicht erfüllt
  input_or_output_iterator auto itx = huge.begin(); // Concept ohne Parameter
  for(output_iterator<unsigned long long> auto i=huge.begin();
      it!=huge.end(); ++it)
    *it *= 2; // verdoppeln
  /* sortieren per set */
  set sortiert(huge.begin(), huge.end());           // set<vector_t::value_type>
  for(const unsigned_integral auto& val : sortiert)
    cout << val << " ";
  cout << "\n";
}

Godbolt Listing lst-0301-godb.cpp, https://godbolt.org/z/hT8o3dqrK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hT8o3dqrK 
#include <vector>
#include <set>
#include <iostream> // cout
#include <concepts> // integral
#include <iterator> // output_iterator, input_iterator
using namespace std;
using vector_t = vector<unsigned long long>;        // Ihr eigener Typalias
int main() {
  vector_t huge{ 12ULL, 10000000000ULL, 9ULL, 0ULL,  };
  unsigned_integral auto sz = huge.size();
  unsigned_integral auto uiuiui = huge[1];
  signed_integral auto meh = huge[1];               //             (ERR)  Concept nicht erfüllt
  input_or_output_iterator auto itx = huge.begin(); // Concept ohne Parameter
  for(output_iterator<unsigned long long> auto i=huge.begin();
      it!=huge.end(); ++it)
    *it *= 2; // verdoppeln
  /* sortieren per set */
  set sortiert(huge.begin(), huge.end());           // set<vector_t::value_type>
  for(const unsigned_integral auto& val : sortiert)
    cout << val << " ";
  cout << "\n";
}

Listing 12.35: Listing 12.35 Wenn Sie »auto« mit »&« anreichern, erhalten Sie eine veränderbare Referenz.

Book listing lst-0302-book.cpp:

// https://godbolt.org/z/ro6fdsvT9 
#include <vector>
#include <iostream> // cout
using std::vector; using std::cout;
int main() {
    vector data{ 12, 100, -1, 0,  };    // vector<int>
    for(auto& val : data)
        val *= 2; // verdoppeln
    for(const auto val : data)
        cout << val << " ";
    cout << "\n";
}

Godbolt Listing lst-0302-godb.cpp, https://godbolt.org/z/ro6fdsvT9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ro6fdsvT9 
#include <vector>
#include <iostream> // cout
using std::vector; using std::cout;
int main() {
    vector data{ 12, 100, -1, 0,  };    // vector<int>
    for(auto& val : data)
        val *= 2; // verdoppeln
    for(const auto val : data)
        cout << val << " ";
    cout << "\n";
}

Listing 12.36: Listing 12.36 Um einen eigenen Datentyp in einen »vector« zu packen, muss dieser nicht viele Bedingungen erfüllen.

Book listing lst-0306-book.cpp:

// https://godbolt.org/z/8ejPs6zr6 
#include <vector>
struct Zahl {
    int wert_ = 0;
    Zahl() {} // Standardkonstruktor
    explicit Zahl(int w) : wert_{w} {}
};
int main() {
    std::vector<Zahl> zahlen{}; // okay: Zahl erfüllt die Bedingungen
    zahlen.push_back( Zahl{2} );
}

Godbolt Listing lst-0306-godb.cpp, https://godbolt.org/z/8ejPs6zr6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8ejPs6zr6 
#include <vector>
struct Zahl {
    int wert_ = 0;
    Zahl() {} // Standardkonstruktor
    explicit Zahl(int w) : wert_{w} {}
};
int main() {
    std::vector<Zahl> zahlen{}; // okay: Zahl erfüllt die Bedingungen
    zahlen.push_back( Zahl{2} );
}

Listing 12.37: Listing 12.37 Für einen »set« eines eigenen Datentyps müssen Sie »operator<« überschreiben.

Book listing lst-0307-book.cpp:

// https://godbolt.org/z/vrdKPvh7f 
#include <set>
struct Zahl {
    int wert_ = 0;
    explicit Zahl(int w) : wert_{w} {}
};
bool operator<(const Zahl& links, const Zahl& rechts) {
    return links.wert_ < rechts.wert_;
}
int main() {
    std::set<Zahl> zahlen{};  // okay
    zahlen.insert( Zahl{3} ); // hier wird operator< gebraucht
}

Godbolt Listing lst-0307-godb.cpp, https://godbolt.org/z/vrdKPvh7f:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vrdKPvh7f 
#include <set>
struct Zahl {
    int wert_ = 0;
    explicit Zahl(int w) : wert_{w} {}
};
bool operator<(const Zahl& links, const Zahl& rechts) {
    return links.wert_ < rechts.wert_;
}
int main() {
    std::set<Zahl> zahlen{};  // okay
    zahlen.insert( Zahl{3} ); // hier wird operator< gebraucht
}

GodboltId:M81MjePh5

Book listing lst-0308-book.cpp:

// https://godbolt.org/z/M81MjePh5 
#include <map>

struct Zahl {
    int wert_ = 0;
    explicit Zahl(int w) : wert_{w} {}
};

bool operator<(const Zahl& links, const Zahl& rechts) {
    return links.wert_ < rechts.wert_;
}

int main() {
    std::map<Zahl,int> zahlen{};                  // okay
    zahlen.insert( std::make_pair(Zahl{4},100) ); // braucht operator<
    zahlen[Zahl{5}] = 200;                        // hier ebenfalls
}

Godbolt Listing lst-0308-godb.cpp, https://godbolt.org/z/M81MjePh5:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M81MjePh5 
#include <map>

struct Zahl {
    int wert_ = 0;
    explicit Zahl(int w) : wert_{w} {}
};

bool operator<(const Zahl& links, const Zahl& rechts) {
    return links.wert_ < rechts.wert_;
}

int main() {
    std::map<Zahl,int> zahlen{};                  // okay
    zahlen.insert( std::make_pair(Zahl{4},100) ); // braucht operator<
    zahlen[Zahl{5}] = 200;                        // hier ebenfalls
}

Listing 13.1: Sie definieren einen Namensraum mit »namespace«.

Book listing lst-0311-book.cpp:

// https://godbolt.org/z/T1ohsxbje 
#include <string>
#include <iostream>                    // ostream, cout
namespace plant {
    class Baum {
        std::string name_;
    public:
        explicit Baum(const std::string_view name) : name_{name} {}
        void print(std::ostream& os) const { os << name_; }
    };
    std::ostream& operator<<(std::ostream& os, const Baum& arg)
        { arg.print(os); return os; }
    using NadelBaum = Baum;            // für spätere Erweiterungen …
    using LaubBaum = Baum;             // … vorsorgen
    namespace beispielnamen {          // eingebetteter Namensraum
        std::string eicheName = "Eiche";
        std::string bucheName = "Buche";
        std::string tanneName = "Tanne";
    } // Ende namespace beispielnamen
} // Ende namespace plant

int main() {  // main darf nicht in einem Namespace stehen
    using namespace plant::beispielnamen; // alle Beispielnamen verfügbar machen
    plant::NadelBaum tanne{ tanneName };
    plant::LaubBaum eiche{ eicheName };
    tanne.print(std::cout); std::cout << "\n";
    using plant::operator<<;           // ohne geht 'cout << eiche' nicht
    std::cout << eiche << "\n";
}

Godbolt Listing lst-0311-godb.cpp, https://godbolt.org/z/T1ohsxbje:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/T1ohsxbje 
#include <string>
#include <iostream>                    // ostream, cout
namespace plant {
    class Baum {
        std::string name_;
    public:
        explicit Baum(const std::string_view name) : name_{name} {}
        void print(std::ostream& os) const { os << name_; }
    };
    std::ostream& operator<<(std::ostream& os, const Baum& arg)
        { arg.print(os); return os; }
    using NadelBaum = Baum;            // für spätere Erweiterungen …
    using LaubBaum = Baum;             // … vorsorgen
    namespace beispielnamen {          // eingebetteter Namensraum
        std::string eicheName = "Eiche";
        std::string bucheName = "Buche";
        std::string tanneName = "Tanne";
    } // Ende namespace beispielnamen
} // Ende namespace plant

int main() {  // main darf nicht in einem Namespace stehen
    using namespace plant::beispielnamen; // alle Beispielnamen verfügbar machen
    plant::NadelBaum tanne{ tanneName };
    plant::LaubBaum eiche{ eicheName };
    tanne.print(std::cout); std::cout << "\n";
    using plant::operator<<;           // ohne geht 'cout << eiche' nicht
    std::cout << eiche << "\n";
}

Listing 13.2: In getrennten Namensräumen können Sie die gleichen Operatoren definieren.

Book listing lst-0315-book.cpp:

namespace plant {
    // … wie zuvor …
    std::ostream& operator<<(std::ostream&, const Baum&) {};
    namespace debug {
        std::ostream& operator<<(std::ostream&, const Baum&) {};
    }
}
plant::Baum baum{"MeinBaum"};
void run() {
    using namespace plant;
    cout << baum << "\n";
}
void diagnostic() {
    using namespace plant::debug;
    cout << baum << "\n";
}
int main() {
    run();
    diagnostic();
}

Listing 13.3: Ein anonymer Namensraum macht Definitionen lokal für die aktuelle Datei.

Book listing lst-0316-book.cpp:

// https://godbolt.org/z/M6EnPT3Gr 
// modul.hpp
#include <string>
#include <iostream>
namespace plant {
    class Baum {
        std::string name_;
    public:
        explicit Baum(const std::string_view name);
        void print(std::ostream& os) const;
    };
    std::ostream& operator<<(std::ostream& os, const Baum& arg);
}
// modul.cpp
#include "modul.hpp"
namespace {  // anonymer Namensraum
    std::string PREFIX = "BAUM:";
    void printInfo(std::ostream& os) {
        os << "Autor: Torsten T. Will\n";
    }
}
bool debug = false;  // global, kein Namensraum
namespace plant {
    Baum::Baum(const std::string_view name)
        : name_{name} {}
    void Baum::print(std::ostream& os) const {
        os << PREFIX << name_;
    }
    std::ostream& operator<<(std::ostream& os, const Baum& arg) {
        if(debug) printInfo(os);
        arg.print(os); return os;
    }
}
// main.cpp
#include "modul.hpp"
int main() {
    plant::Baum x{"x"};
    x.print(std::cout); std::cout << "\n";
}

Godbolt Listing lst-0316-godb.cpp, https://godbolt.org/z/M6EnPT3Gr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M6EnPT3Gr 
// modul.hpp
#include <string>
#include <iostream>
namespace plant {
    class Baum {
        std::string name_;
    public:
        explicit Baum(const std::string_view name);
        void print(std::ostream& os) const;
    };
    std::ostream& operator<<(std::ostream& os, const Baum& arg);
}
// modul.cpp
#include "modul.hpp"
namespace {  // anonymer Namensraum
    std::string PREFIX = "BAUM:";
    void printInfo(std::ostream& os) {
        os << "Autor: Torsten T. Will\n";
    }
}
bool debug = false;  // global, kein Namensraum
namespace plant {
    Baum::Baum(const std::string_view name)
        : name_{name} {}
    void Baum::print(std::ostream& os) const {
        os << PREFIX << name_;
    }
    std::ostream& operator<<(std::ostream& os, const Baum& arg) {
        if(debug) printInfo(os);
        arg.print(os); return os;
    }
}
// main.cpp
#include "modul.hpp"
int main() {
    plant::Baum x{"x"};
    x.print(std::cout); std::cout << "\n";
}

GodboltId:cTYhMfo5W

Book listing lst-0317-book.cpp:

// https://godbolt.org/z/cTYhMfo5W 
// modul.cpp
#include "modul.hpp"
static std::string PREFIX = "BAUM:";
static void printInfo(std::ostream& os) {
    os << "Autor: Torsten T. Will\n";
}
bool debug = false;
// Rest wie bisher

Godbolt Listing lst-0317-godb.cpp, https://godbolt.org/z/cTYhMfo5W:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cTYhMfo5W 
// modul.cpp
#include "modul.hpp"
static std::string PREFIX = "BAUM:";
static void printInfo(std::ostream& os) {
    os << "Autor: Torsten T. Will\n";
}
bool debug = false;
// Rest wie bisher

Listing 13.4: Alle Instanzen teilen sich ihre »static«-Datenfelder und -Methoden.

Book listing lst-0319-book.cpp:

// https://godbolt.org/z/n4e8xdEGj 
#include <iostream> // cout
#include <string>
using std::string;
class Tree {
    static size_t countConstructed_;
    static size_t countDestructed_;
    string kind_;
    Tree(string kind) : kind_{kind}      // privater Konstruktor
        { ++countConstructed_; }
public:
    Tree(const Tree& o) : kind_{o.kind_}
        { ++countConstructed_; }
    string getKind() const { return kind_; }
    ~Tree() { ++countDestructed_; }
    static Tree create(string kind) { return Tree{kind}; }
    static void stats(std::ostream& os) {
        os << "Constructed:+" << countConstructed_
           << " Destructed:-" << countDestructed_ << "\n";
    }
};
size_t Tree::countConstructed_ = 0;
size_t Tree::countDestructed_ = 0;
int main() {
    Tree birke = Tree::create("Birke");
    for(auto kind : {"Esche", "Eibe", "Eiche"}) {
        Tree temp = Tree::create(kind);
        std::cout << temp.getKind() << "\n";
    }
    Tree::stats(std::cout);
}

Godbolt Listing lst-0319-godb.cpp, https://godbolt.org/z/n4e8xdEGj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n4e8xdEGj 
#include <iostream> // cout
#include <string>
using std::string;
class Tree {
    static size_t countConstructed_;
    static size_t countDestructed_;
    string kind_;
    Tree(string kind) : kind_{kind}      // privater Konstruktor
        { ++countConstructed_; }
public:
    Tree(const Tree& o) : kind_{o.kind_}
        { ++countConstructed_; }
    string getKind() const { return kind_; }
    ~Tree() { ++countDestructed_; }
    static Tree create(string kind) { return Tree{kind}; }
    static void stats(std::ostream& os) {
        os << "Constructed:+" << countConstructed_
           << " Destructed:-" << countDestructed_ << "\n";
    }
};
size_t Tree::countConstructed_ = 0;
size_t Tree::countDestructed_ = 0;
int main() {
    Tree birke = Tree::create("Birke");
    for(auto kind : {"Esche", "Eibe", "Eiche"}) {
        Tree temp = Tree::create(kind);
        std::cout << temp.getKind() << "\n";
    }
    Tree::stats(std::cout);
}

GodboltId:b9arcEMM1

Book listing lst-0321-book.cpp:

// https://godbolt.org/z/b9arcEMM1 
constinit auto SZ = 10*1000-1;                 // globale Variable
size_t autoincrement() {
    static constinit size_t i = 0;             // lokale statische Variable
    return i++;
}
class BraitenbergVehicle {
    inline static constinit size_t count_ = 0; // Klassenvariable
public:
    size_t id_;
    BraitenbergVehicle() : id_{++count_} {}
    ~BraitenbergVehicle() { --count_; }
};

Godbolt Listing lst-0321-godb.cpp, https://godbolt.org/z/b9arcEMM1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/b9arcEMM1 
constinit auto SZ = 10*1000-1;                 // globale Variable
size_t autoincrement() {
    static constinit size_t i = 0;             // lokale statische Variable
    return i++;
}
class BraitenbergVehicle {
    inline static constinit size_t count_ = 0; // Klassenvariable
public:
    size_t id_;
    BraitenbergVehicle() : id_{++count_} {}
    ~BraitenbergVehicle() { --count_; }
};

Listing 13.5: Eine lokale statische Variable wird einmal initialisiert und danach wiederverwendet.

Book listing lst-0322-book.cpp:

// https://godbolt.org/z/h5qond6db 
#include <iostream>                     // cout
class Keyboard {
    Keyboard(const Keyboard&) = delete; // keine Kopie
    const size_t nr_;                   // aktuelle Nummer
public:
    static inline size_t count_ = 0;    // zählt erzeugte Instanzen
    explicit Keyboard() : nr_{count_++} {
        std::cout << "  Keyboard().nr:"<<nr_<<"\n";
    }
};
Keyboard& getKeyboard() {
    std::cout << "  getKeyboard()\n";
    static Keyboard keyboard{};         // statische lokale Variable
    return keyboard;
}
void func() {
    std::cout << "kbFunc...\n";
    Keyboard& kbFunc = getKeyboard();
}
int main() {
    std::cout << "kbA...\n";
    Keyboard& kbA = getKeyboard();
    func();
    std::cout << "kbB...\n";
    Keyboard& kbB = getKeyboard();
    std::cout << "count:" << Keyboard::count_ << "\n";
}

Godbolt Listing lst-0322-godb.cpp, https://godbolt.org/z/h5qond6db:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h5qond6db 
#include <iostream>                     // cout
class Keyboard {
    Keyboard(const Keyboard&) = delete; // keine Kopie
    const size_t nr_;                   // aktuelle Nummer
public:
    static inline size_t count_ = 0;    // zählt erzeugte Instanzen
    explicit Keyboard() : nr_{count_++} {
        std::cout << "  Keyboard().nr:"<<nr_<<"\n";
    }
};
Keyboard& getKeyboard() {
    std::cout << "  getKeyboard()\n";
    static Keyboard keyboard{};         // statische lokale Variable
    return keyboard;
}
void func() {
    std::cout << "kbFunc...\n";
    Keyboard& kbFunc = getKeyboard();
}
int main() {
    std::cout << "kbA...\n";
    Keyboard& kbA = getKeyboard();
    func();
    std::cout << "kbB...\n";
    Keyboard& kbB = getKeyboard();
    std::cout << "count:" << Keyboard::count_ << "\n";
}

Listing 13.6: Das Meyers-Singleton

Book listing lst-0323-book.cpp:

Keyboard& getKeyboard() {
    cout << "  getKeyboard()\n";
    static Keyboard keyboard{}; // statische lokale Variable
    return keyboard;
}

Listing 13.7: Die Bezeichner eines inline namespace gehen zusätzlich in seinen umgebenden Namensraum.

Book listing lst-0324-book.cpp:

// https://godbolt.org/z/115M1csEE 
#include <iostream>
namespace mylib {
    namespace v1 {
        int version() { return 1; }
    }
    inline namespace v2 { // aktuelle Version
        int version() { return 2; }
    }
}

int main() {
    std::cout << "Version " << mylib::version() << "\n";     // Ausgabe: 2
    std::cout << "Version " << mylib::v1::version() << "\n"; // Ausgabe: 1
    std::cout << "Version " << mylib::v2::version() << "\n"; // Ausgabe: 2
}

Godbolt Listing lst-0324-godb.cpp, https://godbolt.org/z/115M1csEE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/115M1csEE 
#include <iostream>
namespace mylib {
    namespace v1 {
        int version() { return 1; }
    }
    inline namespace v2 { // aktuelle Version
        int version() { return 2; }
    }
}

int main() {
    std::cout << "Version " << mylib::version() << "\n";     // Ausgabe: 2
    std::cout << "Version " << mylib::v1::version() << "\n"; // Ausgabe: 1
    std::cout << "Version " << mylib::v2::version() << "\n"; // Ausgabe: 2
}

GodboltId:WTWxYa3rd

Book listing lst-0334-book.cpp:

// https://godbolt.org/z/WTWxYa3rd 
class Widget {
    unsigned x = 0, y = 0, w = 0, h = 0; // zum Beispiel
public:
    unsigned getLeft() const;
    unsigned getTop() const;
    unsigned getRight() const;
    unsigned getBottom() const;
    void setWidth(unsigned w);
    void setHeight(unsigned h);
};

Godbolt Listing lst-0334-godb.cpp, https://godbolt.org/z/WTWxYa3rd:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WTWxYa3rd 
class Widget {
    unsigned x = 0, y = 0, w = 0, h = 0; // zum Beispiel
public:
    unsigned getLeft() const;
    unsigned getTop() const;
    unsigned getRight() const;
    unsigned getBottom() const;
    void setWidth(unsigned w);
    void setHeight(unsigned h);
};

Listing 13.8: Lokale Konstanten einer Datei passen gut in einen anonymen Namensraum.

Book listing lst-0339-book.cpp:

// https://godbolt.org/z/q3Ga7hTGa 
#include <vector>
namespace {                         // anonymer Namensraum für Konstanten
    const unsigned DATA_SIZE = 100; /* Anzahl Elemente in Data */
    const double LIMIT = 999.999;   /* Maxwert bei Initialisierung */
};
std::vector<int> createData() {
    std::vector<int> result(DATA_SIZE);
    double currVal = 1.0;
    for(auto &elem : result) {
        elem = currVal;
        currVal *= 2;         // nächster Wert ist größer
        if(currVal > LIMIT) {
            currVal = LIMIT;  // kein Wert darf größer sein
        }
    }
    return result;
}

Godbolt Listing lst-0339-godb.cpp, https://godbolt.org/z/q3Ga7hTGa:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/q3Ga7hTGa 
#include <vector>
namespace {                         // anonymer Namensraum für Konstanten
    const unsigned DATA_SIZE = 100; /* Anzahl Elemente in Data */
    const double LIMIT = 999.999;   /* Maxwert bei Initialisierung */
};
std::vector<int> createData() {
    std::vector<int> result(DATA_SIZE);
    double currVal = 1.0;
    for(auto &elem : result) {
        elem = currVal;
        currVal *= 2;         // nächster Wert ist größer
        if(currVal > LIMIT) {
            currVal = LIMIT;  // kein Wert darf größer sein
        }
    }
    return result;
}

GodboltId:9Esx13h9r

Book listing lst-0340-book.cpp:

// https://godbolt.org/z/9Esx13h9r 
struct Widget {
    int num_ = 0;
    void setNumber(int x) {    // eine Nicht-const-Methode
        num_=x;
    }
};
Widget createWidget() {        // Rückgabe als Wert
    Widget result{};           // Erzeugen
    return result;
}
int main() {
    Widget w = createWidget(); // Rückgabe als Wert erzeugt Kopie
    w.setNumber(100);          // verändern, natürlich okay, w ist nicht-const
}

Godbolt Listing lst-0340-godb.cpp, https://godbolt.org/z/9Esx13h9r:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9Esx13h9r 
struct Widget {
    int num_ = 0;
    void setNumber(int x) {    // eine Nicht-const-Methode
        num_=x;
    }
};
Widget createWidget() {        // Rückgabe als Wert
    Widget result{};           // Erzeugen
    return result;
}
int main() {
    Widget w = createWidget(); // Rückgabe als Wert erzeugt Kopie
    w.setNumber(100);          // verändern, natürlich okay, w ist nicht-const
}

Listing 13.9: Obwohl der Rückgabetyp hier mit »const« markiert ist, wirkt es sich nicht aus, denn es wird immer kopiert.

Book listing lst-0341-book.cpp:

// https://godbolt.org/z/erv34b67c 
const Widget createWidget() {  // Rückgabe als const-Wert
    Widget result{};
    return result;
}
int main() {
    Widget w = createWidget(); // kopiert in neues nicht-const w
    w.setNumber(100);          // w ist nicht-const, verändern ist okay
}

Godbolt Listing lst-0341-godb.cpp, https://godbolt.org/z/erv34b67c:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/erv34b67c 
const Widget createWidget() {  // Rückgabe als const-Wert
    Widget result{};
    return result;
}
int main() {
    Widget w = createWidget(); // kopiert in neues nicht-const w
    w.setNumber(100);          // w ist nicht-const, verändern ist okay
}

Listing 13.10: Konstante Referenzen in Rückgaben

Book listing lst-0342-book.cpp:

// https://godbolt.org/z/v1TP6aYxT 
#include <string>
#include <string_view>
using std::string; using std::string_view;
class Widget {
    string name_ = "";
public:
    void setName(string_view newName) {
        name_ = newName;
    }
    const string& getName() const {    // const&-Rückgabe
        return name_;
    }
};
int main() {
    Widget w{};
    w.setName("Titel");
    string name1 = w.getName();        // neuer String, also Kopie
    name1.clear();                     // die Kopie dürfen Sie wieder verändern
    const string& name2 = w.getName(); // const-Referenz auf inneren string name_
    /* name2.clear(); */                   // name2 ist const, geht also nicht
    string& name3 = w.getName();       //                 (ERR)  Funktion gibt const& zurück, nicht &.
    auto name4 = w.getName();          // identisch mit name1
    const auto& name5 = w.getName();   // identisch mit name2
}

Godbolt Listing lst-0342-godb.cpp, https://godbolt.org/z/v1TP6aYxT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/v1TP6aYxT 
#include <string>
#include <string_view>
using std::string; using std::string_view;
class Widget {
    string name_ = "";
public:
    void setName(string_view newName) {
        name_ = newName;
    }
    const string& getName() const {    // const&-Rückgabe
        return name_;
    }
};
int main() {
    Widget w{};
    w.setName("Titel");
    string name1 = w.getName();        // neuer String, also Kopie
    name1.clear();                     // die Kopie dürfen Sie wieder verändern
    const string& name2 = w.getName(); // const-Referenz auf inneren string name_
    /* name2.clear(); */                   // name2 ist const, geht also nicht
    string& name3 = w.getName();       //                 (ERR)  Funktion gibt const& zurück, nicht &.
    auto name4 = w.getName();          // identisch mit name1
    const auto& name5 = w.getName();   // identisch mit name2
}

Listing 13.11: Referenzen können konstant und nicht konstant zurückgegeben werden.

Book listing lst-0343-book.cpp:

// https://godbolt.org/z/rMrKbrdWe 
#include <string>
#include <iostream>
using std::string; using std::cout;

class Widget {
    string name_{};
public:
    const string& readName() const;        // const&-Rückgabe, const-Methode
    string& getName();                     // &-Rückgabe
};

const string& Widget::readName() const { return name_; }
string& Widget::getName() { return name_; }

int main() {
    Widget w{};
    const string& readonly = w.readName(); // const&, unveränderbar
    cout << "Name: " << readonly << "\n";  // noch "" leer.
    string& readwrite = w.getName();       // &, veränderbar
    readwrite.append("dran");       // verändert auch name_ und readonly
    cout << "Name per readwrite: " << readwrite << "\n"; // "dran"
    cout << "Name per readonly: " << readonly << "\n";   // auch "dran"
}

Godbolt Listing lst-0343-godb.cpp, https://godbolt.org/z/rMrKbrdWe:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rMrKbrdWe 
#include <string>
#include <iostream>
using std::string; using std::cout;

class Widget {
    string name_{};
public:
    const string& readName() const;        // const&-Rückgabe, const-Methode
    string& getName();                     // &-Rückgabe
};

const string& Widget::readName() const { return name_; }
string& Widget::getName() { return name_; }

int main() {
    Widget w{};
    const string& readonly = w.readName(); // const&, unveränderbar
    cout << "Name: " << readonly << "\n";  // noch "" leer.
    string& readwrite = w.getName();       // &, veränderbar
    readwrite.append("dran");       // verändert auch name_ und readonly
    cout << "Name per readwrite: " << readwrite << "\n"; // "dran"
    cout << "Name per readonly: " << readonly << "\n";   // auch "dran"
}

GodboltId:hsWrnaEea

Book listing lst-0346-book.cpp:

// https://godbolt.org/z/hsWrnaEea 
namespace {
    const int MAX_A = 12;       // das Gleiche wie MAX_B, aber kein static nötig
}
static const int MAX_B = 10;    // im globalen Namensraum
struct Data {
    static const int SIZE = 14; // als Datenfeld in einer Klasse
}

void func() {
    static const int LIMIT =16; // als lokale Konstante
}

Godbolt Listing lst-0346-godb.cpp, https://godbolt.org/z/hsWrnaEea:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hsWrnaEea 
namespace {
    const int MAX_A = 12;       // das Gleiche wie MAX_B, aber kein static nötig
}
static const int MAX_B = 10;    // im globalen Namensraum
struct Data {
    static const int SIZE = 14; // als Datenfeld in einer Klasse
}

void func() {
    static const int LIMIT =16; // als lokale Konstante
}

Listing 13.12: Manche Ausdrücke müssen zur Übersetzungszeit bekannt sein.

Book listing lst-0347-book.cpp:

// https://godbolt.org/z/5b3bvKd9r 
#include <array>
int main() {

    std::array<int, 5> arr5{};     // Literal und somit ein konstanter Ausdruck
    std::array<int, 2+3> arr23{};  // 2+3 kann der Compiler auswerten

    const size_t SIZE = 5;         // definiert eine Konstante
    std::array<int, SIZE> arrSC{}; // kann der Compiler verwenden — oft
    size_t size = 7;

    std::array<int,size> arrVar{}; // eine Variable können Sie nicht verwenden
}

Godbolt Listing lst-0347-godb.cpp, https://godbolt.org/z/5b3bvKd9r:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5b3bvKd9r 
#include <array>
int main() {

    std::array<int, 5> arr5{};     // Literal und somit ein konstanter Ausdruck
    std::array<int, 2+3> arr23{};  // 2+3 kann der Compiler auswerten

    const size_t SIZE = 5;         // definiert eine Konstante
    std::array<int, SIZE> arrSC{}; // kann der Compiler verwenden — oft
    size_t size = 7;

    std::array<int,size> arrVar{}; // eine Variable können Sie nicht verwenden
}

Listing 13.13: Ob der Compiler eine Konstante in einem konstanten Ausdruck verwenden kann, ist nicht immer sofort ersichtlich.

Book listing lst-0348-book.cpp:

// https://godbolt.org/z/MEGfeanPP 
#include <array>
struct Data {
    static const size_t SPAET;            // Konstante deklarieren
    static const size_t FRUEH;            // Konstante deklarieren
};

void func() {
    int x = Data::SPAET;                  // Konstante verwenden
}

const size_t Data::FRUEH = 10;            // Konstante definieren

std::array<int, Data::FRUEH> arrFRUEH {}; // Konstante verwenden
std::array<int, Data::SPAET> arrSPAET {}; //                 (ERR)  Konstante verwenden
const size_t Data::SPAET = 10;            // Konstante definieren

int main() {
    func();
}

Godbolt Listing lst-0348-godb.cpp, https://godbolt.org/z/MEGfeanPP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MEGfeanPP 
#include <array>
struct Data {
    static const size_t SPAET;            // Konstante deklarieren
    static const size_t FRUEH;            // Konstante deklarieren
};

void func() {
    int x = Data::SPAET;                  // Konstante verwenden
}

const size_t Data::FRUEH = 10;            // Konstante definieren

std::array<int, Data::FRUEH> arrFRUEH {}; // Konstante verwenden
std::array<int, Data::SPAET> arrSPAET {}; //                 (ERR)  Konstante verwenden
const size_t Data::SPAET = 10;            // Konstante definieren

int main() {
    func();
}

Listing 13.14: Mit »constexpr« sieht der Compiler, wann ein Ausdruck nicht früh berechenbar ist.

Book listing lst-0350-book.cpp:

// https://godbolt.org/z/ba9rv6P51 
struct Data {
    static constexpr size_t SPAET; //                 (ERR)  klappt nicht ohne direkte Initialisierung
    static constexpr size_t FRUEH = 10;
};
constexpr size_t Data::SPAET = 10; //                 (ERR)  bei constexpr geht Definition nicht wie bei const

Godbolt Listing lst-0350-godb.cpp, https://godbolt.org/z/ba9rv6P51:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ba9rv6P51 
struct Data {
    static constexpr size_t SPAET; //                 (ERR)  klappt nicht ohne direkte Initialisierung
    static constexpr size_t FRUEH = 10;
};
constexpr size_t Data::SPAET = 10; //                 (ERR)  bei constexpr geht Definition nicht wie bei const

GodboltId:Krjh8M3aP

Book listing lst-0351-book.cpp:

// https://godbolt.org/z/Krjh8M3aP 
constexpr size_t verdoppleWennZuKlein1(size_t wert) {
   return wert < 100 ? wert*2 : wert; // liefert das Doppelte zurück, wenn kleiner 100
}
std::array<int, verdoppleWennZuKlein1(50)> arr {};

Godbolt Listing lst-0351-godb.cpp, https://godbolt.org/z/Krjh8M3aP:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Krjh8M3aP 
constexpr size_t verdoppleWennZuKlein1(size_t wert) {
   return wert < 100 ? wert*2 : wert; // liefert das Doppelte zurück, wenn kleiner 100
}
std::array<int, verdoppleWennZuKlein1(50)> arr {};

GodboltId:KPc6ExMaY

Book listing lst-0352-book.cpp:

// https://godbolt.org/z/KPc6ExMaY 
const size_t verdoppleWennZuKlein2(size_t wert) {
    return wert < 100 ? wert*2 : wert;
}
std::array<int, verdoppleWennZuKlein2(50)> arr {}; //                     (ERR)  nicht konstant genug

Godbolt Listing lst-0352-godb.cpp, https://godbolt.org/z/KPc6ExMaY:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KPc6ExMaY 
const size_t verdoppleWennZuKlein2(size_t wert) {
    return wert < 100 ? wert*2 : wert;
}
std::array<int, verdoppleWennZuKlein2(50)> arr {}; //                     (ERR)  nicht konstant genug

Listing 13.15: Mit »if constexpr« können Sie zur Übersetzungszeit entscheiden, welcher Code ausgeführt wird.

Book listing lst-0354-book.cpp:

// https://godbolt.org/z/zMbnYzo17 
template<typename T>
auto deref(T t) {
    if constexpr (std::is_pointer_v<T>) {
        return *t;
    } else {
        return t;
    }
}
int main() {
    int i = 42;
    std::cout << deref(i) << '\n';         // direkt der Wert
    auto p = std::make_unique<int>(73);
    std::cout << deref(p.get()) << '\n';   // dereferenzierter Pointer
}

Godbolt Listing lst-0354-godb.cpp, https://godbolt.org/z/zMbnYzo17:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zMbnYzo17 
template<typename T>
auto deref(T t) {
    if constexpr (std::is_pointer_v<T>) {
        return *t;
    } else {
        return t;
    }
}
int main() {
    int i = 42;
    std::cout << deref(i) << '\n';         // direkt der Wert
    auto p = std::make_unique<int>(73);
    std::cout << deref(p.get()) << '\n';   // dereferenzierter Pointer
}

Listing 13.16: »if constexpr« funktioniert auch mit »else«

Book listing lst-0355-book.cpp:

// https://godbolt.org/z/eo468MvMo 
#include <iostream>
#include <string>
struct S {
   int n;
   std::string s;
   float d;
};
template <std::size_t N> auto& get(S& s) {
    if constexpr (N == 0) return s.n;
    else if constexpr (N == 1) return s.s;
    else if constexpr (N == 2) return s.d;
}
int main() {
    S obj { 0, "hello", 10.0f };
    std::cout << get<0>(obj) << ", " << get<1>(obj) << "\n"; // Ausgabe: 0, hello
}

Godbolt Listing lst-0355-godb.cpp, https://godbolt.org/z/eo468MvMo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eo468MvMo 
#include <iostream>
#include <string>
struct S {
   int n;
   std::string s;
   float d;
};
template <std::size_t N> auto& get(S& s) {
    if constexpr (N == 0) return s.n;
    else if constexpr (N == 1) return s.s;
    else if constexpr (N == 2) return s.d;
}
int main() {
    S obj { 0, "hello", 10.0f };
    std::cout << get<0>(obj) << ", " << get<1>(obj) << "\n"; // Ausgabe: 0, hello
}

GodboltId:44KMf1fWr

Book listing lst-0356-book.cpp:

// https://godbolt.org/z/44KMf1fWr 
template<auto N>
constexpr auto fibonacci()    {
    if constexpr (N>=2) {
        return fibonacci<N-1>() + fibonacci<N-2>();
    } else {
        return N;
    }
}

int main() {
    std::cout << fibonacci<10>() << '\n';  // Ausgabe: 55
    std::cout << fibonacci<20>() << '\n';  // Ausgabe: 6765
}

Godbolt Listing lst-0356-godb.cpp, https://godbolt.org/z/44KMf1fWr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/44KMf1fWr 
template<auto N>
constexpr auto fibonacci()    {
    if constexpr (N>=2) {
        return fibonacci<N-1>() + fibonacci<N-2>();
    } else {
        return N;
    }
}

int main() {
    std::cout << fibonacci<10>() << '\n';  // Ausgabe: 55
    std::cout << fibonacci<20>() << '\n';  // Ausgabe: 6765
}

Listing 13.17: Mit »consteval« können Sie Funktionen zur Übersetzungszeit ausführen lassen.

Book listing lst-0357-book.cpp:

// https://godbolt.org/z/8rr4WKo8d 
int hole_eingabe() {
    return 50; // oder lese was aus einer Datei oder so
}
constexpr auto berechne_1(int eingabe) {
    return eingabe * 2;
}
consteval auto berechne_2(int eingabe) {
    return eingabe * 2;
}
int main() {
    int eingabe = hole_eingabe();
    auto a = berechne_1(77);      // zur Übersetzungszeit ... vielleicht berechenbar
    auto b = berechne_1(eingabe); // … berechenbar, aber gültig
    auto c = berechne_2(77);      // … berechenbar
    auto d = berechne_2(eingabe); //                 (ERR)  … nicht berechenbar, ungültig
}

Godbolt Listing lst-0357-godb.cpp, https://godbolt.org/z/8rr4WKo8d:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8rr4WKo8d 
int hole_eingabe() {
    return 50; // oder lese was aus einer Datei oder so
}
constexpr auto berechne_1(int eingabe) {
    return eingabe * 2;
}
consteval auto berechne_2(int eingabe) {
    return eingabe * 2;
}
int main() {
    int eingabe = hole_eingabe();
    auto a = berechne_1(77);      // zur Übersetzungszeit ... vielleicht berechenbar
    auto b = berechne_1(eingabe); // … berechenbar, aber gültig
    auto c = berechne_2(77);      // … berechenbar
    auto d = berechne_2(eingabe); //                 (ERR)  … nicht berechenbar, ungültig
}

Listing 13.18: Auch komplexere Funktionen können mit »consteval« zur Übersetzungszeit berechnet werden.

Book listing lst-0358-book.cpp:

// https://godbolt.org/z/KGn9ob8on 
#include <iostream>
#include <array>
constexpr bool isPrime(int n) { // zur Übersetzungszeit berechenbar
  if(n < 2) return false; // 0, 1 sind nicht prim
  for (int i = 2; i*i <= n; i += i>2 ? 2 : 1) { // 2,3,5,7,9,11,13,15…
    if (n % i == 0) return false;
  }
  return n > 1; // für 0 und 1
}
template<int Num>
consteval std::array<int, Num> primeNumbers() { // nur zur Übersetzungszeit
  std::array<int, Num> primes{};
  int idx = 0;
  for (int val = 1; idx < Num; ++val) {
    if (isPrime(val)) primes[idx++] = val;
  }
  return primes;
}
int main() {
  // Initialisiere mit Primzahlen
  auto primes = primeNumbers<100>();  // 1000000 geht nicht
  for (auto v : primes) {
    std::cout << v << ' ';
  }
  std::cout << '\n';
}

Godbolt Listing lst-0358-godb.cpp, https://godbolt.org/z/KGn9ob8on:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KGn9ob8on 
#include <iostream>
#include <array>
constexpr bool isPrime(int n) { // zur Übersetzungszeit berechenbar
  if(n < 2) return false; // 0, 1 sind nicht prim
  for (int i = 2; i*i <= n; i += i>2 ? 2 : 1) { // 2,3,5,7,9,11,13,15…
    if (n % i == 0) return false;
  }
  return n > 1; // für 0 und 1
}
template<int Num>
consteval std::array<int, Num> primeNumbers() { // nur zur Übersetzungszeit
  std::array<int, Num> primes{};
  int idx = 0;
  for (int val = 1; idx < Num; ++val) {
    if (isPrime(val)) primes[idx++] = val;
  }
  return primes;
}
int main() {
  // Initialisiere mit Primzahlen
  auto primes = primeNumbers<100>();  // 1000000 geht nicht
  for (auto v : primes) {
    std::cout << v << ' ';
  }
  std::cout << '\n';
}

Listing 13.19: Der Compiler stellt fest, ob der Aufruf im Context zur Compilezeit berechnet werden kann.

Book listing lst-0359-book.cpp:

// https://godbolt.org/z/7KWqTPo1K 
#include <iostream> // cout
constexpr int hole_wert() {
    if consteval {
       return 42;
    } else {
       return 668;
    }
}
int main() {
  auto a = hole_wert();
  std::cout << a << '\n';       // Ausgabe: 668
  constexpr auto b = hole_wert();
  std::cout << b << '\n';       // Ausgabe: 42
}

Godbolt Listing lst-0359-godb.cpp, https://godbolt.org/z/7KWqTPo1K:

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/7KWqTPo1K 
#include <iostream> // cout
constexpr int hole_wert() {
    if consteval {
       return 42;
    } else {
       return 668;
    }
}
int main() {
  auto a = hole_wert();
  std::cout << a << '\n';       // Ausgabe: 668
  constexpr auto b = hole_wert();
  std::cout << b << '\n';       // Ausgabe: 42
}

Listing 13.20: »mutable« macht ein Datenfeld in const-Methoden veränderbar.

Book listing lst-0361-book.cpp:

// https://godbolt.org/z/sPorKnEbd 
#include <iostream>
class Data {
    int value_;
    mutable size_t getCount_{0};
  public:
    explicit Data(int v) : value_{v} { }
    ~Data() {
        std::cout << "get wurde " << getCount_ << "-mal benutzt\n";
    }
    int get() const {
        ++getCount_;
        return value_;
    }
};
int main() {
    Data d{42};
    for(int i=0; i<10; ++i) { d.get(); }
} // Ausgabe: get wurde 10-mal benutzt

Godbolt Listing lst-0361-godb.cpp, https://godbolt.org/z/sPorKnEbd:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sPorKnEbd 
#include <iostream>
class Data {
    int value_;
    mutable size_t getCount_{0};
  public:
    explicit Data(int v) : value_{v} { }
    ~Data() {
        std::cout << "get wurde " << getCount_ << "-mal benutzt\n";
    }
    int get() const {
        ++getCount_;
        return value_;
    }
};
int main() {
    Data d{42};
    for(int i=0; i<10; ++i) { d.get(); }
} // Ausgabe: get wurde 10-mal benutzt

Listing 13.21: »const« mit Containern

Book listing lst-0362-book.cpp:

// https://godbolt.org/z/GE5v6Ea8x 
#include <map>
#include <string>
using std::map; using std::string;
struct MyClass {
  bool isFound(const map<int,string> &dict,  // unveränderbarer Eingabeparam.
               const int &key,               // ebenso
               string &result                // Ausgabeparameter: kein const
               ) const                       // Instanz von MyClass const
  {
    const map<int,string>::const_iterator where  // Verweis und Wert fest
      = dict.find(key);
    if(where == end(dict)) {
      return false;
    } else {
      result = where->second;
      return true;
    }
  }
};

Godbolt Listing lst-0362-godb.cpp, https://godbolt.org/z/GE5v6Ea8x:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GE5v6Ea8x 
#include <map>
#include <string>
using std::map; using std::string;
struct MyClass {
  bool isFound(const map<int,string> &dict,  // unveränderbarer Eingabeparam.
               const int &key,               // ebenso
               string &result                // Ausgabeparameter: kein const
               ) const                       // Instanz von MyClass const
  {
    const map<int,string>::const_iterator where  // Verweis und Wert fest
      = dict.find(key);
    if(where == end(dict)) {
      return false;
    } else {
      result = where->second;
      return true;
    }
  }
};

Listing 13.22: x und y können irgendwie von außen verändert werden.

Book listing lst-0363-book.cpp:

#include <iostream>
#include <chrono> // milliseconds
#include <thread> // this_thread::sleep

struct Pos {
  volatile int x;
  volatile int y;
};
Pos pos{};

// irgendwo anders definiert:
int installMouseDriver(Pos *p);

constexpr auto DELAY = std::chrono::milliseconds(100);
constexpr auto LOOPS = 30; // 30*100ms = 3s
int main() {
    installMouseDriver( &pos );  // MouseDriver aktualisiert x und y
    for(int i=0; i<LOOPS; ++i) {
        std::cout << "maus bei ("<<pos.x<<","<<pos.y<<")\n";
        std::this_thread::sleep_for(DELAY);
    }
}

Listing 14.1: Solitäre Tests testen nur eine Komponente, Helferklassen werden untergeschoben.

Book listing lst-0364-book.cpp:

// https://godbolt.org/z/a83sf9h8E 
#include <iostream>
// Produktionscode:
struct DatabaseInterface {
    virtual int getData() const = 0;
};
struct Programm {
    DatabaseInterface &db_;
    void run() {
        std:: cout << db_.getData() << "\n";
    }
};
// Testhelfer:
struct MockDatabase : public DatabaseInterface {
    int getData() const override { return 5; }
};
// main als Test:
int main() {
    MockDatabase mockDb;
    Programm prog { mockDb }; // echte DB wird nicht mitgetestet
    prog.run();               // Erwartete Ausgabe: 5
}

Godbolt Listing lst-0364-godb.cpp, https://godbolt.org/z/a83sf9h8E:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a83sf9h8E 
#include <iostream>
// Produktionscode:
struct DatabaseInterface {
    virtual int getData() const = 0;
};
struct Programm {
    DatabaseInterface &db_;
    void run() {
        std:: cout << db_.getData() << "\n";
    }
};
// Testhelfer:
struct MockDatabase : public DatabaseInterface {
    int getData() const override { return 5; }
};
// main als Test:
int main() {
    MockDatabase mockDb;
    Programm prog { mockDb }; // echte DB wird nicht mitgetestet
    prog.run();               // Erwartete Ausgabe: 5
}

Listing 14.2: Soziale Tests testen das Zusammenspiel der Komponenten mit.

Book listing lst-0365-book.cpp:

// https://godbolt.org/z/fsroE4seh 
#include <iostream>

// Produktionscode:
struct DatabaseInterface {
    virtual int getData() const = 0;
};
struct RealDatabase : public DatabaseInterface {
    int getData() const override { return 999; }
};
struct Programm {
    DatabaseInterface &db_;
    void run() {
        std:: cout << db_.getData() << "\n";
    }
};

// main als Test:
int main() {
    RealDatabase db;
    Programm prog { db }; // echte DB wird  mitgetestet
    prog.run();           // Erwartete Ausgabe: 999
}

Godbolt Listing lst-0365-godb.cpp, https://godbolt.org/z/fsroE4seh:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fsroE4seh 
#include <iostream>

// Produktionscode:
struct DatabaseInterface {
    virtual int getData() const = 0;
};
struct RealDatabase : public DatabaseInterface {
    int getData() const override { return 999; }
};
struct Programm {
    DatabaseInterface &db_;
    void run() {
        std:: cout << db_.getData() << "\n";
    }
};

// main als Test:
int main() {
    RealDatabase db;
    Programm prog { db }; // echte DB wird  mitgetestet
    prog.run();           // Erwartete Ausgabe: 999
}

GodboltId:4PeYrc8jo

Book listing lst-0366-book.cpp:

// https://godbolt.org/z/4PeYrc8jo 
void testVerdopple5() {
    // vorbereiten
    auto param = 5;
    // ausführen
    auto result = verdopple(param);
    // überprüfen
    assertTrue(result == 10);
}

Godbolt Listing lst-0366-godb.cpp, https://godbolt.org/z/4PeYrc8jo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4PeYrc8jo 
void testVerdopple5() {
    // vorbereiten
    auto param = 5;
    // ausführen
    auto result = verdopple(param);
    // überprüfen
    assertTrue(result == 10);
}

GodboltId:Y9exe7rqT

Book listing lst-0367-book.cpp:

// https://godbolt.org/z/Y9exe7rqT 
void testVerdopple() {
    assertTrue( verdopple(0) == 0 );
    assertTrue( verdopple(-1) == -2 );
    assertTrue( verdopple(1) == 2 );
    assertTrue( verdopple(5) == 10 );
}

Godbolt Listing lst-0367-godb.cpp, https://godbolt.org/z/Y9exe7rqT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y9exe7rqT 
void testVerdopple() {
    assertTrue( verdopple(0) == 0 );
    assertTrue( verdopple(-1) == -2 );
    assertTrue( verdopple(1) == 2 );
    assertTrue( verdopple(5) == 10 );
}

Listing 14.3: In der Datei »fib.cpp« ist eine freie Funktion, die Sie testen wollen.

Book listing lst-0368-book.cpp:

// https://godbolt.org/z/Ex6Mv6xcz 
unsigned fib(unsigned n) {
    if(n==0) { return 0; }
    if(n==1) { return 1; }
    unsigned a = 0;
    unsigned b = 1;
    unsigned sum = 1;
    while(n>1) {
        sum += a;
        a = b;
        b = sum;
        n -= 1;
    }
    return sum;
}

Godbolt Listing lst-0368-godb.cpp, https://godbolt.org/z/Ex6Mv6xcz:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ex6Mv6xcz 
unsigned fib(unsigned n) {
    if(n==0) { return 0; }
    if(n==1) { return 1; }
    unsigned a = 0;
    unsigned b = 1;
    unsigned sum = 1;
    while(n>1) {
        sum += a;
        a = b;
        b = sum;
        n -= 1;
    }
    return sum;
}

GodboltId:ba7e7s8qK

Book listing lst-0369-book.cpp:

// https://godbolt.org/z/ba7e7s8qK 
#define BOOST_TEST_MAIN test_main            // generiert main() in diesem Modul
#include <boost/test/included/unit_test.hpp> // Framework
#include <boost/test/test_tools.hpp>         // BOOST_CHECK etc
unsigned fib(unsigned n);                    // zu testen
namespace {
using namespace boost::unit_test;
BOOST_AUTO_TEST_CASE( test_fib_low )         // beliebiger Name des Testcases
{
    BOOST_CHECK( fib(0) == 0 );              // einzelne Assertions
    BOOST_CHECK( fib(1) == 1 );
    BOOST_CHECK( fib(2) == 1 );
    BOOST_CHECK( fib(3) == 2 );
    BOOST_CHECK( fib(4) == 3 );
    BOOST_CHECK( fib(5) == 5 );
    BOOST_CHECK( fib(6) == 8 );
}
}

Godbolt Listing lst-0369-godb.cpp, https://godbolt.org/z/ba7e7s8qK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ba7e7s8qK 
#define BOOST_TEST_MAIN test_main            // generiert main() in diesem Modul
#include <boost/test/included/unit_test.hpp> // Framework
#include <boost/test/test_tools.hpp>         // BOOST_CHECK etc
unsigned fib(unsigned n);                    // zu testen
namespace {
using namespace boost::unit_test;
BOOST_AUTO_TEST_CASE( test_fib_low )         // beliebiger Name des Testcases
{
    BOOST_CHECK( fib(0) == 0 );              // einzelne Assertions
    BOOST_CHECK( fib(1) == 1 );
    BOOST_CHECK( fib(2) == 1 );
    BOOST_CHECK( fib(3) == 2 );
    BOOST_CHECK( fib(4) == 3 );
    BOOST_CHECK( fib(5) == 5 );
    BOOST_CHECK( fib(6) == 8 );
}
}

Listing 14.4: Die Haupt-Headerdatei der Bibliothek qwort.hpp

Book listing lst-0375-book.cpp:

// https://godbolt.org/z/5ajrvGvcW 
#ifndef QWORT_H   // Header-Guard
#define QWORT_H
#include <string>
#include <string_view>
#include <memory> // unique_ptr
namespace qw {    // Namensraum der Bibliothek

    int version();

    namespace impl_multimap {
        class index_impl;
    }

    class index {
        using index_impl = impl_multimap::index_impl;
    public:
        index();
        ~index() noexcept; // wird für pimpl benötigt
        index(const index&) = delete;
        index(index&&) noexcept;
        index& operator=(const index&) = delete;
        index& operator=(index&&) = delete;
    public:
        void add(std::string_view arg);
        size_t size() const;
        std::string getBestMatch(std::string_view query) const;
    public:          // public für Tests
        std::string normalize(std::string arg) const;
    private:
        std::unique_ptr<index_impl> pimpl;
    };
} // namespace qw
#endif // Header-Guard

Godbolt Listing lst-0375-godb.cpp, https://godbolt.org/z/5ajrvGvcW:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5ajrvGvcW 
#ifndef QWORT_H   // Header-Guard
#define QWORT_H
#include <string>
#include <string_view>
#include <memory> // unique_ptr
namespace qw {    // Namensraum der Bibliothek

    int version();

    namespace impl_multimap {
        class index_impl;
    }

    class index {
        using index_impl = impl_multimap::index_impl;
    public:
        index();
        ~index() noexcept; // wird für pimpl benötigt
        index(const index&) = delete;
        index(index&&) noexcept;
        index& operator=(const index&) = delete;
        index& operator=(index&&) = delete;
    public:
        void add(std::string_view arg);
        size_t size() const;
        std::string getBestMatch(std::string_view query) const;
    public:          // public für Tests
        std::string normalize(std::string arg) const;
    private:
        std::unique_ptr<index_impl> pimpl;
    };
} // namespace qw
#endif // Header-Guard

Listing 14.5: Öffentliche Schnittstelle nur fürs Testen

Book listing lst-0376-book.cpp:

class index_impl {
// ...
public: // test interface
    vector<string> _qgramify(string_view n) const { return qgramify(n); }
    static size_t _q() { return Q; }
    static std::string _prefix() { return PREFIX; }
    static std::string _suffix() { return SUFFIX; }
};

Listing 14.6: Dieses Testmodul testet qwort.cpp.

Book listing lst-0377-book.cpp:

// https://godbolt.org/z/Y98jq1eGx 
#include "qwort/qwort.hpp" // under test
#define BOOST_TEST_MODULE qwort
#include <boost/test/included/unit_test.hpp>
using namespace boost::unit_test;
BOOST_AUTO_TEST_CASE( version_is_1 ) {
    BOOST_TEST(qw::version() == 1);
    // der folgende Vergleich soll fehlschlagen, aber nur eine Warnung erzeugen:
    BOOST_WARN_EQUAL(qw::version(), 2);   //                 (ERR)  ungleich, aber macht weiter
}
BOOST_AUTO_TEST_CASE( init_size_0 ) {
    qw::index inst{};                     // arrange
    auto sz = inst.size();                // act
    BOOST_TEST(sz == 0u);                 // assert
}
BOOST_AUTO_TEST_CASE( add_size_1 ) {
    using namespace std::literals::string_literals;
    qw::index inst{};                     // arrange
    inst.add(""s);                        // act
    BOOST_REQUIRE_EQUAL(inst.size(), 1u); // assert
}
BOOST_AUTO_TEST_CASE( normalize ) {
    using namespace std::literals::string_literals;
    qw::index inst{}; // arrange
    // acts und asserts; könnte auch in getrennten Funktionen sein
    BOOST_CHECK_EQUAL(inst.normalize("a"s), "A"s);
    BOOST_CHECK_EQUAL(inst.normalize("Stadt"s), "STADT"s);
    BOOST_CHECK_EQUAL(inst.normalize("Leer Zeichen"s), "LEER#ZEICHEN"s);
    BOOST_CHECK_EQUAL(inst.normalize("!Sym-bol."s), "#SYM#BOL#"s);
}
BOOST_AUTO_TEST_CASE( move ) {
    qw::index inst{};
    qw::index other = std::move( inst );
    BOOST_CHECK_EQUAL(other.size(), 0u); // pimpl erfolgreich verschoben?
}

Godbolt Listing lst-0377-godb.cpp, https://godbolt.org/z/Y98jq1eGx:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y98jq1eGx 
#include "qwort/qwort.hpp" // under test
#define BOOST_TEST_MODULE qwort
#include <boost/test/included/unit_test.hpp>
using namespace boost::unit_test;
BOOST_AUTO_TEST_CASE( version_is_1 ) {
    BOOST_TEST(qw::version() == 1);
    // der folgende Vergleich soll fehlschlagen, aber nur eine Warnung erzeugen:
    BOOST_WARN_EQUAL(qw::version(), 2);   //                 (ERR)  ungleich, aber macht weiter
}
BOOST_AUTO_TEST_CASE( init_size_0 ) {
    qw::index inst{};                     // arrange
    auto sz = inst.size();                // act
    BOOST_TEST(sz == 0u);                 // assert
}
BOOST_AUTO_TEST_CASE( add_size_1 ) {
    using namespace std::literals::string_literals;
    qw::index inst{};                     // arrange
    inst.add(""s);                        // act
    BOOST_REQUIRE_EQUAL(inst.size(), 1u); // assert
}
BOOST_AUTO_TEST_CASE( normalize ) {
    using namespace std::literals::string_literals;
    qw::index inst{}; // arrange
    // acts und asserts; könnte auch in getrennten Funktionen sein
    BOOST_CHECK_EQUAL(inst.normalize("a"s), "A"s);
    BOOST_CHECK_EQUAL(inst.normalize("Stadt"s), "STADT"s);
    BOOST_CHECK_EQUAL(inst.normalize("Leer Zeichen"s), "LEER#ZEICHEN"s);
    BOOST_CHECK_EQUAL(inst.normalize("!Sym-bol."s), "#SYM#BOL#"s);
}
BOOST_AUTO_TEST_CASE( move ) {
    qw::index inst{};
    qw::index other = std::move( inst );
    BOOST_CHECK_EQUAL(other.size(), 0u); // pimpl erfolgreich verschoben?
}

Listing 14.7: Hier wird die Testsuite manuell zusammengebaut.

Book listing lst-0387-book.cpp:

// https://godbolt.org/z/TfMnK1Tnn 
/* private Header aus lib-Verzeichnis: */
#include "impl_multimap.hpp"                  // zu testen
// wir definieren  init_unit_test_suite() selbst, also NICHT setzen:
/* #define BOOST_TEST_MODULE qgram */
#include <boost/test/included/unit_test.hpp>
#include <memory>                             // shared ptr
#include <vector>
#include <string>
using namespace boost::unit_test;
using namespace std::literals::string_literals;
using std::string; using std::vector;
/* === Eine Testklasse für die zu testende Klasse === */
using UnderTest = qw::impl_multimap::index_impl;
class ImplMultimapTest {                      // Klasse mit Testmethoden
public:
    /* === Konstanten === */
    void testConstants() {
        BOOST_REQUIRE_EQUAL(UnderTest::_prefix().length(), UnderTest::_q()-1);
        BOOST_REQUIRE_EQUAL(UnderTest::_suffix().length(), UnderTest::_q()-1);
        for(size_t i = 0; i < UnderTest::_q()-1; ++i) {
            BOOST_CHECK_EQUAL(UnderTest::_prefix()[i], '^');
            BOOST_CHECK_EQUAL(UnderTest::_suffix()[i], '$');
        }
        // oder konkreter:
        BOOST_TEST(UnderTest::_q() == 3u);
        BOOST_TEST(UnderTest::_prefix() == "^^"s);
        BOOST_TEST(UnderTest::_suffix() == "$$"s);
    }
    /* === qgramify === */
    void testQgramifyEmpty() {
        UnderTest inst{};
        auto result = inst._qgramify(""s);
        vector<string> expected{"^^$"s, "^$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify1() {
        UnderTest inst{};
        auto result = inst._qgramify("a"s);
        vector<string> expected{"^^a"s, "^a$"s, "a$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify2() {
        UnderTest inst{};
        auto result = inst._qgramify("ab"s);
        vector<string> expected{"^^a"s, "^ab"s, "ab$"s, "b$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify3() {
        UnderTest inst{};
        auto result = inst._qgramify("abc"s);
        vector<string> expected{"^^a"s, "^ab"s, "abc"s, "bc$"s, "c$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    /* === add === */
    void testAdd_nodups() {
        UnderTest inst{};                     /* arrange */
        BOOST_REQUIRE_EQUAL(inst.size(), 0u); /* assert */
        inst.add("", "");                     /* act */
        BOOST_CHECK_EQUAL(inst.size(), 1u);   /* assert */
        inst.add("ENTRY", "entry");           /* act */
        BOOST_CHECK_EQUAL(inst.size(), 2u);   /* assert */
        inst.add("OTHER", "other");           /* act */
        BOOST_CHECK_EQUAL(inst.size(), 3u);   /* assert */
    }
    /* === add === */
    void test_getBestMatch_empty() {
        UnderTest inst{};
        auto result = inst.getBestMatch("any");
        BOOST_CHECK_EQUAL(result, ""s);
    }
    void test_getBestMatch_one() {
        /* arrange */
        UnderTest inst{};
        inst.add("HOLSDERTEUFEL", "holsderteufel");
        /* act */
        auto result = inst.getBestMatch("ROBERT");
        BOOST_CHECK_EQUAL(result, "holsderteufel"s);
    }
    void test_getBestMatch_exact() {
        /* arrange */
        UnderTest inst{};
        inst.add("BERLIN", "Berlin");
        inst.add("HAMBURG", "Hamburg");
        inst.add("DORTMUND", "Dortmund");
        inst.add("STUTTGART", "Stuttgart");
        inst.add("WYK", "Wyk");
        /* act and assert */
        BOOST_CHECK_EQUAL(inst.getBestMatch("BERLIN"), "Berlin"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("HAMBURG"), "Hamburg"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("DORTMUND"), "Dortmund"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("STUTTGART"), "Stuttgart"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("WYK"), "Wyk"s);
    }
    void test_getBestMatch_close() {
        /* arrange */
        UnderTest inst{};
        inst.add("BERLIN", "Berlin");
        inst.add("HAMBURG", "Hamburg");
        inst.add("DORTMUND", "Dortmund");
        inst.add("STUTTGART", "Stuttgart");
        inst.add("WYK", "Wyk");
        /* act and assert */
        BOOST_CHECK_EQUAL(inst.getBestMatch("BRLIN"), "Berlin"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("BURG"), "Hamburg"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("DORTDORT"), "Dortmund"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("STUTGURT"), "Stuttgart"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("WIK"), "Wyk"s);
    }
/* Bei neuen Testmethoden: Hinzufügen zu init_unit_test_suite() nicht vergessen */
};
/* === Suite === */
test_suite* init_unit_test_suite( int argc, char* argv[] ) {
    auto tester = std::make_shared<ImplMultimapTest>();
    auto &ts = framework::master_test_suite();
    ts.add( BOOST_TEST_CASE( [=](){ tester->testConstants(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramifyEmpty(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify1(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify2(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify3(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify3(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testAdd_nodups(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_empty(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_one(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_exact(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_close(); } ));
    return nullptr;
}

Godbolt Listing lst-0387-godb.cpp, https://godbolt.org/z/TfMnK1Tnn:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TfMnK1Tnn 
/* private Header aus lib-Verzeichnis: */
#include "impl_multimap.hpp"                  // zu testen
// wir definieren  init_unit_test_suite() selbst, also NICHT setzen:
/* #define BOOST_TEST_MODULE qgram */
#include <boost/test/included/unit_test.hpp>
#include <memory>                             // shared ptr
#include <vector>
#include <string>
using namespace boost::unit_test;
using namespace std::literals::string_literals;
using std::string; using std::vector;
/* === Eine Testklasse für die zu testende Klasse === */
using UnderTest = qw::impl_multimap::index_impl;
class ImplMultimapTest {                      // Klasse mit Testmethoden
public:
    /* === Konstanten === */
    void testConstants() {
        BOOST_REQUIRE_EQUAL(UnderTest::_prefix().length(), UnderTest::_q()-1);
        BOOST_REQUIRE_EQUAL(UnderTest::_suffix().length(), UnderTest::_q()-1);
        for(size_t i = 0; i < UnderTest::_q()-1; ++i) {
            BOOST_CHECK_EQUAL(UnderTest::_prefix()[i], '^');
            BOOST_CHECK_EQUAL(UnderTest::_suffix()[i], '$');
        }
        // oder konkreter:
        BOOST_TEST(UnderTest::_q() == 3u);
        BOOST_TEST(UnderTest::_prefix() == "^^"s);
        BOOST_TEST(UnderTest::_suffix() == "$$"s);
    }
    /* === qgramify === */
    void testQgramifyEmpty() {
        UnderTest inst{};
        auto result = inst._qgramify(""s);
        vector<string> expected{"^^$"s, "^$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify1() {
        UnderTest inst{};
        auto result = inst._qgramify("a"s);
        vector<string> expected{"^^a"s, "^a$"s, "a$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify2() {
        UnderTest inst{};
        auto result = inst._qgramify("ab"s);
        vector<string> expected{"^^a"s, "^ab"s, "ab$"s, "b$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    void testQgramify3() {
        UnderTest inst{};
        auto result = inst._qgramify("abc"s);
        vector<string> expected{"^^a"s, "^ab"s, "abc"s, "bc$"s, "c$$"s};
        BOOST_CHECK_EQUAL_COLLECTIONS(
            result.begin(), result.end(), expected.begin(), expected.end() );
    }
    /* === add === */
    void testAdd_nodups() {
        UnderTest inst{};                     /* arrange */
        BOOST_REQUIRE_EQUAL(inst.size(), 0u); /* assert */
        inst.add("", "");                     /* act */
        BOOST_CHECK_EQUAL(inst.size(), 1u);   /* assert */
        inst.add("ENTRY", "entry");           /* act */
        BOOST_CHECK_EQUAL(inst.size(), 2u);   /* assert */
        inst.add("OTHER", "other");           /* act */
        BOOST_CHECK_EQUAL(inst.size(), 3u);   /* assert */
    }
    /* === add === */
    void test_getBestMatch_empty() {
        UnderTest inst{};
        auto result = inst.getBestMatch("any");
        BOOST_CHECK_EQUAL(result, ""s);
    }
    void test_getBestMatch_one() {
        /* arrange */
        UnderTest inst{};
        inst.add("HOLSDERTEUFEL", "holsderteufel");
        /* act */
        auto result = inst.getBestMatch("ROBERT");
        BOOST_CHECK_EQUAL(result, "holsderteufel"s);
    }
    void test_getBestMatch_exact() {
        /* arrange */
        UnderTest inst{};
        inst.add("BERLIN", "Berlin");
        inst.add("HAMBURG", "Hamburg");
        inst.add("DORTMUND", "Dortmund");
        inst.add("STUTTGART", "Stuttgart");
        inst.add("WYK", "Wyk");
        /* act and assert */
        BOOST_CHECK_EQUAL(inst.getBestMatch("BERLIN"), "Berlin"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("HAMBURG"), "Hamburg"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("DORTMUND"), "Dortmund"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("STUTTGART"), "Stuttgart"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("WYK"), "Wyk"s);
    }
    void test_getBestMatch_close() {
        /* arrange */
        UnderTest inst{};
        inst.add("BERLIN", "Berlin");
        inst.add("HAMBURG", "Hamburg");
        inst.add("DORTMUND", "Dortmund");
        inst.add("STUTTGART", "Stuttgart");
        inst.add("WYK", "Wyk");
        /* act and assert */
        BOOST_CHECK_EQUAL(inst.getBestMatch("BRLIN"), "Berlin"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("BURG"), "Hamburg"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("DORTDORT"), "Dortmund"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("STUTGURT"), "Stuttgart"s);
        BOOST_CHECK_EQUAL(inst.getBestMatch("WIK"), "Wyk"s);
    }
/* Bei neuen Testmethoden: Hinzufügen zu init_unit_test_suite() nicht vergessen */
};
/* === Suite === */
test_suite* init_unit_test_suite( int argc, char* argv[] ) {
    auto tester = std::make_shared<ImplMultimapTest>();
    auto &ts = framework::master_test_suite();
    ts.add( BOOST_TEST_CASE( [=](){ tester->testConstants(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramifyEmpty(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify1(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify2(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify3(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testQgramify3(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->testAdd_nodups(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_empty(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_one(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_exact(); } ));
    ts.add( BOOST_TEST_CASE( [=](){ tester->test_getBestMatch_close(); } ));
    return nullptr;
}

Listing 14.8: Eine Testfunktion mit einem Parameter kann mit Testdaten aufgerufen werden.

Book listing lst-0392-book.cpp:

// https://godbolt.org/z/q8E6WMano 
#include <boost/test/parameterized_test.hpp>
struct Param {
    string input;
    vector<string> expected;
};
const vector<Param> params {
    // { Eingabe, erwartetes Ergebnis }
    {""s,     {"^^$"s, "^$$"s} },
    {"A"s,    {"^^A"s, "^A$"s, "A$$"s} },
    {"AB"s,   {"^^A"s, "^AB"s, "AB$"s, "B$$"s} },
    {"ACB"s,  {"^^A"s, "^AC"s, "ACB"s, "CB$"s, "B$$"s} },
    {"AAA"s,  {"^^A"s, "^AA"s, "AAA"s, "AA$"s, "A$$"s} },
};
void testQgramify(const Param& param) {
    /* arrange */
    UnderTest inst{};
    /* act */
    auto result = inst._qgramify(param.input);
    /* assert */
    BOOST_CHECK_EQUAL_COLLECTIONS(
        param.expected.begin(), param.expected.end(),
        result.begin(), result.end());
}

Godbolt Listing lst-0392-godb.cpp, https://godbolt.org/z/q8E6WMano:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/q8E6WMano 
#include <boost/test/parameterized_test.hpp>
struct Param {
    string input;
    vector<string> expected;
};
const vector<Param> params {
    // { Eingabe, erwartetes Ergebnis }
    {""s,     {"^^$"s, "^$$"s} },
    {"A"s,    {"^^A"s, "^A$"s, "A$$"s} },
    {"AB"s,   {"^^A"s, "^AB"s, "AB$"s, "B$$"s} },
    {"ACB"s,  {"^^A"s, "^AC"s, "ACB"s, "CB$"s, "B$$"s} },
    {"AAA"s,  {"^^A"s, "^AA"s, "AAA"s, "AA$"s, "A$$"s} },
};
void testQgramify(const Param& param) {
    /* arrange */
    UnderTest inst{};
    /* act */
    auto result = inst._qgramify(param.input);
    /* assert */
    BOOST_CHECK_EQUAL_COLLECTIONS(
        param.expected.begin(), param.expected.end(),
        result.begin(), result.end());
}

Listing 15.1: Der gemeinsame Vorfahre unserer Hilfsklassen »Year«, »Month« und »Day«

Book listing lst-0398-book.cpp:

// https://godbolt.org/z/hhGo46z5a 
#include <iostream>  // ostream
#include <format>    // format, vformat, make_format_args
using std::ostream;
class Value {
protected: // nicht öffentlich, nur für den eigenen und abgeleiteten Gebrauch
    int value_;
    const std::string fmt_;  // z. B. "{:02}" oder "{:04}"
    Value(int v, unsigned w) // Konstruktor mit zwei Argumenten
      : value_{v}, fmt_{std::format("{{:0{}}}", w)} {}
public:
    ostream& print(ostream& os) const;
};
ostream& operator<<(ostream& os, const Value& rechts) {
    return rechts.print(os);
}
ostream& Value::print(ostream& os) const {
    return os << std::vformat(fmt_, std::make_format_args(value_));
}

Godbolt Listing lst-0398-godb.cpp, https://godbolt.org/z/hhGo46z5a:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hhGo46z5a 
#include <iostream>  // ostream
#include <format>    // format, vformat, make_format_args
using std::ostream;
class Value {
protected: // nicht öffentlich, nur für den eigenen und abgeleiteten Gebrauch
    int value_;
    const std::string fmt_;  // z. B. "{:02}" oder "{:04}"
    Value(int v, unsigned w) // Konstruktor mit zwei Argumenten
      : value_{v}, fmt_{std::format("{{:0{}}}", w)} {}
public:
    ostream& print(ostream& os) const;
};
ostream& operator<<(ostream& os, const Value& rechts) {
    return rechts.print(os);
}
ostream& Value::print(ostream& os) const {
    return os << std::vformat(fmt_, std::make_format_args(value_));
}

Listing 15.2: Der doppelte Code der Hilfsklassen ist nun verschwunden.

Book listing lst-0399-book.cpp:

// https://godbolt.org/z/eYY1js4Te 
class Year : public Value {               // von Klasse Value ableiten
public:
    explicit Year(int v) : Value{v, 4} {} // Basisklasse initialisieren
};
class Month : public Value {
public:
    explicit Month(int v) : Value{v, 2} {}
};
struct Day : public Value {               // class-public entspricht struct
    explicit Day(int v) : Value{v, 2} {}
};

Godbolt Listing lst-0399-godb.cpp, https://godbolt.org/z/eYY1js4Te:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eYY1js4Te 
class Year : public Value {               // von Klasse Value ableiten
public:
    explicit Year(int v) : Value{v, 4} {} // Basisklasse initialisieren
};
class Month : public Value {
public:
    explicit Month(int v) : Value{v, 2} {}
};
struct Day : public Value {               // class-public entspricht struct
    explicit Day(int v) : Value{v, 2} {}
};

Listing 15.3: So verwendet »Date« die neuen Klassen.

Book listing lst-0400-book.cpp:

// https://godbolt.org/z/9rY7qhK89 
class Date {
    Year year_;
    Month month_ {1};
    Day day_ {1};
public:
    explicit Date(int y) : year_{y} {} // year-01-01
    Date(Year y, Month m, Day d) : year_{y}, month_{m}, day_{d} {}
    ostream& print(ostream& os) const;
};
ostream& Date::print(ostream& os) const {
    return os << year_ << "-" << month_ << "-"  << day_;
}
ostream& operator<<(ostream& os, const Date& rechts) {
    return rechts.print(os);
}
int main() {
    Date d1 { Year{2013}, Month{15}, Day{19} };
    std::cout << d1 << "\n"; // Ausgabe: 2013-15-19
}

Godbolt Listing lst-0400-godb.cpp, https://godbolt.org/z/9rY7qhK89:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9rY7qhK89 
class Date {
    Year year_;
    Month month_ {1};
    Day day_ {1};
public:
    explicit Date(int y) : year_{y} {} // year-01-01
    Date(Year y, Month m, Day d) : year_{y}, month_{m}, day_{d} {}
    ostream& print(ostream& os) const;
};
ostream& Date::print(ostream& os) const {
    return os << year_ << "-" << month_ << "-"  << day_;
}
ostream& operator<<(ostream& os, const Date& rechts) {
    return rechts.print(os);
}
int main() {
    Date d1 { Year{2013}, Month{15}, Day{19} };
    std::cout << d1 << "\n"; // Ausgabe: 2013-15-19
}

Listing 15.4: Nun ist »ostern« eine Methode von »Year«.

Book listing lst-0401-book.cpp:

// https://godbolt.org/z/Wjsvv6Gdv 
class Date;  // Vorwärtsdeklaration
class Year : public Value {
public:
    explicit Year(int v) : Value{v, 4} {}
    Date ostern() const;            // neue Methode deklarieren
};
// Hier Month, Day und Date deklarieren. Dann:
Date Year::ostern() const {         // neue Methode definieren
    const int y = value_;
    int a = value_/100*1483 - value_/400*2225 + 2613;
    int b = (value_%19*3510 + a/25*319)/330%29;
    b = 148 - b - (value_*5/4 + a - b)%7;
    return Date{Year{value_}, Month{b/31}, Day{b%31 + 1}};
}
int main() {
    using std::cout;
    Year year{2014};
    cout << year.ostern() << "\n";  // Ausgabe: 2014-04-20
}

Godbolt Listing lst-0401-godb.cpp, https://godbolt.org/z/Wjsvv6Gdv:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Wjsvv6Gdv 
class Date;  // Vorwärtsdeklaration
class Year : public Value {
public:
    explicit Year(int v) : Value{v, 4} {}
    Date ostern() const;            // neue Methode deklarieren
};
// Hier Month, Day und Date deklarieren. Dann:
Date Year::ostern() const {         // neue Methode definieren
    const int y = value_;
    int a = value_/100*1483 - value_/400*2225 + 2613;
    int b = (value_%19*3510 + a/25*319)/330%29;
    b = 148 - b - (value_*5/4 + a - b)%7;
    return Date{Year{value_}, Month{b/31}, Day{b%31 + 1}};
}
int main() {
    using std::cout;
    Year year{2014};
    cout << year.ostern() << "\n";  // Ausgabe: 2014-04-20
}

Listing 15.5: Alle Komponenten haben eine weiße Farbe, nur der Druckknopf wird grau.

Book listing lst-0402-book.cpp:

struct Komponente {
    Color getColor() const { return weiss; }
};
struct Fenster : public Komponente { };
struct Hauptfenster : public Fenster { };
struct Dialog : public Fenster { };
struct Texteingabe : public Komponente { };
struct Druckknopf : public Komponente {
    Color getColor() const  { return grau; }
};

Listing 15.6: Was gibt »print« aus? Die Methode »wert« kommt öfter vor.

Book listing lst-0403-book.cpp:

// https://godbolt.org/z/476G1xzKr 
#include <iostream>
struct Basis {
    int acht_ = 8;
    int wert() const { return acht_; }
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
struct Print : public Basis {
    int neun_ = 9;
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
struct Wert : public Basis {
    int zehn_ = 10;
    int wert() const { return zehn_; }
};
struct Beides : public Basis {
    int elf_ = 11;
    int wert() const { return elf_; }
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
int main() {
    Basis ba{}; ba.print(std::cout);   // Basisaufruf
    Print pr{}; pr.print(std::cout);   // print überschrieben
    Wert we{}; we.print(std::cout);    // print aus Basis
    Beides be{}; be.print(std::cout);  // alles überschrieben
}

Godbolt Listing lst-0403-godb.cpp, https://godbolt.org/z/476G1xzKr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/476G1xzKr 
#include <iostream>
struct Basis {
    int acht_ = 8;
    int wert() const { return acht_; }
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
struct Print : public Basis {
    int neun_ = 9;
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
struct Wert : public Basis {
    int zehn_ = 10;
    int wert() const { return zehn_; }
};
struct Beides : public Basis {
    int elf_ = 11;
    int wert() const { return elf_; }
    void print(std::ostream& os) const { os << wert() << "\n"; }
};
int main() {
    Basis ba{}; ba.print(std::cout);   // Basisaufruf
    Print pr{}; pr.print(std::cout);   // print überschrieben
    Wert we{}; we.print(std::cout);    // print aus Basis
    Beides be{}; be.print(std::cout);  // alles überschrieben
}

Listing 15.7: Mit »virtual« markierte Methoden werden zur Laufzeit aufgelöst.

Book listing lst-0404-book.cpp:

// https://godbolt.org/z/aj8cnox4f 
#include <iostream>

using std::ostream; using std::cout;
struct Basis2 {
    int acht_ = 8;
    virtual int wert() const          // virtuelle Methode
        { return acht_; }
    void print(ostream& os) const
        { os << wert() << "\n"; }
};
struct Wert2 : public Basis2 {
    int zehn_ = 10;
    virtual int wert() const override // überschreiben
        { return zehn_; }
};
int main() {
    Wert2 we2{}; we2.print(cout);     // verwenden
}

Godbolt Listing lst-0404-godb.cpp, https://godbolt.org/z/aj8cnox4f:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/aj8cnox4f 
#include <iostream>

using std::ostream; using std::cout;
struct Basis2 {
    int acht_ = 8;
    virtual int wert() const          // virtuelle Methode
        { return acht_; }
    void print(ostream& os) const
        { os << wert() << "\n"; }
};
struct Wert2 : public Basis2 {
    int zehn_ = 10;
    virtual int wert() const override // überschreiben
        { return zehn_; }
};
int main() {
    Wert2 we2{}; we2.print(cout);     // verwenden
}

Listing 15.8: Die abgeleitete Klasse erbt Methoden, aber nicht Konstruktoren der Elternklasse.

Book listing lst-0406-book.cpp:

// https://godbolt.org/z/57vexTPnn 
class Base {
public:
    Base() {}                 // null-Argument-Konstruktor
    explicit Base(int i) {}   // ein Argument
    Base(int i, int j) {}     // zwei Argumente
    void func() {};           // Methode
};

class Derived : public Base { // kein eigener Konstruktor
};

int main() {
    Base b0{};                // okay, null-Argument-Konstruktor
    Base b1{12};              // okay, ein Argument
    Base b2{6,18};            // okay, zwei Argumente
    Derived d0{};             // okay, Compiler generiert Defaultkonstruktor
    d0.func();                // okay, Methode wird geerbt
    Derived d1{7};            //                 (ERR)                 Fehler: kein Konstruktor für ein Argument
    Derived d2{3,13};         //                 (ERR)                 Fehler: kein Konstruktor für zwei Argumente
}

Godbolt Listing lst-0406-godb.cpp, https://godbolt.org/z/57vexTPnn:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/57vexTPnn 
class Base {
public:
    Base() {}                 // null-Argument-Konstruktor
    explicit Base(int i) {}   // ein Argument
    Base(int i, int j) {}     // zwei Argumente
    void func() {};           // Methode
};

class Derived : public Base { // kein eigener Konstruktor
};

int main() {
    Base b0{};                // okay, null-Argument-Konstruktor
    Base b1{12};              // okay, ein Argument
    Base b2{6,18};            // okay, zwei Argumente
    Derived d0{};             // okay, Compiler generiert Defaultkonstruktor
    d0.func();                // okay, Methode wird geerbt
    Derived d1{7};            //                 (ERR)                 Fehler: kein Konstruktor für ein Argument
    Derived d2{3,13};         //                 (ERR)                 Fehler: kein Konstruktor für zwei Argumente
}

Listing 15.9: Mit »using« importieren Sie alle Konstruktoren der Elternklasse.

Book listing lst-0407-book.cpp:

// https://godbolt.org/z/8b3Yvnjh4 
class Base {
public:
    Base() {}
    explicit Base(int i) {}
    Base(int i, int j) {}
    void func() {};           // Methode
};

class Derived : public Base {
public:
    using Base::Base;         // Importieren aller Konstruktoren der Elternklasse
};

int main() {
    Derived d0{};             // okay, importiert, nicht mehr generiert
    Derived d1{7};            // okay, wurde importiert
    Derived d2{3,13};         // okay, wurde importiert
}

Godbolt Listing lst-0407-godb.cpp, https://godbolt.org/z/8b3Yvnjh4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8b3Yvnjh4 
class Base {
public:
    Base() {}
    explicit Base(int i) {}
    Base(int i, int j) {}
    void func() {};           // Methode
};

class Derived : public Base {
public:
    using Base::Base;         // Importieren aller Konstruktoren der Elternklasse
};

int main() {
    Derived d0{};             // okay, importiert, nicht mehr generiert
    Derived d1{7};            // okay, wurde importiert
    Derived d2{3,13};         // okay, wurde importiert
}

Listing 15.10: Die Übergabe als Wert kopiert nur den gemeinsamen Teil des Typs.

Book listing lst-0408-book.cpp:

// https://godbolt.org/z/jfocr7qf1 
//… Basis2 und Wert2 wie gehabt …
void ausgabe(Basis2 x) {        // Übergabe als Wert
    x.print(cout);
}
int main() {
    Basis2 ba2{}; ausgabe(ba2); // gibt 8 aus
    Wert2 we2{}; ausgabe(we2);  // gibt auch 8 aus
}

Godbolt Listing lst-0408-godb.cpp, https://godbolt.org/z/jfocr7qf1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jfocr7qf1 
//… Basis2 und Wert2 wie gehabt …
void ausgabe(Basis2 x) {        // Übergabe als Wert
    x.print(cout);
}
int main() {
    Basis2 ba2{}; ausgabe(ba2); // gibt 8 aus
    Wert2 we2{}; ausgabe(we2);  // gibt auch 8 aus
}

Listing 15.11: Die abgeleitete Klasse als Argumenttyp zu einer Funktion erlaubt nicht den Aufruf mit einer Variable der Basisklasse als Wertparameter.

Book listing lst-0409-book.cpp:

// https://godbolt.org/z/j9Er3s1xo 
//… Basis2 und Wert2 wie gehabt …
void ausgabe(Wert2 x) {         // abgeleitete Klasse als Wert
    x.print(cout);
}
int main() {
    Basis2 ba2{}; ausgabe(ba2); //                 (ERR)  ba2 kann nicht in Wert2 umgewandelt werden
    Wert2 we2{}; ausgabe(we2);  // gibt 10 aus
}

Godbolt Listing lst-0409-godb.cpp, https://godbolt.org/z/j9Er3s1xo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/j9Er3s1xo 
//… Basis2 und Wert2 wie gehabt …
void ausgabe(Wert2 x) {         // abgeleitete Klasse als Wert
    x.print(cout);
}
int main() {
    Basis2 ba2{}; ausgabe(ba2); //                 (ERR)  ba2 kann nicht in Wert2 umgewandelt werden
    Wert2 we2{}; ausgabe(we2);  // gibt 10 aus
}

Listing 15.12: Die Übergabe als Referenz verändert die Instanz nicht.

Book listing lst-0410-book.cpp:

// https://godbolt.org/z/3nvrvrrYW 
//… Basis2 und Wert2 wie gehabt …
void ausgabe(Basis2& x) {       // Übergabe als Referenz
    x.print(cout);
}

int main() {
    Basis2 ba2{}; ausgabe(ba2); // gibt 8 aus
    Wert2 we2{}; ausgabe(we2);  // gibt 10 aus, denn das Objekt wird nicht kopiert
}

Godbolt Listing lst-0410-godb.cpp, https://godbolt.org/z/3nvrvrrYW:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3nvrvrrYW 
//… Basis2 und Wert2 wie gehabt …
void ausgabe(Basis2& x) {       // Übergabe als Referenz
    x.print(cout);
}

int main() {
    Basis2 ba2{}; ausgabe(ba2); // gibt 8 aus
    Wert2 we2{}; ausgabe(we2);  // gibt 10 aus, denn das Objekt wird nicht kopiert
}

Listing 16.1: Welche Variablen können Sie bei »x1« bis »x5« einsetzen?

Book listing lst-0411-book.cpp:

// https://godbolt.org/z/K7TqWrjbo 
struct MeinWert { /* irgendwas */ };
MeinWert globalWert{};                    // globale Klasseninstanz

void funktion(const MeinWert &paramRef) {
    if( /*...*/ ) funktion( /*x1?*/ );        // irgendeine Funktion aufrufen
    MeinWert lokalWert{};                 // lokale Klasseninstanz
}                                         // Ende der Funktion

int main() {
    MeinWert mwert1{};
    funktion( /*x2?*/ );
    funktion( MeinWert{} );               // temporärer Wert
    {
        MeinWert mwert2{};
        funktion( /*x3?*/ );
        MeinWert mwert3{};
    }                                     // Ende des inneren Blocks
    funktion( /*x4?*/ );
    MeinWert mwert4{};
    funktion( /*x5?*/ );
}                                         // Ende der main-Funktion

Godbolt Listing lst-0411-godb.cpp, https://godbolt.org/z/K7TqWrjbo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/K7TqWrjbo 
struct MeinWert { /* irgendwas */ };
MeinWert globalWert{};                    // globale Klasseninstanz

void funktion(const MeinWert &paramRef) {
    if( /*...*/ ) funktion( /*x1?*/ );        // irgendeine Funktion aufrufen
    MeinWert lokalWert{};                 // lokale Klasseninstanz
}                                         // Ende der Funktion

int main() {
    MeinWert mwert1{};
    funktion( /*x2?*/ );
    funktion( MeinWert{} );               // temporärer Wert
    {
        MeinWert mwert2{};
        funktion( /*x3?*/ );
        MeinWert mwert3{};
    }                                     // Ende des inneren Blocks
    funktion( /*x4?*/ );
    MeinWert mwert4{};
    funktion( /*x5?*/ );
}                                         // Ende der main-Funktion

Listing 16.2: Wenn Sie eine Funktion mit einem Parameter aufrufen, für den der Compiler zur Umwandlung einen Konstruktor aufruft, erzeugt er einen Tempwert.

Book listing lst-0412-book.cpp:

// https://godbolt.org/z/TvKP7Ghvh 
#include <string>
#include <iostream>                      // cout
using std::string; using std::cout;

struct Value {
    int wert_;
    Value(int wert)                      // 1-Arg-Konstruktor = Typumwandlung
        : wert_{wert} {}
};

size_t laenge(string arg) {
    return arg.size();
}
Value doppel(Value v) {
    return Value{ v.wert_*2 };
}
int main() {
    cout << laenge("Hipphopp") << "\n";  // const char* in string
    cout << doppel(10).wert_ << "\n";    // int in Value
    string name {"Gandalf"};
    cout << ( name + " der Graue" ) << "\n"; // string + const char*
}

Godbolt Listing lst-0412-godb.cpp, https://godbolt.org/z/TvKP7Ghvh:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TvKP7Ghvh 
#include <string>
#include <iostream>                      // cout
using std::string; using std::cout;

struct Value {
    int wert_;
    Value(int wert)                      // 1-Arg-Konstruktor = Typumwandlung
        : wert_{wert} {}
};

size_t laenge(string arg) {
    return arg.size();
}
Value doppel(Value v) {
    return Value{ v.wert_*2 };
}
int main() {
    cout << laenge("Hipphopp") << "\n";  // const char* in string
    cout << doppel(10).wert_ << "\n";    // int in Value
    string name {"Gandalf"};
    cout << ( name + " der Graue" ) << "\n"; // string + const char*
}

Listing 16.3: Ein Destruktor wird beim Entfernen eines Objekts ausgeführt.

Book listing lst-0413-book.cpp:

// https://godbolt.org/z/qzbnK9v1o 
#include <string>
#include <iostream>
#include <iomanip>   // setw
using std::cout; using std::setw; using std::string;
struct MeinWert {
    static int zaehler;              // static: existiert nur einmal für alle Instanzen
    int nummer_;                     // Einrücktiefe dieser Instanz für die Ausgabe
    string name_;                    // Name dieser Instanz für die Ausgabe
    explicit MeinWert(string name)
        : nummer_{++zaehler}         // Zähler für Einrücktiefe pro Instanz hochzählen
        , name_{name}               // Name des Objekts für Ausgabe merken
    {
        cout << setw(nummer_) << " " // nummer_ verwenden für Einrücktiefe
             << "Konstruktor " << name_ << "\n"; // Instanzname ausgeben        }
    ~MeinWert() {                    // Destruktor
        cout << setw(nummer_) << " " << "Destruktor " << name_ << "\n";
    }
};
int MeinWert::zaehler = 0;           // Initialisierung der statischen Klassenvariablen

Godbolt Listing lst-0413-godb.cpp, https://godbolt.org/z/qzbnK9v1o:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qzbnK9v1o 
#include <string>
#include <iostream>
#include <iomanip>   // setw
using std::cout; using std::setw; using std::string;
struct MeinWert {
    static int zaehler;              // static: existiert nur einmal für alle Instanzen
    int nummer_;                     // Einrücktiefe dieser Instanz für die Ausgabe
    string name_;                    // Name dieser Instanz für die Ausgabe
    explicit MeinWert(string name)
        : nummer_{++zaehler}         // Zähler für Einrücktiefe pro Instanz hochzählen
        , name_{name}               // Name des Objekts für Ausgabe merken
    {
        cout << setw(nummer_) << " " // nummer_ verwenden für Einrücktiefe
             << "Konstruktor " << name_ << "\n"; // Instanzname ausgeben        }
    ~MeinWert() {                    // Destruktor
        cout << setw(nummer_) << " " << "Destruktor " << name_ << "\n";
    }
};
int MeinWert::zaehler = 0;           // Initialisierung der statischen Klassenvariablen

Listing 16.4: Hier werden viele Objekte erzeugt und zerstört.

Book listing lst-0414-book.cpp:

// https://godbolt.org/z/oY953arPj 
void funktion(const MeinWert &paramRef) {
    MeinWert lokalWert{"lokal"};
}

int main() {
    MeinWert mwert1{"mwert1"};
    funktion( MeinWert{"temp"} );
    funktion( mwert1 );
    {
        MeinWert mwert2{"mwert2"};
    }
}

Godbolt Listing lst-0414-godb.cpp, https://godbolt.org/z/oY953arPj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oY953arPj 
void funktion(const MeinWert &paramRef) {
    MeinWert lokalWert{"lokal"};
}

int main() {
    MeinWert mwert1{"mwert1"};
    funktion( MeinWert{"temp"} );
    funktion( mwert1 );
    {
        MeinWert mwert2{"mwert2"};
    }
}

Listing 16.5: Diese Ausgabe zeigt, wann Objekte erzeugt und zerstört werden.

Book listing lst-0415-book.cpp:

Konstruktor mwert1
 Konstruktor temp
  Konstruktor lokal
  Destruktor lokal
 Destruktor temp
   Konstruktor lokal
   Destruktor lokal
    Konstruktor mwert2
    Destruktor mwert2
Destruktor mwert1

Listing 16.6: Ein einfaches Beispiel für eine C-Schnittstelle zu einer Ressource

Book listing lst-0416-book.cpp:

// https://godbolt.org/z/54dzsb31z 
#ifndef DATABASE_HPP
#define DATABASE_HPP

typedef void* db_handle_t;

db_handle_t db_open(const char* filename);
void db_close(db_handle_t db);
int db_execute(db_handle_t db, const char* query);

#endif

Godbolt Listing lst-0416-godb.cpp, https://godbolt.org/z/54dzsb31z:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/54dzsb31z 
#ifndef DATABASE_HPP
#define DATABASE_HPP

typedef void* db_handle_t;

db_handle_t db_open(const char* filename);
void db_close(db_handle_t db);
int db_execute(db_handle_t db, const char* query);

#endif

Listing 16.7: Wenn Sie eine Ressource schließen müssen, dann eignet sich dafür der Destruktor.

Book listing lst-0417-book.cpp:

// https://godbolt.org/z/93PT8W9hY 
#include <iostream>              // cout
#include "database.hpp"          // Einbinden der fremden Programmierschnittstelle
class Database {
    db_handle_t db_;             // eingepackte Ressource
public:
    Database(const char* filename);
    ~Database();
    int execute(const char* query);
};
Database::Database(const char* filename)
    : db_{db_open(filename)}     // Anfordern der Ressource
    { }
Database::~Database() {
    db_close(db_);               // Freigeben der Ressource
}
int Database::execute(const char* query) {
    return db_execute(db_, query); // Nutzen der Ressource
}
int main() {
    Database db{ "kunden.dat" };   // Erzeugen des Wrappers
    std::cout << "Anzahl: "<< db.execute("select * from kunden") << "\n";
}                                  // automatisches Entfernen des Wrappers

Godbolt Listing lst-0417-godb.cpp, https://godbolt.org/z/93PT8W9hY:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/93PT8W9hY 
#include <iostream>              // cout
#include "database.hpp"          // Einbinden der fremden Programmierschnittstelle
class Database {
    db_handle_t db_;             // eingepackte Ressource
public:
    Database(const char* filename);
    ~Database();
    int execute(const char* query);
};
Database::Database(const char* filename)
    : db_{db_open(filename)}     // Anfordern der Ressource
    { }
Database::~Database() {
    db_close(db_);               // Freigeben der Ressource
}
int Database::execute(const char* query) {
    return db_execute(db_, query); // Nutzen der Ressource
}
int main() {
    Database db{ "kunden.dat" };   // Erzeugen des Wrappers
    std::cout << "Anzahl: "<< db.execute("select * from kunden") << "\n";
}                                  // automatisches Entfernen des Wrappers

Listing 16.8: Der Konstruktor initialisiert oder löst eine Exception aus.

Book listing lst-0418-book.cpp:

Database::Database(const char* filename)
    : db_{ db_open(filename) }
    {
        if(nullptr == db_) { // Fehler beim Öffnen
            throw IllegalArgumentException("Fehler beim Oeffnen der DB");
        }
    }

Listing 16.9: Beispiele für Yoda-Bedingungen mit »==«

Book listing lst-0420-book.cpp:

if("Yoda" == character) 
if(42 == antwort) 

Listing 16.10: Eine Yoda-Bedingung mit einem Methodenaufruf

Book listing lst-0421-book.cpp:

// https://godbolt.org/z/c3695v4r8 
#include "mein_string.hpp"
static const mein_string ZEBRA { "zebra" };
int main() {
    mein_string tier{ "pferd" };
    if(ZEBRA.equals(tier)) return 0;
    else return 1;
}

Godbolt Listing lst-0421-godb.cpp, https://godbolt.org/z/c3695v4r8:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/c3695v4r8 
#include "mein_string.hpp"
static const mein_string ZEBRA { "zebra" };
int main() {
    mein_string tier{ "pferd" };
    if(ZEBRA.equals(tier)) return 0;
    else return 1;
}

Listing 16.11: Der Konstruktor von »KannWerfen« kann mit einer Exception beendet werden.

Book listing lst-0422-book.cpp:

// https://godbolt.org/z/vaP4bdvns 
#include <iostream> // cout
#include <stdexcept> // runtime_error
struct KannWerfen {
    KannWerfen(int wasSollPassieren) {
        std::cout << "Konstruktor " << wasSollPassieren << "...\n";
        if(wasSollPassieren == 666)
            throw std::runtime_error("Testfehler");
        std::cout << "...Konstruktor fertig\n";
    }
    ~KannWerfen() {
        std::cout << "Destruktor.\n";
    }
};
int main() {
    try {
        KannWerfen kw1{0};               // okay, löst keine Ausnahme aus
    } catch(std::runtime_error &exc) {
        std::cout << "Gefangen-1: " << exc.what() << "\n";
    }
    try {
        KannWerfen kw2{666};             // löst aus, kw2 wird nicht erzeugt
    } catch(std::runtime_error &exc) {
        std::cout << "Gefangen-2: " << exc.what() << "\n";
    }
}

Godbolt Listing lst-0422-godb.cpp, https://godbolt.org/z/vaP4bdvns:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vaP4bdvns 
#include <iostream> // cout
#include <stdexcept> // runtime_error
struct KannWerfen {
    KannWerfen(int wasSollPassieren) {
        std::cout << "Konstruktor " << wasSollPassieren << "...\n";
        if(wasSollPassieren == 666)
            throw std::runtime_error("Testfehler");
        std::cout << "...Konstruktor fertig\n";
    }
    ~KannWerfen() {
        std::cout << "Destruktor.\n";
    }
};
int main() {
    try {
        KannWerfen kw1{0};               // okay, löst keine Ausnahme aus
    } catch(std::runtime_error &exc) {
        std::cout << "Gefangen-1: " << exc.what() << "\n";
    }
    try {
        KannWerfen kw2{666};             // löst aus, kw2 wird nicht erzeugt
    } catch(std::runtime_error &exc) {
        std::cout << "Gefangen-2: " << exc.what() << "\n";
    }
}

Listing 16.12: Teilweise initialisierte Datenfelder werden auch bei einer Exception weggeräumt.

Book listing lst-0423-book.cpp:

class Mega {
    std::vector<int>     data_;
    KannWerfen           kannWerfen_;
    std::map<string,int> mehr_;
public:
    Mega()
      : data_{}
      , kannWerfen_{666}  // löst eine Exception aus
      , mehr_{}
      { }
};

Listing 16.13: Die Übergabe als Wert erstellt Objekte mit dem vom Compiler erzeugten Kopierkonstruktor.

Book listing lst-0424-book.cpp:

// https://godbolt.org/z/KGEe7hj1b 
void funktion(MeinWert paramWert) {
    std::cout << "(funktion)\n";
    MeinWert lokalWert{"lokal"};
}
int main() {
    MeinWert mwert1{"mwert1"};
    funktion( MeinWert{"temp"} );
    funktion( mwert1 );
    {
        MeinWert mwert2{"mwert2"};
    }
}

Godbolt Listing lst-0424-godb.cpp, https://godbolt.org/z/KGEe7hj1b:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KGEe7hj1b 
void funktion(MeinWert paramWert) {
    std::cout << "(funktion)\n";
    MeinWert lokalWert{"lokal"};
}
int main() {
    MeinWert mwert1{"mwert1"};
    funktion( MeinWert{"temp"} );
    funktion( mwert1 );
    {
        MeinWert mwert2{"mwert2"};
    }
}

Listing 16.14: Der Kopierkonstruktor bekommt eine konstante Referenz der Klasse als Argument.

Book listing lst-0425-book.cpp:

// https://godbolt.org/z/j67W4zPWE 
struct MeinWert {
   static int zaehler;
   int nummer_;
   string name_;
   explicit MeinWert(string name) // wie zuvor
      : nummer_{++zaehler} , name_{name}
      { cout << setw(nummer_) << '_'  << "Konstruktor " << name_ << "\n"; }
   MeinWert(const MeinWert &orig) // neuer Kopierkonstruktor
      : nummer_{++zaehler} , name_{orig.name_ + "-Kopie"}
      { cout << setw(nummer_)<<" " << "Kopierkonstruktor " << name_ << "\n"; }
   ~MeinWert() { // wie zuvor
      cout << setw(nummer_)<<" " << "Destruktor " << name_ << "\n";
   }
};
int MeinWert::zaehler = 0;

Godbolt Listing lst-0425-godb.cpp, https://godbolt.org/z/j67W4zPWE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/j67W4zPWE 
struct MeinWert {
   static int zaehler;
   int nummer_;
   string name_;
   explicit MeinWert(string name) // wie zuvor
      : nummer_{++zaehler} , name_{name}
      { cout << setw(nummer_) << '_'  << "Konstruktor " << name_ << "\n"; }
   MeinWert(const MeinWert &orig) // neuer Kopierkonstruktor
      : nummer_{++zaehler} , name_{orig.name_ + "-Kopie"}
      { cout << setw(nummer_)<<" " << "Kopierkonstruktor " << name_ << "\n"; }
   ~MeinWert() { // wie zuvor
      cout << setw(nummer_)<<" " << "Destruktor " << name_ << "\n";
   }
};
int MeinWert::zaehler = 0;

Listing 16.15: Kopie und Zuweisung

Book listing lst-0426-book.cpp:

void byVal(MeinWert arg) { }
int main() {
    MeinWert wert1{"ABCD"}; // neue Instanz, konstruiert per string
    MeinWert wert2{wert1};  // neue Instanz, konstruiert per Kopie
    MeinWert wert3 = wert1; // neue Instanz, ebenfalls per Kopie, trotz =
    byVal(wert1);           // eine neue Instanz per Kopie
    wert1 = wert2;          // keine neue Instanz, sondern eine Zuweisung
}

Listing 16.16: Das Schema für die Implementierung eines eigenen Zuweisungsoperators

Book listing lst-0429-book.cpp:

struct MeinWert {
    // … alles andere wie bisher
    MeinWert& operator=(const MeinWert& rechts) {
        if(this != &rechts) { // 1. auf Selbstzuweisung prüfen
            // 2. Freigeben bisheriger Ressourcen; hier keine
            // 3. elementweises Übertragen durch Zuweisung oder Ähnliches
            name_ = rechts.name_ + "-Zuweisung (zuvor " + name_ + ")";
            /* nummer_ bleibt, und damit die originale Einrückung */
        }
        return *this; // 4. sich selbst zurückgeben
    }
};

Listing 16.17: »const«-Datenelement zunächst ohne Zuweisungsoperator

Book listing lst-0430-book.cpp:

struct MeineNummer {

    const int nummer_;         // konstantes Datenfeld

    explicit MeineNummer(int v)
        : nummer_{v}           // Initialisierung des konstanten Datenfelds
        {}
};

int main() {
    MeineNummer c1{4};
    MeineNummer c2{7};
    c1 = c2;                   //             (ERR)  Fehler: Zuweisung vom Compiler gestrichen
}

Listing 16.18: Mit »= delete« entfernen Sie Operationen manuell.

Book listing lst-0431-book.cpp:

// https://godbolt.org/z/acWjozE15 
struct MeineNummer {
    int nummer_; // variables Datenfeld

    explicit MeineNummer(int v)
        : nummer_{v} {}
    MeineNummer& operator=(const MeineNummer&) = delete; // Zuweisung streichen
    MeineNummer(const MeineNummer&) = delete;            // Kopie streichen
};
int main() {
    MeineNummer c1{4};
    MeineNummer c2{7};
    c1 = c2;            //             (ERR)  Fehler – Zuweisung vom Programmierer gestrichen
    MeineNummer c3{c1}; //             (ERR)  Fehler – Kopie vom Programmierer gestrichen
}

Godbolt Listing lst-0431-godb.cpp, https://godbolt.org/z/acWjozE15:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/acWjozE15 
struct MeineNummer {
    int nummer_; // variables Datenfeld

    explicit MeineNummer(int v)
        : nummer_{v} {}
    MeineNummer& operator=(const MeineNummer&) = delete; // Zuweisung streichen
    MeineNummer(const MeineNummer&) = delete;            // Kopie streichen
};
int main() {
    MeineNummer c1{4};
    MeineNummer c2{7};
    c1 = c2;            //             (ERR)  Fehler – Zuweisung vom Programmierer gestrichen
    MeineNummer c3{c1}; //             (ERR)  Fehler – Kopie vom Programmierer gestrichen
}

Listing 16.19: Mit den gelöschten Funktionen verhindert der Compiler eine fehlerhafte Benutzung der Klasse.

Book listing lst-0432-book.cpp:

// https://godbolt.org/z/PfW8oKPK4 
#include <iostream>              // cout
#include "database.hpp"          // Einbinden der fremden Programmierschnittstelle

class Database {
    const db_handle_t db_;                         // konstant machen
public:
    Database(const char* filename);
    ~Database();
    int execute(const char* query);
    Database(const Database&) = delete;            // Kopieren verbieten
    Database& operator=(const Database&) = delete; // Zuweisung verbieten
};
// … Implementierungen wie gehabt …
int main() {
    Database db{ "kunden.dat" };
    std::cout << "Anzahl: "<< db.execute("select * from kunden") << "\n";
    Database db2{ db }; //                 (ERR)               Compiler verhindert gefährliche Kopie
    db = db2;           //                 (ERR)               Compiler verhindert gefährliche Zuweisung
}

Godbolt Listing lst-0432-godb.cpp, https://godbolt.org/z/PfW8oKPK4:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PfW8oKPK4 
#include <iostream>              // cout
#include "database.hpp"          // Einbinden der fremden Programmierschnittstelle

class Database {
    const db_handle_t db_;                         // konstant machen
public:
    Database(const char* filename);
    ~Database();
    int execute(const char* query);
    Database(const Database&) = delete;            // Kopieren verbieten
    Database& operator=(const Database&) = delete; // Zuweisung verbieten
};
// … Implementierungen wie gehabt …
int main() {
    Database db{ "kunden.dat" };
    std::cout << "Anzahl: "<< db.execute("select * from kunden") << "\n";
    Database db2{ db }; //                 (ERR)               Compiler verhindert gefährliche Kopie
    db = db2;           //                 (ERR)               Compiler verhindert gefährliche Zuweisung
}

Listing 16.20: Die Klasse enthält wahrscheinlich große Datenmengen, die teuer zu kopieren sind. Doch was wird hier kopiert?

Book listing lst-0433-book.cpp:

// https://godbolt.org/z/MT3MPs3rE 
#include <vector>
class Image {
    std::vector<std::byte> data_;
public:
    explicit Image(const char *fn) { /*...*/ }
    // Compiler generiert (u. a.): 
    // Kopierkonstruktor, Zuweisung, aber auch Verschiebungen
};
std::vector<Image> loadCollection(bool empty) {
    if(empty) return std::vector<Image>{};
    std::vector<Image> result {};                // für Rückgabe; zunächst leer
    // drei Bilder in die Sammlung … kopieren?
    result.push_back( Image{"MonaLisa.png"} );
    result.push_back( Image{"DerSchrei.png"} );
    result.push_back( Image{"JungeMitPfeife.png"} );
    return result; // Sammlung als Wert zurückgeben
}
int main() {
    // Rückgabe in Variable speichern
    std::vector<Image> sammlung = loadCollection(false);
}

Godbolt Listing lst-0433-godb.cpp, https://godbolt.org/z/MT3MPs3rE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MT3MPs3rE 
#include <vector>
class Image {
    std::vector<std::byte> data_;
public:
    explicit Image(const char *fn) { /*...*/ }
    // Compiler generiert (u. a.): 
    // Kopierkonstruktor, Zuweisung, aber auch Verschiebungen
};
std::vector<Image> loadCollection(bool empty) {
    if(empty) return std::vector<Image>{};
    std::vector<Image> result {};                // für Rückgabe; zunächst leer
    // drei Bilder in die Sammlung … kopieren?
    result.push_back( Image{"MonaLisa.png"} );
    result.push_back( Image{"DerSchrei.png"} );
    result.push_back( Image{"JungeMitPfeife.png"} );
    return result; // Sammlung als Wert zurückgeben
}
int main() {
    // Rückgabe in Variable speichern
    std::vector<Image> sammlung = loadCollection(false);
}

Listing 16.21: Implementierung der beiden Verschiebeoperationen

Book listing lst-0434-book.cpp:

// https://godbolt.org/z/6xjeYWe7c 
#include <vector>
class Image {
    std::vector<std::byte> data_;              // byte gibt es seit C++17
public:
    explicit Image(const char *fn) { /*...*/ }
    Image(Image&& other) noexcept              // Verschiebekonstruktor
        : data_{} // leer erzeugen
    {
        using std::swap;
        swap(data_, other.data_);
    }
    Image& operator=(Image&& other) noexcept { // Verschiebeoperator
        using std::swap;
        swap(data_, other.data_);
        return *this;
    }
};

Godbolt Listing lst-0434-godb.cpp, https://godbolt.org/z/6xjeYWe7c:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6xjeYWe7c 
#include <vector>
class Image {
    std::vector<std::byte> data_;              // byte gibt es seit C++17
public:
    explicit Image(const char *fn) { /*...*/ }
    Image(Image&& other) noexcept              // Verschiebekonstruktor
        : data_{} // leer erzeugen
    {
        using std::swap;
        swap(data_, other.data_);
    }
    Image& operator=(Image&& other) noexcept { // Verschiebeoperator
        using std::swap;
        swap(data_, other.data_);
        return *this;
    }
};

Listing 16.22: Infix-, Funktions- und Methodenschreibweise für Operatoren

Book listing lst-0440-book.cpp:

// https://godbolt.org/z/fefP5d343 
#include <iostream>
using std::cout; using std::ostream;
struct Widget {
    bool operator<(const Widget&) const {      // Methodenschreibweise
        return true;                           // immer true
    }
};
bool operator<(const Widget&, const Widget&) { // Funktionsschreibweise
    return false;                              // immer false
}
int main() {
    Widget x{};
    Widget y{};
    cout << (operator<(x, y)      // ruft Funktionsschreibweise auf
        ? "Methode1\n" : "Funktion1\n");
    cout << (y.operator<(x)       // ruft Methodenschreibweise auf
        ? "Methode2\n" : "Funktion2\n");
    cout << (x < y                // Infix-Schreibweise, lässt die Wahl, hier Methode
        ? "Methode3\n" : "Funktion3\n");
}

Godbolt Listing lst-0440-godb.cpp, https://godbolt.org/z/fefP5d343:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fefP5d343 
#include <iostream>
using std::cout; using std::ostream;
struct Widget {
    bool operator<(const Widget&) const {      // Methodenschreibweise
        return true;                           // immer true
    }
};
bool operator<(const Widget&, const Widget&) { // Funktionsschreibweise
    return false;                              // immer false
}
int main() {
    Widget x{};
    Widget y{};
    cout << (operator<(x, y)      // ruft Funktionsschreibweise auf
        ? "Methode1\n" : "Funktion1\n");
    cout << (y.operator<(x)       // ruft Methodenschreibweise auf
        ? "Methode2\n" : "Funktion2\n");
    cout << (x < y                // Infix-Schreibweise, lässt die Wahl, hier Methode
        ? "Methode3\n" : "Funktion3\n");
}

Listing 16.23: Eine »friend«-Funktion ist keine Methode, auch wenn sie innerhalb der Klasse steht oder dort definiert ist.

Book listing lst-0441-book.cpp:

// https://godbolt.org/z/Wvr3aK75G 
#include <compare>              // für <=>
class Value {
    // Wenn Sie class verwenden, geht es mit Privatem los.
    int value_; 
public:
    explicit Value(int value) : value_{value} {}

    // freie Funktionen, aber als friend deklariert
    friend Value operator+(const Value& li, const Value& re);
    friend Value operator-(const Value& li, const Value& re)
        { return Value{li.value_ - re.value_};  // innerhalb auch definiert
    }
    // operator<=> braucht nicht friend zu sein.
    // für alle Vergleiche: <, >, <=, >= sowie == und !=
    auto operator<=>(const Value& re) const = default; 
};

// Definition der zuvor deklarierten friend-Funktion:
Value operator+(const Value& li, const Value& re) {
    return Value{li.value_ + re.value_}; // Zugriff auf Privates erlaubt
}

int main() {
    Value sieben{7}; Value drei{3}; Value zwei{2};
    if((drei+zwei) < sieben) {    // operator+, dann operarator< via <=>
        return 0;                 // okay
    } else {
        return 1;                 // etwas ist falsch gelaufen
    }
}

Godbolt Listing lst-0441-godb.cpp, https://godbolt.org/z/Wvr3aK75G:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Wvr3aK75G 
#include <compare>              // für <=>
class Value {
    // Wenn Sie class verwenden, geht es mit Privatem los.
    int value_; 
public:
    explicit Value(int value) : value_{value} {}

    // freie Funktionen, aber als friend deklariert
    friend Value operator+(const Value& li, const Value& re);
    friend Value operator-(const Value& li, const Value& re)
        { return Value{li.value_ - re.value_};  // innerhalb auch definiert
    }
    // operator<=> braucht nicht friend zu sein.
    // für alle Vergleiche: <, >, <=, >= sowie == und !=
    auto operator<=>(const Value& re) const = default; 
};

// Definition der zuvor deklarierten friend-Funktion:
Value operator+(const Value& li, const Value& re) {
    return Value{li.value_ + re.value_}; // Zugriff auf Privates erlaubt
}

int main() {
    Value sieben{7}; Value drei{3}; Value zwei{2};
    if((drei+zwei) < sieben) {    // operator+, dann operarator< via <=>
        return 0;                 // okay
    } else {
        return 1;                 // etwas ist falsch gelaufen
    }
}

Listing 16.24: Ein beinahe mit allen Operatoren voll ausgerüsteter Datentyp

Book listing lst-0442-book.cpp:

// https://godbolt.org/z/Gf38nTa1q 
#include <iostream>  // istream, ostream, cout
class Num {
  int val_ = 0;
public:
  int& operator*();  // Dereferenzieren: Zugriff auf den Wert direkt erhalten
  const int& operator*() const; // Dereferenzieren: Lesezugriff auf den Wert
  Num() {}
  explicit Num(int value) : val_{value} {}
  // einstellige Operatoren
  Num& operator++(); // Pre-Inkrement
  Num& operator--(); // Pre-Dekrement
  Num operator+();   // Positiv
  Num operator-();   // Negieren
  Num operator~();   // bitweises Invertieren
  // zweistellige Operatoren
  // - zusammengesetzte Zuweisungen, arithmetisch
  Num& operator+=(const Num& re) { val_ += *re; return *this; }
  Num& operator-=(const Num& re) { val_ -= *re; return *this; }
  Num& operator*=(const Num& re) { val_ *= *re; return *this; }
  Num& operator/=(const Num& re) { val_ /= *re; return *this; }
  Num& operator%=(const Num& re) { val_ %= *re; return *this; }
  // - zusammengesetzte Zuweisungen, bitweise
  Num& operator|=(const Num& re) { val_ |= *re; return *this; }
  Num& operator&=(const Num& re) { val_ &= *re; return *this; }
  Num& operator^=(const Num& re) { val_ ^= *re; return *this; }
  Num& operator<<=(int n) { val_ <<= n; return *this; }
  Num& operator>>=(int n) { val_ >>= n; return *this; }
  // - Variation zusammengesetzter Zuweisungen, für einfachere Bedienung
  Num& operator+=(int re) { val_ += re; return *this; }
  Num& operator-=(int re) { val_ -= re; return *this; }
  // zweistellige Operatoren, mit Call-by-Value für den ersten Parameter
  // und die die zusammengesetzte Zuweisung zu Hilfe nehmen
  // - Arithmetik
  friend Num operator+(Num li, const Num& re) { return li += re; }
  friend Num operator-(Num li, const Num& re) { return li -= re; }
  friend Num operator*(Num li, const Num& re) { return li *= re; }
  friend Num operator/(Num li, const Num& re) { return li /= re; }
  friend Num operator%(Num li, const Num& re) { return li %= re; }
  // - bitweise
  friend Num operator|(Num li, const Num& re) { return li |= re; }
  friend Num operator&(Num li, const Num& re) { return li &= re; }
  friend Num operator^(Num li, const Num& re) { return li ^= re; }
  // - Vergleiche
  // - … fundamental für Standardcontainer und -algorithmen
  friend bool operator==(const Num& li, const Num& re) { return *li == *re; }
  auto operator<=>(const Num& re) const {return val_ <=> *re; } // C++20
  // - Ein- und Ausgabe
  friend std::ostream& operator<<(std::ostream& os, const Num& arg);
  friend std::istream& operator>>(std::istream& is,  Num& arg);
};
// einstellige Operatoren
Num& Num::operator++() { ++val_; return *this; }
Num& Num::operator--() { --val_; return *this; }
Num Num::operator+() { return Num{val_}; }
Num Num::operator-() { return Num{-val_}; }
Num Num::operator~() { return Num{~val_}; }
int& Num::operator*() { return val_; }
const int& Num::operator*() const { return val_; }
// Ein- und Ausgabe
std::ostream& operator<<(std::ostream&os, const Num& arg) { return os<<*arg; }
std::istream& operator>>(std::istream&is, Num& arg) { return is>>*arg; }

Godbolt Listing lst-0442-godb.cpp, https://godbolt.org/z/Gf38nTa1q:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gf38nTa1q 
#include <iostream>  // istream, ostream, cout
class Num {
  int val_ = 0;
public:
  int& operator*();  // Dereferenzieren: Zugriff auf den Wert direkt erhalten
  const int& operator*() const; // Dereferenzieren: Lesezugriff auf den Wert
  Num() {}
  explicit Num(int value) : val_{value} {}
  // einstellige Operatoren
  Num& operator++(); // Pre-Inkrement
  Num& operator--(); // Pre-Dekrement
  Num operator+();   // Positiv
  Num operator-();   // Negieren
  Num operator~();   // bitweises Invertieren
  // zweistellige Operatoren
  // - zusammengesetzte Zuweisungen, arithmetisch
  Num& operator+=(const Num& re) { val_ += *re; return *this; }
  Num& operator-=(const Num& re) { val_ -= *re; return *this; }
  Num& operator*=(const Num& re) { val_ *= *re; return *this; }
  Num& operator/=(const Num& re) { val_ /= *re; return *this; }
  Num& operator%=(const Num& re) { val_ %= *re; return *this; }
  // - zusammengesetzte Zuweisungen, bitweise
  Num& operator|=(const Num& re) { val_ |= *re; return *this; }
  Num& operator&=(const Num& re) { val_ &= *re; return *this; }
  Num& operator^=(const Num& re) { val_ ^= *re; return *this; }
  Num& operator<<=(int n) { val_ <<= n; return *this; }
  Num& operator>>=(int n) { val_ >>= n; return *this; }
  // - Variation zusammengesetzter Zuweisungen, für einfachere Bedienung
  Num& operator+=(int re) { val_ += re; return *this; }
  Num& operator-=(int re) { val_ -= re; return *this; }
  // zweistellige Operatoren, mit Call-by-Value für den ersten Parameter
  // und die die zusammengesetzte Zuweisung zu Hilfe nehmen
  // - Arithmetik
  friend Num operator+(Num li, const Num& re) { return li += re; }
  friend Num operator-(Num li, const Num& re) { return li -= re; }
  friend Num operator*(Num li, const Num& re) { return li *= re; }
  friend Num operator/(Num li, const Num& re) { return li /= re; }
  friend Num operator%(Num li, const Num& re) { return li %= re; }
  // - bitweise
  friend Num operator|(Num li, const Num& re) { return li |= re; }
  friend Num operator&(Num li, const Num& re) { return li &= re; }
  friend Num operator^(Num li, const Num& re) { return li ^= re; }
  // - Vergleiche
  // - … fundamental für Standardcontainer und -algorithmen
  friend bool operator==(const Num& li, const Num& re) { return *li == *re; }
  auto operator<=>(const Num& re) const {return val_ <=> *re; } // C++20
  // - Ein- und Ausgabe
  friend std::ostream& operator<<(std::ostream& os, const Num& arg);
  friend std::istream& operator>>(std::istream& is,  Num& arg);
};
// einstellige Operatoren
Num& Num::operator++() { ++val_; return *this; }
Num& Num::operator--() { --val_; return *this; }
Num Num::operator+() { return Num{val_}; }
Num Num::operator-() { return Num{-val_}; }
Num Num::operator~() { return Num{~val_}; }
int& Num::operator*() { return val_; }
const int& Num::operator*() const { return val_; }
// Ein- und Ausgabe
std::ostream& operator<<(std::ostream&os, const Num& arg) { return os<<*arg; }
std::istream& operator>>(std::istream&is, Num& arg) { return is>>*arg; }

Listing 16.25: Sie verwenden den mit Operatoren ausgestatteten Datentyp wie gewohnt.

Book listing lst-0443-book.cpp:

// https://godbolt.org/z/asaYr3ox6 
#include <iostream>                      // cout
int main() {
    using std::cout;
    Num a{1};
    *a = 7;                              // operator* liefert auch int&
    a += Num{3};                         // Inkrement mit Num
    cout << ( ++( ++a ) ) << "\n";       // Ausgabe: 12
    a -= 2;                              // Variation mit int
    cout << --(--a) << "\n";             // Ausgabe: 8
    Num b{99};
    cout << (a<b ? "ja\n" : "xxx\n");    // Ausgabe: ja
    cout << (a>b ? "xxx\n" : "nein\n");  // Ausgabe: nein
    b /= Num{3};          // b: 33
    b %= Num{10};         // b: 3
    b <<= 4;              // b: 48
    b >>= 2;              // b: 12
    Num c = b / Num{3} + a * Num{2}; // c: 20
}

Godbolt Listing lst-0443-godb.cpp, https://godbolt.org/z/asaYr3ox6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/asaYr3ox6 
#include <iostream>                      // cout
int main() {
    using std::cout;
    Num a{1};
    *a = 7;                              // operator* liefert auch int&
    a += Num{3};                         // Inkrement mit Num
    cout << ( ++( ++a ) ) << "\n";       // Ausgabe: 12
    a -= 2;                              // Variation mit int
    cout << --(--a) << "\n";             // Ausgabe: 8
    Num b{99};
    cout << (a<b ? "ja\n" : "xxx\n");    // Ausgabe: ja
    cout << (a>b ? "xxx\n" : "nein\n");  // Ausgabe: nein
    b /= Num{3};          // b: 33
    b %= Num{10};         // b: 3
    b <<= 4;              // b: 48
    b >>= 2;              // b: 12
    Num c = b / Num{3} + a * Num{2}; // c: 20
}

Listing 16.26: Dieser Datentyp demonstriert die booleschen Operatoren.

Book listing lst-0444-book.cpp:

// https://godbolt.org/z/ojeh8Gzcx 
#include <iostream>               // istream, ostream, cout
class Bool {
    bool val_ = false;
    bool& operator*()             // dereferenzieren; veränderbar
        { return val_; };
    const bool& operator*() const // dereferenzieren; nur lesen
        { return val_; }
public:
    constexpr Bool() {}
    explicit constexpr Bool(bool value)
        : val_{value} {}
    // einstellige Operatoren
    Bool operator!() const        // Nicht-Operator
        { return Bool{!val_}; };
    // zweistellige Operatoren
    friend Bool operator&&(const Bool &re, const Bool &li)
        { return Bool{*re && *li}; }
    friend Bool operator||(const Bool &re, const Bool &li)
        { return Bool{*re || *li}; }
    // Ein- und Ausgabe
    friend std::ostream& operator<<(std::ostream& os, const Bool& arg);
    friend std::istream& operator>>(std::istream& is,  Bool& arg);
};
std::ostream& operator<<(std::ostream& os, const Bool& arg)
    { return os << *arg; }
std::istream& operator>>(std::istream& is, Bool& arg)
    { return is >> *arg; }
// Konstanten
static constexpr Bool False{false};
static constexpr Bool True{true};
int main() {
    Bool jein = True && ( Bool{false} || !Bool{} ); // verwendet &&, || und !
    std::cout << jein << "\n"; // Ausgabe: 1
}

Godbolt Listing lst-0444-godb.cpp, https://godbolt.org/z/ojeh8Gzcx:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ojeh8Gzcx 
#include <iostream>               // istream, ostream, cout
class Bool {
    bool val_ = false;
    bool& operator*()             // dereferenzieren; veränderbar
        { return val_; };
    const bool& operator*() const // dereferenzieren; nur lesen
        { return val_; }
public:
    constexpr Bool() {}
    explicit constexpr Bool(bool value)
        : val_{value} {}
    // einstellige Operatoren
    Bool operator!() const        // Nicht-Operator
        { return Bool{!val_}; };
    // zweistellige Operatoren
    friend Bool operator&&(const Bool &re, const Bool &li)
        { return Bool{*re && *li}; }
    friend Bool operator||(const Bool &re, const Bool &li)
        { return Bool{*re || *li}; }
    // Ein- und Ausgabe
    friend std::ostream& operator<<(std::ostream& os, const Bool& arg);
    friend std::istream& operator>>(std::istream& is,  Bool& arg);
};
std::ostream& operator<<(std::ostream& os, const Bool& arg)
    { return os << *arg; }
std::istream& operator>>(std::istream& is, Bool& arg)
    { return is >> *arg; }
// Konstanten
static constexpr Bool False{false};
static constexpr Bool True{true};
int main() {
    Bool jein = True && ( Bool{false} || !Bool{} ); // verwendet &&, || und !
    std::cout << jein << "\n"; // Ausgabe: 1
}

Listing 16.27: Die Vergleichskategorien enthalten Konstanten für die Rückgabe.

Book listing lst-0446-book.cpp:

// https://godbolt.org/z/KxWb4q8q9 
#include <compare>  // partial_ordering etc
#include <set>
#include <iostream>
using namespace std;
struct Bruch {
  int z, n;  // zaehler / nenner
  partial_ordering operator<=>(const Bruch& re) const {
    if(n==0 || re.n==0) return partial_ordering::unordered;
    return (double)z / n <=> (double)re.z / re.n;
  }
};
int main() {
  set<Bruch> brueche{ {1,2}, {2,4}, {1,3}, {2,3}, {1,4}, {2,5}, {3,8}, {99,0} };
  for(auto b : brueche)
    cout << b.z << "/" << b.n << " ";
  cout << "\n"; // Ausgabe: 1/4 1/3 3/8 2/5 1/2 2/3
}

Godbolt Listing lst-0446-godb.cpp, https://godbolt.org/z/KxWb4q8q9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KxWb4q8q9 
#include <compare>  // partial_ordering etc
#include <set>
#include <iostream>
using namespace std;
struct Bruch {
  int z, n;  // zaehler / nenner
  partial_ordering operator<=>(const Bruch& re) const {
    if(n==0 || re.n==0) return partial_ordering::unordered;
    return (double)z / n <=> (double)re.z / re.n;
  }
};
int main() {
  set<Bruch> brueche{ {1,2}, {2,4}, {1,3}, {2,3}, {1,4}, {2,5}, {3,8}, {99,0} };
  for(auto b : brueche)
    cout << b.z << "/" << b.n << " ";
  cout << "\n"; // Ausgabe: 1/4 1/3 3/8 2/5 1/2 2/3
}

Listing 16.28: Die Rückgabe von <=> können Sie mit null vergleichen.

Book listing lst-0448-book.cpp:

auto operator<=>(const Adresse& re) const {
  array a{strasse, plz, ort};
  array b{re.strasse, re.plz, re.ort};
  return lexicographical_compare_three_way(begin(a), end(a), begin(b), end(b));
}

Listing 16.29: Eine virtuelle Methode, die = 0 ist, nennt man pur virtuell oder abstrakt.

Book listing lst-0449-book.cpp:

// https://godbolt.org/z/f458s99Ga 
#include <string>
#include <iostream>
using std::string; using std::ostream;
class Shape {
    string color_;
public:
    virtual double calcArea() const = 0; // pur virtuelle Methode
    string getColor() const { return color_; }
    void setColor(const string& color) { color_ = color; }
    virtual ~Shape() {}
};
class Square : public Shape {
    double len_;
public:
    explicit Square(double len) : len_{len} {}
    double calcArea() const override { return len_*len_; }
};
class Circle : public Shape {
    double rad_;
public:
    explicit Circle(double rad) : rad_{rad} {}
    double calcArea() const override { return 3.1415*rad_*rad_; }
};
struct Calculator {
    Shape& shape_;
    Calculator(Shape& shape) : shape_{shape} { }
    void run(ostream& os) const {
        os << "The area of the shape is " << shape_.calcArea() << "\n";
    }
};
int main() {
    Square quadrat {5.0};
    Calculator ti { quadrat };
    ti.run(std::cout); // Ausgabe: The area of the shape is 25
}

Godbolt Listing lst-0449-godb.cpp, https://godbolt.org/z/f458s99Ga:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/f458s99Ga 
#include <string>
#include <iostream>
using std::string; using std::ostream;
class Shape {
    string color_;
public:
    virtual double calcArea() const = 0; // pur virtuelle Methode
    string getColor() const { return color_; }
    void setColor(const string& color) { color_ = color; }
    virtual ~Shape() {}
};
class Square : public Shape {
    double len_;
public:
    explicit Square(double len) : len_{len} {}
    double calcArea() const override { return len_*len_; }
};
class Circle : public Shape {
    double rad_;
public:
    explicit Circle(double rad) : rad_{rad} {}
    double calcArea() const override { return 3.1415*rad_*rad_; }
};
struct Calculator {
    Shape& shape_;
    Calculator(Shape& shape) : shape_{shape} { }
    void run(ostream& os) const {
        os << "The area of the shape is " << shape_.calcArea() << "\n";
    }
};
int main() {
    Square quadrat {5.0};
    Calculator ti { quadrat };
    ti.run(std::cout); // Ausgabe: The area of the shape is 25
}

Listing 16.30: Mit einem »enum« definieren Sie einen Typ mit eigenem Wertebereich.

Book listing lst-0454-book.cpp:

// https://godbolt.org/z/xhd7s1YhE 
#include <string>
using std::string;
enum class Ampelfarbe {
    ROT, GELB, ROTGELB, GRUEN
};
struct Ampel {
    Ampelfarbe farbe_;
    Ampel(Ampelfarbe farbe, string name) : farbe_{farbe} {}
};

Ampel erzeugeAmpel(Ampelfarbe farbe, string ampelName) {
    return Ampel{farbe, ampelName};
}

int main() {
    Ampel ampel = erzeugeAmpel(Ampelfarbe::ROT, "AX-001");
}

Godbolt Listing lst-0454-godb.cpp, https://godbolt.org/z/xhd7s1YhE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xhd7s1YhE 
#include <string>
using std::string;
enum class Ampelfarbe {
    ROT, GELB, ROTGELB, GRUEN
};
struct Ampel {
    Ampelfarbe farbe_;
    Ampel(Ampelfarbe farbe, string name) : farbe_{farbe} {}
};

Ampel erzeugeAmpel(Ampelfarbe farbe, string ampelName) {
    return Ampel{farbe, ampelName};
}

int main() {
    Ampel ampel = erzeugeAmpel(Ampelfarbe::ROT, "AX-001");
}

Listing 16.31: In einem »enum« können Sie auch die gewünschten Zahlenwerte angeben.

Book listing lst-0457-book.cpp:

// https://godbolt.org/z/esevnfEM3 
enum class Wochentag {
    MO=1, DI, MI, DO, FR, SA, SO         // DI wird 2, MI wird 3 etc.
};
enum class Level {
   TRACE=1, DEBUG, INFO=10, ERROR, FATAL // auch mit Lücken möglich
};
void log(Level level) {
   int intLevel = (int)level;            // explizit in einen int umwandeln
   if(intLevel > 10) { /* ... */ }
}

Godbolt Listing lst-0457-godb.cpp, https://godbolt.org/z/esevnfEM3:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/esevnfEM3 
enum class Wochentag {
    MO=1, DI, MI, DO, FR, SA, SO         // DI wird 2, MI wird 3 etc.
};
enum class Level {
   TRACE=1, DEBUG, INFO=10, ERROR, FATAL // auch mit Lücken möglich
};
void log(Level level) {
   int intLevel = (int)level;            // explizit in einen int umwandeln
   if(intLevel > 10) { /* ... */ }
}

Listing 17.1: Verbieten Sie mit »= delete« vier der großen Fünf.

Book listing lst-0458-book.cpp:

// https://godbolt.org/z/1Ke5W5Pj5 
struct Typ {
    char* data_;            // roher Zeiger kann für unklare Besitzverhältnisse sorgen
    Typ(int n) : data_(new char[n]) {}
    ~Typ() { delete[] data_; }           // den Destruktor benötigen Sie

    Typ(const Typ&) = delete;            // keine Kopie zulassen
    Typ& operator=(const Typ&) = delete; // keine Zuweisung bitte
    Typ(Typ&&) = delete;                 // kein Verschieben
    Typ& operator=(Typ&&) = delete;      // kein Verschiebeoperator
};

Godbolt Listing lst-0458-godb.cpp, https://godbolt.org/z/1Ke5W5Pj5:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1Ke5W5Pj5 
struct Typ {
    char* data_;            // roher Zeiger kann für unklare Besitzverhältnisse sorgen
    Typ(int n) : data_(new char[n]) {}
    ~Typ() { delete[] data_; }           // den Destruktor benötigen Sie

    Typ(const Typ&) = delete;            // keine Kopie zulassen
    Typ& operator=(const Typ&) = delete; // keine Zuweisung bitte
    Typ(Typ&&) = delete;                 // kein Verschieben
    Typ& operator=(Typ&&) = delete;      // kein Verschiebeoperator
};

Listing 17.2: Statt eines rohen Zeigers verwenden Sie ein Standardkonstrukt und definieren keine Operation der Großen Fünf.

Book listing lst-0459-book.cpp:

// https://godbolt.org/z/xMbG771En 
#include <vector>
#include <memory>           // unique_ptr, shared_ptr
struct Typ1 {               // automatische komplette Kopie der Ressource
    std::vector<char> data_;
    Typ1(int n) : data_(n) {}
};
struct Typ2 {               // Kopie untersagt, Verschieben möglich
    std::unique_ptr<int[]> data_;
    Typ2(int n) : data_(new int[n]) {}
};
struct Typ3 {               // Kopie erlaubt, Ressource wird dann sauber geteilt
    std::shared_ptr<Typ1> data_;
    Typ3(int n) : data_(std::make_shared<Typ1>(n)) {}
};

Godbolt Listing lst-0459-godb.cpp, https://godbolt.org/z/xMbG771En:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xMbG771En 
#include <vector>
#include <memory>           // unique_ptr, shared_ptr
struct Typ1 {               // automatische komplette Kopie der Ressource
    std::vector<char> data_;
    Typ1(int n) : data_(n) {}
};
struct Typ2 {               // Kopie untersagt, Verschieben möglich
    std::unique_ptr<int[]> data_;
    Typ2(int n) : data_(new int[n]) {}
};
struct Typ3 {               // Kopie erlaubt, Ressource wird dann sauber geteilt
    std::shared_ptr<Typ1> data_;
    Typ3(int n) : data_(std::make_shared<Typ1>(n)) {}
};

Listing 17.3: In einer Hierarchie mit virtuellen Methoden müssen Sie den Destruktor der Basisklasse definieren und virtuell markieren.

Book listing lst-0460-book.cpp:

// https://godbolt.org/z/1xcqon7dM 
struct Base {
    virtual ~Base() {}; // definieren Sie den Destruktor, machen Sie ihn virtual
    virtual void other();
};

struct Derived : public Base {
    void other() override;
};

int main() {
    Base *obj = new Derived{};
    /* ... mehr Programmzeilen hier ... */
    delete obj;     // klappt, weil Base::~Base virtual ist
}

Godbolt Listing lst-0460-godb.cpp, https://godbolt.org/z/1xcqon7dM:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xcqon7dM 
struct Base {
    virtual ~Base() {}; // definieren Sie den Destruktor, machen Sie ihn virtual
    virtual void other();
};

struct Derived : public Base {
    void other() override;
};

int main() {
    Base *obj = new Derived{};
    /* ... mehr Programmzeilen hier ... */
    delete obj;     // klappt, weil Base::~Base virtual ist
}

Listing 17.4: shared_ptr ruft immer den richtigen Destruktor auf, virtuell oder nicht.

Book listing lst-0461-book.cpp:

int main() {
    shared_ptr<Base> obj{ new Derived{} };
    /* ... mehr Programmzeilen hier ... */
} // obj wird korrekt weggeräumt

Listing 17.5: Eine RAII-Zeichenpufferklasse

Book listing lst-0463-book.cpp:

// https://godbolt.org/z/9eeG575Wz 
struct Puffer {
  const char *data;
  explicit Puffer(unsigned sz): data(new char[sz]) {}
  ~Puffer() { delete[] data; }
  Puffer(const Puffer&) = delete;
  Puffer& operator=(const Puffer&) = delete;
};

Godbolt Listing lst-0463-godb.cpp, https://godbolt.org/z/9eeG575Wz:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9eeG575Wz 
struct Puffer {
  const char *data;
  explicit Puffer(unsigned sz): data(new char[sz]) {}
  ~Puffer() { delete[] data; }
  Puffer(const Puffer&) = delete;
  Puffer& operator=(const Puffer&) = delete;
};

Listing 17.6: Wirft »right« eine Exception, entsteht mit »left« ein Leck.

Book listing lst-0464-book.cpp:

// https://godbolt.org/z/TK3vTv1EM 
struct StereoImage {
  Image *left, *right;
  StereoImage()
  : left(new Image)
  , right(new Image) // Gefahr!
  { }
  ~StereoImage() {
      delete left;
      delete right;
  }
};

Godbolt Listing lst-0464-godb.cpp, https://godbolt.org/z/TK3vTv1EM:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TK3vTv1EM 
struct StereoImage {
  Image *left, *right;
  StereoImage()
  : left(new Image)
  , right(new Image) // Gefahr!
  { }
  ~StereoImage() {
      delete left;
      delete right;
  }
};

Listing 17.7: Korrektes RAII für »StereoImage«

Book listing lst-0465-book.cpp:

// https://godbolt.org/z/cs4eEEGrf 
#include <memory> // unique_ptr
struct Image {
    /* ... */
};
struct StereoImage {
  std::unique_ptr<Image> left, right;
  StereoImage()
  : left(new Image)
  , right(new Image)
  { }
};

Godbolt Listing lst-0465-godb.cpp, https://godbolt.org/z/cs4eEEGrf:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cs4eEEGrf 
#include <memory> // unique_ptr
struct Image {
    /* ... */
};
struct StereoImage {
  std::unique_ptr<Image> left, right;
  StereoImage()
  : left(new Image)
  , right(new Image)
  { }
};

Listing 17.8: C-API in C++-Code

Book listing lst-0466-book.cpp:

// https://godbolt.org/z/GK4W1nKd4 
#include <string>
#include <stdexcept>
#include <sqlite3.h>
using std::string; using std::runtime_error;

void dbExec(const string &dbname, const string &sql) {
  sqlite3 *db;
  int errCode = sqlite3_open(dbname.c_str(), &db);  // Acquire
  if(errCode) {
    throw runtime_error("Fehler beim Öffnen der DB.");
  }
  errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
  if(errCode) {
    throw runtime_error("Fehler SQL-Exec.");        //                 (ERR)  Nicht gut!
  }
  errCode = sqlite3_close(db);                      // Release
}

Godbolt Listing lst-0466-godb.cpp, https://godbolt.org/z/GK4W1nKd4:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GK4W1nKd4 
#include <string>
#include <stdexcept>
#include <sqlite3.h>
using std::string; using std::runtime_error;

void dbExec(const string &dbname, const string &sql) {
  sqlite3 *db;
  int errCode = sqlite3_open(dbname.c_str(), &db);  // Acquire
  if(errCode) {
    throw runtime_error("Fehler beim Öffnen der DB.");
  }
  errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
  if(errCode) {
    throw runtime_error("Fehler SQL-Exec.");        //                 (ERR)  Nicht gut!
  }
  errCode = sqlite3_close(db);                      // Release
}

Listing 17.9: C-API mit einfachem RAII

Book listing lst-0467-book.cpp:

// https://godbolt.org/z/hqrPjGjnK 
#include <sqlite3.h>
class DbWrapper {
  sqlite3 *db_;
public:
  // acquire resource
  DbWrapper(const string& dbname)
    : db_{nullptr}
  {
    const int errCode = sqlite3_open(dbname.c_str(), &db_);
    if(errCode)
      throw runtime_error("Fehler beim Öffnen"); // verhindert sqlite3_close
  }

  // release resource
  ~DbWrapper() {
    sqlite3_close(db_);  // Release
  }
  // access Resource
  sqlite3* operator*() { return db_; }
  // Keine Kopie und Zuweisung
  DbWrapper(const DbWrapper&) = delete;
  DbWrapper& operator=(const DbWrapper&) = delete;
};
void dbExec(const string &dbname, const string &sql) {
  DbWrapper db { dbname };
  const int errCode = sqlite3_exec(*db, sql.c_str(), nullptr, 
    nullptr, nullptr);
  if(errCode)
    throw runtime_error("Fehler SQL-Exec."); // Jetzt geht es!
}

Godbolt Listing lst-0467-godb.cpp, https://godbolt.org/z/hqrPjGjnK:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hqrPjGjnK 
#include <sqlite3.h>
class DbWrapper {
  sqlite3 *db_;
public:
  // acquire resource
  DbWrapper(const string& dbname)
    : db_{nullptr}
  {
    const int errCode = sqlite3_open(dbname.c_str(), &db_);
    if(errCode)
      throw runtime_error("Fehler beim Öffnen"); // verhindert sqlite3_close
  }

  // release resource
  ~DbWrapper() {
    sqlite3_close(db_);  // Release
  }
  // access Resource
  sqlite3* operator*() { return db_; }
  // Keine Kopie und Zuweisung
  DbWrapper(const DbWrapper&) = delete;
  DbWrapper& operator=(const DbWrapper&) = delete;
};
void dbExec(const string &dbname, const string &sql) {
  DbWrapper db { dbname };
  const int errCode = sqlite3_exec(*db, sql.c_str(), nullptr, 
    nullptr, nullptr);
  if(errCode)
    throw runtime_error("Fehler SQL-Exec."); // Jetzt geht es!
}

Listing 17.10: C-API mit einfachem RAII, ohne throw

Book listing lst-0468-book.cpp:

// https://godbolt.org/z/5bW9Evorc 
#include <string>
#include <sqlite3.h>
class DbWrapper {
  sqlite3 *db_;
public:
  DbWrapper(const std::string& dbname)
    : db_{nullptr}
  {
    const int errCode = sqlite3_open(dbname.c_str(), &db_);
    if(errCode) db_ = nullptr;  // als 'nicht erfolgreich' markieren
  }
  explicit operator bool() const {
    return db_ != nullptr;      // Markierung auswerten
  }
  ~DbWrapper() {
    if(db_) sqlite3_close(db_);
  }
  // ... Rest wie zuvor ...
};
bool dbExec(const std::string &dbname, const std::string &sql) {
  DbWrapper db { dbname };
  if(db) {                 // prüfe auf erfolgreiche Initialisierung
    const int errCode = sqlite3_exec(*db,sql.c_str(),nullptr,nullptr,nullptr);
    if(errCode)
      return false; // immer noch korrektes RAII
  }
  return (bool)db;
}

Godbolt Listing lst-0468-godb.cpp, https://godbolt.org/z/5bW9Evorc:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5bW9Evorc 
#include <string>
#include <sqlite3.h>
class DbWrapper {
  sqlite3 *db_;
public:
  DbWrapper(const std::string& dbname)
    : db_{nullptr}
  {
    const int errCode = sqlite3_open(dbname.c_str(), &db_);
    if(errCode) db_ = nullptr;  // als 'nicht erfolgreich' markieren
  }
  explicit operator bool() const {
    return db_ != nullptr;      // Markierung auswerten
  }
  ~DbWrapper() {
    if(db_) sqlite3_close(db_);
  }
  // ... Rest wie zuvor ...
};
bool dbExec(const std::string &dbname, const std::string &sql) {
  DbWrapper db { dbname };
  if(db) {                 // prüfe auf erfolgreiche Initialisierung
    const int errCode = sqlite3_exec(*db,sql.c_str(),nullptr,nullptr,nullptr);
    if(errCode)
      return false; // immer noch korrektes RAII
  }
  return (bool)db;
}

Listing 17.11: Nothrow-new wirft kein »bad_alloc«, sondern liefert »nullptr« zurück.

Book listing lst-0469-book.cpp:

// https://godbolt.org/z/s8KoE4ETs 
#include <new> // nothrow
std::string *ps = new(std::nothrow) std::string{};
if(ps == nullptr) {
   std::cerr << "Die Speicheranforderung ging schief\n";
   return SOME_ERROR;
}

Godbolt Listing lst-0469-godb.cpp, https://godbolt.org/z/s8KoE4ETs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s8KoE4ETs 
#include <new> // nothrow
std::string *ps = new(std::nothrow) std::string{};
if(ps == nullptr) {
   std::cerr << "Die Speicheranforderung ging schief\n";
   return SOME_ERROR;
}

Listing 18.1: Mit friend können Sie einer anderen Klasse Zugriff auf Privates erlauben.

Book listing lst-0470-book.cpp:

// https://godbolt.org/z/WqfMGaP71 
#include <iostream>
class Schrauber;
class Ding {
    int value_; // privat
public:
    explicit Ding(int value) : value_{value} {}
    void inc() { ++value_; }
    std::ostream& print(std::ostream& os) const { return os<<value_; }
    friend class Schrauber;
};
class Schrauber {
    const Ding &ding_;
public:
    explicit Schrauber(const Ding &ding) : ding_{ding} {}
    auto dingWert() const {
        return ding_.value_;                   // Zugriff auf Privates aus Ding
    }
};
int main() {
    Ding ding{45};
    ding.print(std::cout) << '\n';             // Ausgabe: 45
    Schrauber schrauber{ding};
    ding.inc(); // internen Wert verändern
    std::cout << schrauber.dingWert() << '\n'; // Ausgabe: 46
}

Godbolt Listing lst-0470-godb.cpp, https://godbolt.org/z/WqfMGaP71:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WqfMGaP71 
#include <iostream>
class Schrauber;
class Ding {
    int value_; // privat
public:
    explicit Ding(int value) : value_{value} {}
    void inc() { ++value_; }
    std::ostream& print(std::ostream& os) const { return os<<value_; }
    friend class Schrauber;
};
class Schrauber {
    const Ding &ding_;
public:
    explicit Schrauber(const Ding &ding) : ding_{ding} {}
    auto dingWert() const {
        return ding_.value_;                   // Zugriff auf Privates aus Ding
    }
};
int main() {
    Ding ding{45};
    ding.print(std::cout) << '\n';             // Ausgabe: 45
    Schrauber schrauber{ding};
    ding.inc(); // internen Wert verändern
    std::cout << schrauber.dingWert() << '\n'; // Ausgabe: 46
}

Listing 18.2: Die Klasse Tree hat Zugriff auf Privates von Node.

Book listing lst-0471-book.cpp:

// https://godbolt.org/z/dTnxobz6v 
#include <memory> // unique_ptr
#include <string>
using std::unique_ptr; using std::cout;
template <typename K, typename D> class Tree; // Vorwärtsdeklaration
template <typename K, typename D>
class Node {
    friend class Tree<K,D>; // Zugriff auf Privates erlauben
    K key;
    D data;
    unique_ptr<Node> left, right;
public:
    Node(const K& k, const D& d) : key(k), data(d) { }
};
template <typename K, typename D>
class Tree {
public:
    void insert(const K &key, const D& data);
    D* find(const K &key) { return findRec(key, root); }
private:
    D* findRec(const K &key, unique_ptr<Node<K,D>> &wo);
    unique_ptr<Node<K,D>> root;
};
template <typename K, typename D>
void Tree<K,D>::insert(const K& key, const D& data) {
    auto *current = &root;
    while(*current) { // solange unique_ptr was enthält
        auto &node = *(current->get());
        if (key < node.key) {
            current = &node.left;
        } else if (node.key < key) {
            current = &node.right;
        }
    }
    *current = std::make_unique<Node<K,D>>(key,data);
};
template <typename K, typename D>
D* Tree<K,D>::findRec(const K& key, unique_ptr<Node<K,D>> &wo) {
    if(!wo)
        return nullptr;
    auto &node = *(wo.get());
    if(key < node.key)
        return findRec(key, node.left);
    if(node.key < key)
        return findRec(key, node.right);
    return &node.data; // key == node.key
};
int main() {
    Tree<int,std::string> bt {};
    bt.insert(3, "drei");
    bt.insert(2, "zwei");
    bt.insert(4, "vier");
    auto wo = bt.find(7);
    if(wo==nullptr) cout<<"keine 7\n"; // Ausgabe: keine 7
    wo = bt.find(3);
    if(wo!=nullptr) cout<<*wo<<"\n";   // Ausgabe: drei
}

Godbolt Listing lst-0471-godb.cpp, https://godbolt.org/z/dTnxobz6v:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dTnxobz6v 
#include <memory> // unique_ptr
#include <string>
using std::unique_ptr; using std::cout;
template <typename K, typename D> class Tree; // Vorwärtsdeklaration
template <typename K, typename D>
class Node {
    friend class Tree<K,D>; // Zugriff auf Privates erlauben
    K key;
    D data;
    unique_ptr<Node> left, right;
public:
    Node(const K& k, const D& d) : key(k), data(d) { }
};
template <typename K, typename D>
class Tree {
public:
    void insert(const K &key, const D& data);
    D* find(const K &key) { return findRec(key, root); }
private:
    D* findRec(const K &key, unique_ptr<Node<K,D>> &wo);
    unique_ptr<Node<K,D>> root;
};
template <typename K, typename D>
void Tree<K,D>::insert(const K& key, const D& data) {
    auto *current = &root;
    while(*current) { // solange unique_ptr was enthält
        auto &node = *(current->get());
        if (key < node.key) {
            current = &node.left;
        } else if (node.key < key) {
            current = &node.right;
        }
    }
    *current = std::make_unique<Node<K,D>>(key,data);
};
template <typename K, typename D>
D* Tree<K,D>::findRec(const K& key, unique_ptr<Node<K,D>> &wo) {
    if(!wo)
        return nullptr;
    auto &node = *(wo.get());
    if(key < node.key)
        return findRec(key, node.left);
    if(node.key < key)
        return findRec(key, node.right);
    return &node.data; // key == node.key
};
int main() {
    Tree<int,std::string> bt {};
    bt.insert(3, "drei");
    bt.insert(2, "zwei");
    bt.insert(4, "vier");
    auto wo = bt.find(7);
    if(wo==nullptr) cout<<"keine 7\n"; // Ausgabe: keine 7
    wo = bt.find(3);
    if(wo!=nullptr) cout<<*wo<<"\n";   // Ausgabe: drei
}

Listing 18.3: Beim Erben können Sie angeben, was sichtbar werden soll.

Book listing lst-0473-book.cpp:

// https://godbolt.org/z/eKbK39nG1 
class Base {
public:
    int xPublic = 1;
protected:
    int xProtected = 2;
private:
    int xPrivate = 3;
};
class DerivedPublic : public Base {
    // xPublic wird 'public'
    // xProtected wird 'protected'
    // xPrivate ist hier nicht sichtbar
};
class DerivedProtected : protected Base {
    // xPublic wird 'protected'
    // xProtected wird 'protected'
    // xPrivate ist hier nicht sichtbar
};
class DerivedPrivate : private Base { // oder wenn nichts angegeben
    // xPublic wird 'private'
    // xProtected wird 'private'
    // xPrivate ist hier nicht sichtbar
};

Godbolt Listing lst-0473-godb.cpp, https://godbolt.org/z/eKbK39nG1:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eKbK39nG1 
class Base {
public:
    int xPublic = 1;
protected:
    int xProtected = 2;
private:
    int xPrivate = 3;
};
class DerivedPublic : public Base {
    // xPublic wird 'public'
    // xProtected wird 'protected'
    // xPrivate ist hier nicht sichtbar
};
class DerivedProtected : protected Base {
    // xPublic wird 'protected'
    // xProtected wird 'protected'
    // xPrivate ist hier nicht sichtbar
};
class DerivedPrivate : private Base { // oder wenn nichts angegeben
    // xPublic wird 'private'
    // xProtected wird 'private'
    // xPrivate ist hier nicht sichtbar
};

Listing 18.4: Ererbte Sichtbarkeiten, von außen betrachtet

Book listing lst-0474-book.cpp:

// https://godbolt.org/z/Pxqrjjqs8 
#include <iostream>
using std::cout; using std::ostream;
// … wie zuvor …
int main() {
    // öffentlich erben
    DerivedPublic dpu{};
    cout << dpu.xPublic << '\n';    // Ausgabe: 1
    cout << dpu.xProtected << '\n'; // kein Zugriff von außen
    // geschützt erben
    DerivedProtected dpt{};
    cout << dpt.xPublic << '\n';    // kein Zugriff von außen
    cout << dpt.xProtected << '\n'; // kein Zugriff von außen
    // private erben
    DerivedPrivate dpv{};
    cout << dpv.xPublic << '\n';    // kein Zugriff von außen
    cout << dpv.xProtected << '\n'; // kein Zugriff von außen
}

Godbolt Listing lst-0474-godb.cpp, https://godbolt.org/z/Pxqrjjqs8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Pxqrjjqs8 
#include <iostream>
using std::cout; using std::ostream;
// … wie zuvor …
int main() {
    // öffentlich erben
    DerivedPublic dpu{};
    cout << dpu.xPublic << '\n';    // Ausgabe: 1
    cout << dpu.xProtected << '\n'; // kein Zugriff von außen
    // geschützt erben
    DerivedProtected dpt{};
    cout << dpt.xPublic << '\n';    // kein Zugriff von außen
    cout << dpt.xProtected << '\n'; // kein Zugriff von außen
    // private erben
    DerivedPrivate dpv{};
    cout << dpv.xPublic << '\n';    // kein Zugriff von außen
    cout << dpv.xProtected << '\n'; // kein Zugriff von außen
}

Listing 18.5: Ererbte Sichtbarkeiten für weitere Ableitungen

Book listing lst-0475-book.cpp:

// https://godbolt.org/z/xKEo38c4n 
#include <iostream>
using std::cout; using std::ostream;
// … wie zuvor …
struct Normalfall : public DerivedPublic {
    void drucke() {
        cout << xPublic;
        cout << xProtected;
    }
};
struct Spezialfall : public DerivedPrivate {
    void drucke() {
        cout << xPublic;                  //                 (ERR)  kein Zugriff
        cout << xProtected;               //                 (ERR)  kein Zugriff
    }
};
int main() {
    Normalfall n {};
    n.drucke(); // Ausgabe: 12
    Spezialfall s {};
    s.drucke();
}

Godbolt Listing lst-0475-godb.cpp, https://godbolt.org/z/xKEo38c4n:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xKEo38c4n 
#include <iostream>
using std::cout; using std::ostream;
// … wie zuvor …
struct Normalfall : public DerivedPublic {
    void drucke() {
        cout << xPublic;
        cout << xProtected;
    }
};
struct Spezialfall : public DerivedPrivate {
    void drucke() {
        cout << xPublic;                  //                 (ERR)  kein Zugriff
        cout << xProtected;               //                 (ERR)  kein Zugriff
    }
};
int main() {
    Normalfall n {};
    n.drucke(); // Ausgabe: 12
    Spezialfall s {};
    s.drucke();
}

Listing 18.6: In der Praxis nutzen Kindklassen privat Geerbtes indirekt.

Book listing lst-0476-book.cpp:

// https://godbolt.org/z/zMvWxT854 
#include <iostream>
using std::cout; using std::ostream;
class Basis {
    public: int daten = 5;
};
class Mitte : private Basis {
protected: void drucke() {
        cout << daten; // 'daten' ist hier privat geerbt
    }
};
class Letztendlich : public Mitte {
    public: void los() {
        // 'daten' ist nicht sichtbar
        drucke(); // 'drucke' ist geschützt sichtbar
    }
};
int main() {
    Letztendlich l {};
    l.los(); // Ausgabe: 5
}

Godbolt Listing lst-0476-godb.cpp, https://godbolt.org/z/zMvWxT854:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zMvWxT854 
#include <iostream>
using std::cout; using std::ostream;
class Basis {
    public: int daten = 5;
};
class Mitte : private Basis {
protected: void drucke() {
        cout << daten; // 'daten' ist hier privat geerbt
    }
};
class Letztendlich : public Mitte {
    public: void los() {
        // 'daten' ist nicht sichtbar
        drucke(); // 'drucke' ist geschützt sichtbar
    }
};
int main() {
    Letztendlich l {};
    l.los(); // Ausgabe: 5
}

Listing 18.7: »Hat-ein«-Beziehung mittels privater Vererbung

Book listing lst-0477-book.cpp:

// https://godbolt.org/z/zzT17q588 
class Motor {
public:
  Motor(int anzZylinder);
  void start();                  // Motor starten
};
class Auto : private Motor {     // Auto hat-einen Motor
public:
  Auto() : Motor{8} { }          // initialisiert ein Auto mit 8 Zylindern
  using Motor::start;            // startet Auto durch Starten des Motors
};

Godbolt Listing lst-0477-godb.cpp, https://godbolt.org/z/zzT17q588:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zzT17q588 
class Motor {
public:
  Motor(int anzZylinder);
  void start();                  // Motor starten
};
class Auto : private Motor {     // Auto hat-einen Motor
public:
  Auto() : Motor{8} { }          // initialisiert ein Auto mit 8 Zylindern
  using Motor::start;            // startet Auto durch Starten des Motors
};

Listing 18.8: »Hat-ein«-Beziehung mittels Mitglied

Book listing lst-0478-book.cpp:

// https://godbolt.org/z/8jGWTqh9z 
class Auto {
public:
  Auto() : motor_{8} { }           // initialisiert ein Auto mit 8 Zylindern
  void start() { motor_.start(); } // startet Auto durch Starten des Motors
private:
  Motor motor_;                    // Auto hat-einen Motor
};

Godbolt Listing lst-0478-godb.cpp, https://godbolt.org/z/8jGWTqh9z:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8jGWTqh9z 
class Auto {
public:
  Auto() : motor_{8} { }           // initialisiert ein Auto mit 8 Zylindern
  void start() { motor_.start(); } // startet Auto durch Starten des Motors
private:
  Motor motor_;                    // Auto hat-einen Motor
};

Listing 18.9: Eine Signaturklasse hat nur pur virtuelle Methoden.

Book listing lst-0479-book.cpp:

// https://godbolt.org/z/rW4oTPhrG 
struct Driver {
    virtual void init() = 0;
    virtual void done() = 0;
    virtual bool send(const char* data, unsigned len) = 0;
};

Godbolt Listing lst-0479-godb.cpp, https://godbolt.org/z/rW4oTPhrG:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rW4oTPhrG 
struct Driver {
    virtual void init() = 0;
    virtual void done() = 0;
    virtual bool send(const char* data, unsigned len) = 0;
};

Listing 18.10: Eine Signaturklasse macht eine gute Basisklasse.

Book listing lst-0480-book.cpp:

// https://godbolt.org/z/7xf6sxPqG 
#include <iostream>
using std::cout;
struct KeyboardDriver : public Driver {
    void init() override { cout << "Init Keyboard\n"; }
    void done() override { cout << "Done Keyboard\n"; }
    bool send(const char* data, unsigned int len) override {
        cout << "sending " << len << " bytes\n";
        return true;
    }
};
struct Computer {
    Driver &driver_;
    explicit Computer(Driver &driver) : driver_{driver} {
        driver_.init();
    }
    void run() {
        driver_.send("Hello", 5);
    }
    ~Computer() {
        driver_.done();
    }
    Computer(const Computer&) = delete;
};
int main() {
    KeyboardDriver keyboard {};
    Computer computer(keyboard); // Ausgabe: Init Keyboard
    computer.run();              // Ausgabe: sending 5 bytes
}                                // Ausgabe: Done Keyboard

Godbolt Listing lst-0480-godb.cpp, https://godbolt.org/z/7xf6sxPqG:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7xf6sxPqG 
#include <iostream>
using std::cout;
struct KeyboardDriver : public Driver {
    void init() override { cout << "Init Keyboard\n"; }
    void done() override { cout << "Done Keyboard\n"; }
    bool send(const char* data, unsigned int len) override {
        cout << "sending " << len << " bytes\n";
        return true;
    }
};
struct Computer {
    Driver &driver_;
    explicit Computer(Driver &driver) : driver_{driver} {
        driver_.init();
    }
    void run() {
        driver_.send("Hello", 5);
    }
    ~Computer() {
        driver_.done();
    }
    Computer(const Computer&) = delete;
};
int main() {
    KeyboardDriver keyboard {};
    Computer computer(keyboard); // Ausgabe: Init Keyboard
    computer.run();              // Ausgabe: sending 5 bytes
}                                // Ausgabe: Done Keyboard

Listing 18.11: Eine virtuelle Methode mit Implementierung »= 0« ist abstrakt.

Book listing lst-0481-book.cpp:

// https://godbolt.org/z/G1q964f1M 
#include <iostream>           // cout
#include <memory>             // unique_ptr
using std::cout;
class Driver {                // abstrakte Basisklasse
public:
    virtual void init() = 0;
    virtual void done() = 0;
    virtual void send(const std::string &data) = 0;
};
class ProductionDriver : public Driver {
public:
    void init() override { }
    void done() override { }
    void send(const std::string &data) override { cout << data << "\n"; }
};
class DebuggingDriver : public Driver {
   size_t countSend_ = 0;
public:
    void init() override {
        countSend_= 0; cout << "Ok, bin initialisiert.\n";
    }
    void done() override {
        cout << "send benutzt:" << countSend_ << " mal\n";
    }
    void send(const std::string &data) override {
        cout << "send("<<countSend_<<"):"<< data << "\n";
        ++countSend_;
    }
};
struct DriverWrapper {        // RAII-Wrapper für init() und done()
    Driver &driver_;
    explicit DriverWrapper(Driver& driver) : driver_(driver) { driver_.init(); }
    ~DriverWrapper() { driver_.done(); }
    DriverWrapper(const DriverWrapper&) = delete; // nicht kopieren
};

void doWork(Driver &driver) { // jemand, der flexibel einen beliebigen Driver nutzt
    DriverWrapper wrapper(driver);      // init() und done() aufrufen
    driver.send("Eine unerwartete Reise");
    driver.send("Smaugs Einoede");
}

int main() {
    // gleiche doWork, einmal mit Produktions- und einmal mit Debugging-Treiber
    ProductionDriver production{};
    doWork( production );
    DebuggingDriver debugging{};
    doWork( debugging );

    // üblichere Variante eines dynamisch erzeugten Treibers
    std::unique_ptr<Driver> driver{ new ProductionDriver{} };
    doWork( *driver );
}

Godbolt Listing lst-0481-godb.cpp, https://godbolt.org/z/G1q964f1M:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/G1q964f1M 
#include <iostream>           // cout
#include <memory>             // unique_ptr
using std::cout;
class Driver {                // abstrakte Basisklasse
public:
    virtual void init() = 0;
    virtual void done() = 0;
    virtual void send(const std::string &data) = 0;
};
class ProductionDriver : public Driver {
public:
    void init() override { }
    void done() override { }
    void send(const std::string &data) override { cout << data << "\n"; }
};
class DebuggingDriver : public Driver {
   size_t countSend_ = 0;
public:
    void init() override {
        countSend_= 0; cout << "Ok, bin initialisiert.\n";
    }
    void done() override {
        cout << "send benutzt:" << countSend_ << " mal\n";
    }
    void send(const std::string &data) override {
        cout << "send("<<countSend_<<"):"<< data << "\n";
        ++countSend_;
    }
};
struct DriverWrapper {        // RAII-Wrapper für init() und done()
    Driver &driver_;
    explicit DriverWrapper(Driver& driver) : driver_(driver) { driver_.init(); }
    ~DriverWrapper() { driver_.done(); }
    DriverWrapper(const DriverWrapper&) = delete; // nicht kopieren
};

void doWork(Driver &driver) { // jemand, der flexibel einen beliebigen Driver nutzt
    DriverWrapper wrapper(driver);      // init() und done() aufrufen
    driver.send("Eine unerwartete Reise");
    driver.send("Smaugs Einoede");
}

int main() {
    // gleiche doWork, einmal mit Produktions- und einmal mit Debugging-Treiber
    ProductionDriver production{};
    doWork( production );
    DebuggingDriver debugging{};
    doWork( debugging );

    // üblichere Variante eines dynamisch erzeugten Treibers
    std::unique_ptr<Driver> driver{ new ProductionDriver{} };
    doWork( *driver );
}

Listing 18.12: Multiple Vererbung heißt, mehrere Basisklassen zu haben.

Book listing lst-0483-book.cpp:

// https://godbolt.org/z/MPaYW1v5j 
#include <iostream>
using std::cout;
class Saeugetier {
public:
    void gebaere() { cout << "Geburt!\n"; }
};
class Fliegend {
public:
    void fliege() { cout << "Flug!\n"; }
};
class Fledermaus: public Saeugetier, public Fliegend {
public:
    void rufe() { cout << "Ultraschall!\n"; }
};
int main() {
    Fledermaus bruce{};
    bruce.gebaere();       // Ausgabe: Geburt!
    bruce.fliege();        // Ausgabe: Flug!
    bruce.rufe();          // Ausgabe: Ultraschall!
}

Godbolt Listing lst-0483-godb.cpp, https://godbolt.org/z/MPaYW1v5j:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MPaYW1v5j 
#include <iostream>
using std::cout;
class Saeugetier {
public:
    void gebaere() { cout << "Geburt!\n"; }
};
class Fliegend {
public:
    void fliege() { cout << "Flug!\n"; }
};
class Fledermaus: public Saeugetier, public Fliegend {
public:
    void rufe() { cout << "Ultraschall!\n"; }
};
int main() {
    Fledermaus bruce{};
    bruce.gebaere();       // Ausgabe: Geburt!
    bruce.fliege();        // Ausgabe: Flug!
    bruce.rufe();          // Ausgabe: Ultraschall!
}

Listing 18.13: Uhr und Kalender ergeben Uhr mit Kalender.

Book listing lst-0484-book.cpp:

// https://godbolt.org/z/M7TTvaPxx 
// Parameter müssen gültige Werte der jeweiligen Einheit sein.
#include <iostream> // ostream
#include <iomanip>  // setw, setfill
#include <format>
using std::ostream; using std::format;
class Clock {
protected:
    int h_, m_, s_;
public:
    Clock(int hours, int minutes, int seconds)
    : h_{hours}, m_{minutes}, s_{seconds} {}
    void setClock(int hours, int minutes, int seconds) {
        h_ = hours; m_ = minutes; s_ = seconds;
    }
    friend ostream& operator<<(ostream&os, const Clock& c) {
        return os << format("{:02}:{:02}:{:02}", c.h_, c.m_, c.s_);
    }
    void tick() { // +1 Sekunde
        if(s_ >= 59) {
            s_ = 0;
            if(m_ >= 59) {
                m_ = 0;
                if(h_ >= 23) h_ = 0;
                else { h_ += 1; }
            } else { m_ += 1; }
        } else { s_ += 1; }
    }
};

Godbolt Listing lst-0484-godb.cpp, https://godbolt.org/z/M7TTvaPxx:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M7TTvaPxx 
// Parameter müssen gültige Werte der jeweiligen Einheit sein.
#include <iostream> // ostream
#include <iomanip>  // setw, setfill
#include <format>
using std::ostream; using std::format;
class Clock {
protected:
    int h_, m_, s_;
public:
    Clock(int hours, int minutes, int seconds)
    : h_{hours}, m_{minutes}, s_{seconds} {}
    void setClock(int hours, int minutes, int seconds) {
        h_ = hours; m_ = minutes; s_ = seconds;
    }
    friend ostream& operator<<(ostream&os, const Clock& c) {
        return os << format("{:02}:{:02}:{:02}", c.h_, c.m_, c.s_);
    }
    void tick() { // +1 Sekunde
        if(s_ >= 59) {
            s_ = 0;
            if(m_ >= 59) {
                m_ = 0;
                if(h_ >= 23) h_ = 0;
                else { h_ += 1; }
            } else { m_ += 1; }
        } else { s_ += 1; }
    }
};

GodboltId:a5WxqjxEr

Book listing lst-0485-book.cpp:

// https://godbolt.org/z/a5WxqjxEr 
int main() {
    Clock clock{ 23, 59, 59 };
    std::cout << clock << '\n'; // Ausgabe: 23:59:59
    clock.tick();
    std::cout << clock << '\n'; // Ausgabe: 00:00:00
}

Godbolt Listing lst-0485-godb.cpp, https://godbolt.org/z/a5WxqjxEr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a5WxqjxEr 
int main() {
    Clock clock{ 23, 59, 59 };
    std::cout << clock << '\n'; // Ausgabe: 23:59:59
    clock.tick();
    std::cout << clock << '\n'; // Ausgabe: 00:00:00
}

Listing 18.14: Eine einfache Kalenderklasse

Book listing lst-0486-book.cpp:

// https://godbolt.org/z/oe1hT9McG 
// … includes und usings …
struct Calendar {
    int y_, m_, d_;
    static const std::vector<int> mlens_;
    bool leapyear() const {
        if(y_ % 4 != 0) return false;
        if(y_ % 100 != 0) return true;
        if(y_ % 400 != 0) return false;
        return true;
    }
public:
    Calendar(int year, int month, int day)
    : y_{year}, m_{month}, d_{day} {}
    void setCalendar(int year, int month, int day) {
        y_ = year; m_ = month; d_ = day;
    }
    friend ostream& operator<<(ostream& os, const Calendar& c) {
        return os << format("{:04}-{:02}-{:02}", c.y_, c.m_, c.d_);
    }
    void advance() { // +1 day
        auto maxd = mlens_[m_-1]; // 0-basierter vector
        if(m_==2 && leapyear())
            maxd += 1;            // Februar im Schaltjahr
        if(d_ >= maxd) {
            d_ = 1;
            if(m_ >= 12) { m_ = 1; y_ += 1; }
            else { m_ += 1; }
        } else { d_ += 1; }
    }
};
const std::vector<int> Calendar::mlens_ = {31,28,31,30,31,30,31,31,30,31,30,31};

Godbolt Listing lst-0486-godb.cpp, https://godbolt.org/z/oe1hT9McG:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oe1hT9McG 
// … includes und usings …
struct Calendar {
    int y_, m_, d_;
    static const std::vector<int> mlens_;
    bool leapyear() const {
        if(y_ % 4 != 0) return false;
        if(y_ % 100 != 0) return true;
        if(y_ % 400 != 0) return false;
        return true;
    }
public:
    Calendar(int year, int month, int day)
    : y_{year}, m_{month}, d_{day} {}
    void setCalendar(int year, int month, int day) {
        y_ = year; m_ = month; d_ = day;
    }
    friend ostream& operator<<(ostream& os, const Calendar& c) {
        return os << format("{:04}-{:02}-{:02}", c.y_, c.m_, c.d_);
    }
    void advance() { // +1 day
        auto maxd = mlens_[m_-1]; // 0-basierter vector
        if(m_==2 && leapyear())
            maxd += 1;            // Februar im Schaltjahr
        if(d_ >= maxd) {
            d_ = 1;
            if(m_ >= 12) { m_ = 1; y_ += 1; }
            else { m_ += 1; }
        } else { d_ += 1; }
    }
};
const std::vector<int> Calendar::mlens_ = {31,28,31,30,31,30,31,31,30,31,30,31};

GodboltId:xf1xq8Ts3

Book listing lst-0487-book.cpp:

// https://godbolt.org/z/xf1xq8Ts3 
int main() {
    Calendar cal{ 2024, 2, 28 };
    std::cout << cal << '\n'; // Ausgabe: 2024-02-28
    cal.advance();
    std::cout << cal << '\n'; // Ausgabe: 2024-02-29
    cal.advance();
    std::cout << cal << '\n'; // Ausgabe: 2024-03-01
}

Godbolt Listing lst-0487-godb.cpp, https://godbolt.org/z/xf1xq8Ts3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xf1xq8Ts3 
int main() {
    Calendar cal{ 2024, 2, 28 };
    std::cout << cal << '\n'; // Ausgabe: 2024-02-28
    cal.advance();
    std::cout << cal << '\n'; // Ausgabe: 2024-02-29
    cal.advance();
    std::cout << cal << '\n'; // Ausgabe: 2024-03-01
}

Listing 18.15: Die Kalenderuhr ist ein Kalender und eine Uhr.

Book listing lst-0488-book.cpp:

// https://godbolt.org/z/rh179GW3j 
class CalendarClock : public Clock, public Calendar {
public:
    CalendarClock(int y, int m, int d, int hh, int mm, int ss)
    : Calendar{y,m,d}, Clock{hh,mm,ss} {}
    void tick() {         // +1 Sekunde
        auto prev_h = h_;
        Clock::tick();    // Aufruf Basisklassenmethode
        if(h_ < prev_h) { // falls neuer Tag
            advance();    // … Kalender fortschreiten
        }
    }
    friend ostream& operator<<(ostream&os, const CalendarClock& cc) {
        operator<<(os, (Calendar&)cc) << " "; // Aufruf freie Funktion
        operator<<(os, (Clock&)cc);           // Aufruf freie Funktion
        return os;
    }
};

Godbolt Listing lst-0488-godb.cpp, https://godbolt.org/z/rh179GW3j:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rh179GW3j 
class CalendarClock : public Clock, public Calendar {
public:
    CalendarClock(int y, int m, int d, int hh, int mm, int ss)
    : Calendar{y,m,d}, Clock{hh,mm,ss} {}
    void tick() {         // +1 Sekunde
        auto prev_h = h_;
        Clock::tick();    // Aufruf Basisklassenmethode
        if(h_ < prev_h) { // falls neuer Tag
            advance();    // … Kalender fortschreiten
        }
    }
    friend ostream& operator<<(ostream&os, const CalendarClock& cc) {
        operator<<(os, (Calendar&)cc) << " "; // Aufruf freie Funktion
        operator<<(os, (Clock&)cc);           // Aufruf freie Funktion
        return os;
    }
};

GodboltId:P6nzT7EY4

Book listing lst-0489-book.cpp:

// https://godbolt.org/z/P6nzT7EY4 
int main() {
    CalendarClock cc{ 2024,2,29, 23,59,59 };
    std::cout << cc << '\n'; // Ausgabe: 2024-02-29 23:59:59
    cc.tick();
    std::cout << cc << '\n'; // Ausgabe: 2024-03-01 00:00:00
}

Godbolt Listing lst-0489-godb.cpp, https://godbolt.org/z/P6nzT7EY4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/P6nzT7EY4 
int main() {
    CalendarClock cc{ 2024,2,29, 23,59,59 };
    std::cout << cc << '\n'; // Ausgabe: 2024-02-29 23:59:59
    cc.tick();
    std::cout << cc << '\n'; // Ausgabe: 2024-03-01 00:00:00
}

Listing 18.16: Mit multipler Vererbung kann sich der Wert eines Zeigers ändern.

Book listing lst-0492-book.cpp:

// https://godbolt.org/z/oc7jsbrEK 
#include <iostream>
using std::cout;
struct Base1 {
    virtual void f1() {}
};
struct Base2 {
    virtual void f2() {}
};
struct Derived : public Base1, public Base2 {
    virtual void g() {};
};
void vergleich(void* a, void* b) {
    cout << (a==b ? "identisch\n" : "unterschiedlich\n");
}
int main() {
    Derived d{};
    auto *pd = &d;
    cout << pd << '\n';       // zum Beispiel 0x1000
    auto pb1 = static_cast<Base1*>(pd);
    cout << pb1 << '\n';      // immer noch 0x1000
    auto pb2 = static_cast<Base2*>(pd);
    cout << pb2 << '\n';      // jetzt 0x1008 !
    cout << (pd==pb1 ? "gleich\n" : "verschieden\n"); // Ausgabe: gleich
    cout << (pd==pb2 ? "gleich\n" : "verschieden\n"); // Ausgabe: gleich
    vergleich(pb1, pd);       // Ausgabe: identisch
    vergleich(pb2, pd);       // Ausgabe: unterschiedlich
}

Godbolt Listing lst-0492-godb.cpp, https://godbolt.org/z/oc7jsbrEK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oc7jsbrEK 
#include <iostream>
using std::cout;
struct Base1 {
    virtual void f1() {}
};
struct Base2 {
    virtual void f2() {}
};
struct Derived : public Base1, public Base2 {
    virtual void g() {};
};
void vergleich(void* a, void* b) {
    cout << (a==b ? "identisch\n" : "unterschiedlich\n");
}
int main() {
    Derived d{};
    auto *pd = &d;
    cout << pd << '\n';       // zum Beispiel 0x1000
    auto pb1 = static_cast<Base1*>(pd);
    cout << pb1 << '\n';      // immer noch 0x1000
    auto pb2 = static_cast<Base2*>(pd);
    cout << pb2 << '\n';      // jetzt 0x1008 !
    cout << (pd==pb1 ? "gleich\n" : "verschieden\n"); // Ausgabe: gleich
    cout << (pd==pb2 ? "gleich\n" : "verschieden\n"); // Ausgabe: gleich
    vergleich(pb1, pd);       // Ausgabe: identisch
    vergleich(pb2, pd);       // Ausgabe: unterschiedlich
}

Listing 18.17: Das Beobachter-Muster mit multipler Vererbung

Book listing lst-0493-book.cpp:

// https://godbolt.org/z/EnE7Y886M 
#include <iostream>
#include <vector>
using std::cout;
// == Beobachter-Entwurfsmuster ==
struct Observer {
    virtual void update() = 0;
};
class Subject {
    std::vector<Observer*> observers_; // not owning pointers
protected:
    void notify() {
        for (auto o : observers_)
            o->update();
    }
public:
    void addObserver(Observer* o) {
        observers_.push_back(o);
    }
};
// == konkrete Klasse ==
struct MyThing {
    int calc() { return 1+1; }
};
// == zusammenbringen ==
struct MyObservableThing : public MyThing, public Subject {
    int calc() {
        notify();
        return MyThing::calc();
    }
};
// == etwas beobachten ==
struct MyObserver : public Observer {
    void update() override {
        cout << "observed\n";
    }
};
int main() {
    MyObserver myObserver{};
    MyObservableThing myObservableThing{};
    myObservableThing.addObserver(&myObserver);
    auto result = myObservableThing.calc(); // Ausgabe: observed
}

Godbolt Listing lst-0493-godb.cpp, https://godbolt.org/z/EnE7Y886M:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EnE7Y886M 
#include <iostream>
#include <vector>
using std::cout;
// == Beobachter-Entwurfsmuster ==
struct Observer {
    virtual void update() = 0;
};
class Subject {
    std::vector<Observer*> observers_; // not owning pointers
protected:
    void notify() {
        for (auto o : observers_)
            o->update();
    }
public:
    void addObserver(Observer* o) {
        observers_.push_back(o);
    }
};
// == konkrete Klasse ==
struct MyThing {
    int calc() { return 1+1; }
};
// == zusammenbringen ==
struct MyObservableThing : public MyThing, public Subject {
    int calc() {
        notify();
        return MyThing::calc();
    }
};
// == etwas beobachten ==
struct MyObserver : public Observer {
    void update() override {
        cout << "observed\n";
    }
};
int main() {
    MyObserver myObserver{};
    MyObservableThing myObservableThing{};
    myObservableThing.addObserver(&myObserver);
    auto result = myObservableThing.calc(); // Ausgabe: observed
}

Listing 18.18: Ein einfaches Beispiel mit virtueller Vererbung

Book listing lst-0494-book.cpp:

// https://godbolt.org/z/8jYeYPs7W 
#include <iostream>
using std::cout;
class Base {
public:
  int data_ = 0;
};
class Derived1 : public virtual Base {
};
class Derived2 : public virtual Base {
};
class DerivedDerived : public Derived1, public Derived2 {
public:
  void method() {
     data_ = 1;  // eindeutig, denn es gibt nur ein data_
  }
};
void ausgabe(const DerivedDerived &dd) {
    cout << dd.data_
        << (((Derived1&)dd).data_)
        << (((Derived2&)dd).data_)
        << (((Base&)dd).data_) << '\n';
}
int main() {
  DerivedDerived dd{};
  ausgabe(dd);   // Ausgabe: 0000
  dd.method();   // setzt data_ auf 1
  ausgabe(dd);   // Ausgabe: 1111
}

Godbolt Listing lst-0494-godb.cpp, https://godbolt.org/z/8jYeYPs7W:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8jYeYPs7W 
#include <iostream>
using std::cout;
class Base {
public:
  int data_ = 0;
};
class Derived1 : public virtual Base {
};
class Derived2 : public virtual Base {
};
class DerivedDerived : public Derived1, public Derived2 {
public:
  void method() {
     data_ = 1;  // eindeutig, denn es gibt nur ein data_
  }
};
void ausgabe(const DerivedDerived &dd) {
    cout << dd.data_
        << (((Derived1&)dd).data_)
        << (((Derived2&)dd).data_)
        << (((Base&)dd).data_) << '\n';
}
int main() {
  DerivedDerived dd{};
  ausgabe(dd);   // Ausgabe: 0000
  dd.method();   // setzt data_ auf 1
  ausgabe(dd);   // Ausgabe: 1111
}

Listing 18.19: Effektiv ruft nutzer() hier eine Schwestermethode auf.

Book listing lst-0495-book.cpp:

// https://godbolt.org/z/s9xnn7c5j 
#include <iostream>
using std::cout;
struct Base { // abstrakte Klasse
  virtual void anbieter() = 0;
  virtual void nutzer() = 0;
};
struct Derived1 : public virtual Base { // noch abstrakt
  virtual void nutzer() override { anbieter(); }
};
struct Derived2 : public virtual Base { // noch abstrakt
  virtual void anbieter() override { cout << "Derived2::anbieter!\n"; }
};
struct DerivedDerived : public Derived1, public Derived2 { // konkret
};
int main() {
  DerivedDerived dd{};
  DerivedDerived *pdd = &dd;
  Derived1* pd1 = pdd; // Cast innerhalb der Hierarchie
  Derived2* pd2 = pdd; // Cast innerhalb der Hierarchie
  pdd->nutzer();       // Ausgabe: Derived2::anbieter()!
  pd1->nutzer();       // Ausgabe: Derived2::anbieter()!
  pd2->nutzer();       // Ausgabe: Derived2::anbieter()!
}

Godbolt Listing lst-0495-godb.cpp, https://godbolt.org/z/s9xnn7c5j:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s9xnn7c5j 
#include <iostream>
using std::cout;
struct Base { // abstrakte Klasse
  virtual void anbieter() = 0;
  virtual void nutzer() = 0;
};
struct Derived1 : public virtual Base { // noch abstrakt
  virtual void nutzer() override { anbieter(); }
};
struct Derived2 : public virtual Base { // noch abstrakt
  virtual void anbieter() override { cout << "Derived2::anbieter!\n"; }
};
struct DerivedDerived : public Derived1, public Derived2 { // konkret
};
int main() {
  DerivedDerived dd{};
  DerivedDerived *pdd = &dd;
  Derived1* pd1 = pdd; // Cast innerhalb der Hierarchie
  Derived2* pd2 = pdd; // Cast innerhalb der Hierarchie
  pdd->nutzer();       // Ausgabe: Derived2::anbieter()!
  pd1->nutzer();       // Ausgabe: Derived2::anbieter()!
  pd2->nutzer();       // Ausgabe: Derived2::anbieter()!
}

Listing 18.20: Einen literalen Datentyp erstellen Sie mit einem constexpr-Konstruktor.

Book listing lst-0498-book.cpp:

// https://godbolt.org/z/Kvfx9Yeox 
#include <array>
class Value {
    int val_;
public:
    constexpr Value(int val) : val_{val} {};
    constexpr int get() const { return val_; }
};

constexpr Value fuenf{5}; // geht, Value ist literaler Datentyp

std::array<int,fuenf.get()> data; // geht, get ist constexpr

Godbolt Listing lst-0498-godb.cpp, https://godbolt.org/z/Kvfx9Yeox:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Kvfx9Yeox 
#include <array>
class Value {
    int val_;
public:
    constexpr Value(int val) : val_{val} {};
    constexpr int get() const { return val_; }
};

constexpr Value fuenf{5}; // geht, Value ist literaler Datentyp

std::array<int,fuenf.get()> data; // geht, get ist constexpr

Listing 18.21: Benutzerdefinierte Literale sind besonders nützlich mit literalen Datentypen.

Book listing lst-0499-book.cpp:

// https://godbolt.org/z/r1vYc7r5j 
#include <array>
#include <iostream>
#include <type_traits> // is_literal_type
class Value {
    int val_;
public:
    constexpr Value(int val) : val_{val} {};
    constexpr operator int() const { return val_; }
};
namespace lit {
    constexpr Value operator"" _val(const char*, size_t sz) { 
      return Value(sz); }
}
struct Nope {
    constexpr Nope() {};
    virtual ~Nope() {};                // nicht trivialer Destruktor
};
int main() {
    using namespace lit;
    constexpr Value fuenf{5};
    std::array<int,"11111"_val> data;  // benutzerdefiniertes Literal verwenden
    std::cout << data.size() << '\n';                        // Ausgabe: 5
    std::cout << std::boolalpha;
    std::cout << std::is_literal_type<Value>::value << '\n'; // Ausgabe: true
    std::cout << std::is_literal_type<Nope>::value << '\n';  // Ausgabe: false
}

Godbolt Listing lst-0499-godb.cpp, https://godbolt.org/z/r1vYc7r5j:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r1vYc7r5j 
#include <array>
#include <iostream>
#include <type_traits> // is_literal_type
class Value {
    int val_;
public:
    constexpr Value(int val) : val_{val} {};
    constexpr operator int() const { return val_; }
};
namespace lit {
    constexpr Value operator"" _val(const char*, size_t sz) { 
      return Value(sz); }
}
struct Nope {
    constexpr Nope() {};
    virtual ~Nope() {};                // nicht trivialer Destruktor
};
int main() {
    using namespace lit;
    constexpr Value fuenf{5};
    std::array<int,"11111"_val> data;  // benutzerdefiniertes Literal verwenden
    std::cout << data.size() << '\n';                        // Ausgabe: 5
    std::cout << std::boolalpha;
    std::cout << std::is_literal_type<Value>::value << '\n'; // Ausgabe: true
    std::cout << std::is_literal_type<Nope>::value << '\n';  // Ausgabe: false
}

Listing 19.1: Call-by-Reference als Basis für Polymorphie

Book listing lst-0501-book.cpp:

// https://godbolt.org/z/scqTWvhsv 
class Auto { };
  class VwBulli : public Auto { };
  class Ente : public Auto { };
void lassFahren(Auto wagen) { }   //             (ERR)  Wertparameter kopiert nur Basisklasse
void lassBremsen(Auto &wagen) { } // Referenzparameter
void lassHupen(Auto *wagen) { }   // Übergabe als Zeiger
int main() {
    VwBulli bulli{  };            // automatische Variable
    Auto *ente = new Ente{  };    // dynamisch verwaltet
    lassFahren(bulli);            //             (ERR)  wird zum Auto kopiert
    lassFahren(*ente);            //             (ERR)  wird zum Auto kopiert
    lassBremsen(bulli);           // bleibt VwBulli
    lassBremsen(*ente);           // bleibt Ente
    lassHupen(&bulli);            // bleibt VwBulli
    lassHupen(ente);              // bleibt Ente
}

Godbolt Listing lst-0501-godb.cpp, https://godbolt.org/z/scqTWvhsv:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/scqTWvhsv 
class Auto { };
  class VwBulli : public Auto { };
  class Ente : public Auto { };
void lassFahren(Auto wagen) { }   //             (ERR)  Wertparameter kopiert nur Basisklasse
void lassBremsen(Auto &wagen) { } // Referenzparameter
void lassHupen(Auto *wagen) { }   // Übergabe als Zeiger
int main() {
    VwBulli bulli{  };            // automatische Variable
    Auto *ente = new Ente{  };    // dynamisch verwaltet
    lassFahren(bulli);            //             (ERR)  wird zum Auto kopiert
    lassFahren(*ente);            //             (ERR)  wird zum Auto kopiert
    lassBremsen(bulli);           // bleibt VwBulli
    lassBremsen(*ente);           // bleibt Ente
    lassHupen(&bulli);            // bleibt VwBulli
    lassHupen(ente);              // bleibt Ente
}

Listing 19.2: Die Klasse Buch dient den Akteuren Leser und Bibliothekar.

Book listing lst-0502-book.cpp:

// https://godbolt.org/z/fdh4n5x84 
struct Buch {
   auto getTitel() { return Titel{"Das C++ Handbuch"s}; }
   auto getAutor() { return Autor{"Torsten T. Will"s}; }
   auto umblaettern() { return /* Referenz zur nächsten Seite */ 42; }
   auto getSeite() { return "aktueller Seiteninhalt"; }
   auto getStandort() { return /* Regalnummer/Buchnummer */ 73; }
};

Godbolt Listing lst-0502-godb.cpp, https://godbolt.org/z/fdh4n5x84:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fdh4n5x84 
struct Buch {
   auto getTitel() { return Titel{"Das C++ Handbuch"s}; }
   auto getAutor() { return Autor{"Torsten T. Will"s}; }
   auto umblaettern() { return /* Referenz zur nächsten Seite */ 42; }
   auto getSeite() { return "aktueller Seiteninhalt"; }
   auto getStandort() { return /* Regalnummer/Buchnummer */ 73; }
};

Listing 19.3: Die Änderungen eines Akteurs spielen sich meist nur noch in einer Klasse ab.

Book listing lst-0503-book.cpp:

// https://godbolt.org/z/Tq9xbGxs4 
struct Buch {
   auto getTitel() { return Titel{"Das C++ Handbuch"s}; }
   auto getAutor() { return Autor{"Torsten T. Will"s}; }
   auto umblaettern() { return /* Referenz zur nächsten Seite */ 42; }
   auto getSeite() { return "aktueller Seiteninhalt"; }
   auto getStandort() { return /* Regalnummer/Buchnummer */ 73; }
};
struct BuchFinder {
    Katalog katalog;
    auto finde(Buch& buch) { /* Regalnummer/Buchnummer */
        katalog.findeBuchNach(buch.getTitel(), buch.getAutor());
    }
};

Godbolt Listing lst-0503-godb.cpp, https://godbolt.org/z/Tq9xbGxs4:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Tq9xbGxs4 
struct Buch {
   auto getTitel() { return Titel{"Das C++ Handbuch"s}; }
   auto getAutor() { return Autor{"Torsten T. Will"s}; }
   auto umblaettern() { return /* Referenz zur nächsten Seite */ 42; }
   auto getSeite() { return "aktueller Seiteninhalt"; }
   auto getStandort() { return /* Regalnummer/Buchnummer */ 73; }
};
struct BuchFinder {
    Katalog katalog;
    auto finde(Buch& buch) { /* Regalnummer/Buchnummer */
        katalog.findeBuchNach(buch.getTitel(), buch.getAutor());
    }
};

Listing 19.4: Folgt nicht dem Open/Closed Principle

Book listing lst-0504-book.cpp:

// https://godbolt.org/z/vxTsveGjT 
#include <vector>
#include <memory> // unique_ptr
#include <iostream> // cout
enum class ShapeTag { CIRC, RECT };
struct Shape { // Data
    ShapeTag tag_;
    double v1_, v2_;
    Shape(double w, double h) : tag_{ShapeTag::RECT}, v1_{w}, v2_{h} {}
    Shape(double r) : tag_{ShapeTag::CIRC}, v1_{r}, v2_{0} {}
};
class AreaCalculator { // Logic
public:
    double area(const std::vector<std::unique_ptr<Shape>> &shapes) const {
        double result = 0;
        for(auto &shape :  shapes) {
            switch(shape->tag_) {
            case ShapeTag::CIRC:
                 result += 3.1415 * shape->v1_ * shape->v1_;
                 break;
            case ShapeTag::RECT:
                 result += shape->v1_*shape->v2_;
                 break;
            }
        }
        return result;
    }
};
int main() {
    std::vector<std::unique_ptr<Shape>> data{};
    data.push_back(std::make_unique<Shape>(10.));     // ein Kreis
    data.push_back(std::make_unique<Shape>(4., 6.));  // ein Rechteck
    // rechnen
    AreaCalculator calc{};
    std::cout  << calc.area( data ) << "\n";
}

Godbolt Listing lst-0504-godb.cpp, https://godbolt.org/z/vxTsveGjT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vxTsveGjT 
#include <vector>
#include <memory> // unique_ptr
#include <iostream> // cout
enum class ShapeTag { CIRC, RECT };
struct Shape { // Data
    ShapeTag tag_;
    double v1_, v2_;
    Shape(double w, double h) : tag_{ShapeTag::RECT}, v1_{w}, v2_{h} {}
    Shape(double r) : tag_{ShapeTag::CIRC}, v1_{r}, v2_{0} {}
};
class AreaCalculator { // Logic
public:
    double area(const std::vector<std::unique_ptr<Shape>> &shapes) const {
        double result = 0;
        for(auto &shape :  shapes) {
            switch(shape->tag_) {
            case ShapeTag::CIRC:
                 result += 3.1415 * shape->v1_ * shape->v1_;
                 break;
            case ShapeTag::RECT:
                 result += shape->v1_*shape->v2_;
                 break;
            }
        }
        return result;
    }
};
int main() {
    std::vector<std::unique_ptr<Shape>> data{};
    data.push_back(std::make_unique<Shape>(10.));     // ein Kreis
    data.push_back(std::make_unique<Shape>(4., 6.));  // ein Rechteck
    // rechnen
    AreaCalculator calc{};
    std::cout  << calc.area( data ) << "\n";
}

Listing 19.5: Folgt dem OCP

Book listing lst-0505-book.cpp:

// https://godbolt.org/z/YWE4bT4zG 
#include <vector>
#include <memory>    // unique_ptr
#include <iostream>  // cout
struct Shape {
    virtual ~Shape() {}
    virtual double area() const = 0; // abstrakt
};
class Rectangle : public Shape {
    double w_, h_;
public:
    Rectangle(double w, double h) : w_{w}, h_{h} {}
    double area() const override { return w_ * h_; }
};
class Circle : public Shape {
    double r_;
public:
    Circle(double r) : r_{r} {}
    double area() const override { return 3.1415*r_* r_; }
};
class AreaCalculator { // Logic
public:
    double area(const std::vector<std::unique_ptr<Shape>> &shapes) const {
        double result = 0;
        for(auto &shape :  shapes) {
            result += shape->area();
        }
        return result;
    }
};
int main() {
    std::vector<std::unique_ptr<Shape>> data{};
    data.push_back(std::make_unique<Circle>(10.));        // ein Kreis
    data.push_back(std::make_unique<Rectangle>(4., 6.));  // ein Rechteck
    // rechnen
    AreaCalculator calc{};
    std::cout  << calc.area( data ) << "\n";
}

Godbolt Listing lst-0505-godb.cpp, https://godbolt.org/z/YWE4bT4zG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YWE4bT4zG 
#include <vector>
#include <memory>    // unique_ptr
#include <iostream>  // cout
struct Shape {
    virtual ~Shape() {}
    virtual double area() const = 0; // abstrakt
};
class Rectangle : public Shape {
    double w_, h_;
public:
    Rectangle(double w, double h) : w_{w}, h_{h} {}
    double area() const override { return w_ * h_; }
};
class Circle : public Shape {
    double r_;
public:
    Circle(double r) : r_{r} {}
    double area() const override { return 3.1415*r_* r_; }
};
class AreaCalculator { // Logic
public:
    double area(const std::vector<std::unique_ptr<Shape>> &shapes) const {
        double result = 0;
        for(auto &shape :  shapes) {
            result += shape->area();
        }
        return result;
    }
};
int main() {
    std::vector<std::unique_ptr<Shape>> data{};
    data.push_back(std::make_unique<Circle>(10.));        // ein Kreis
    data.push_back(std::make_unique<Rectangle>(4., 6.));  // ein Rechteck
    // rechnen
    AreaCalculator calc{};
    std::cout  << calc.area( data ) << "\n";
}

GodboltId:rc67xWWfT

Book listing lst-0506-book.cpp:

// https://godbolt.org/z/rc67xWWfT 
#include <iostream>
struct Point { int x, y; };
class Rectangle {
protected:
    Point origin_;  int width_;  int height_;
public:
    Rectangle(Point o, int w, int h) : origin_{o}, width_{w}, height_{h} {}
    virtual void setHeight(int height) { height_ = height; }
    virtual int  getHeight() const { return height_; }
    virtual void setWidth(int width) { width_ = width; }
    virtual int getWidth() const { return width_; }
    virtual int getArea() const { return width_ * height_; }
};
class Square : public Rectangle {
public:
    Square(Point o, int wh) : Rectangle{o, wh, wh} {}
    void setHeight(int wh) override { width_ = height_ = wh; }
    void setWidth(int wh) override { width_ = height_ = wh; }
};
void areaCheck(Rectangle &rect) {
    rect.setWidth(5);
    rect.setHeight(4);
    auto areaValue = rect.getArea();
    if(areaValue != 20) {
        std::cout << "error!\n";
    } else {
        std::cout << "all fine\n";
    }
}
int main() {
    Rectangle rect{ {0,0}, 0,0 };
    areaCheck( rect );          // Ausgabe: all fine
    Square square{ {0,0}, 0 };
    areaCheck( square );        // Ausgabe: error!
}

Godbolt Listing lst-0506-godb.cpp, https://godbolt.org/z/rc67xWWfT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rc67xWWfT 
#include <iostream>
struct Point { int x, y; };
class Rectangle {
protected:
    Point origin_;  int width_;  int height_;
public:
    Rectangle(Point o, int w, int h) : origin_{o}, width_{w}, height_{h} {}
    virtual void setHeight(int height) { height_ = height; }
    virtual int  getHeight() const { return height_; }
    virtual void setWidth(int width) { width_ = width; }
    virtual int getWidth() const { return width_; }
    virtual int getArea() const { return width_ * height_; }
};
class Square : public Rectangle {
public:
    Square(Point o, int wh) : Rectangle{o, wh, wh} {}
    void setHeight(int wh) override { width_ = height_ = wh; }
    void setWidth(int wh) override { width_ = height_ = wh; }
};
void areaCheck(Rectangle &rect) {
    rect.setWidth(5);
    rect.setHeight(4);
    auto areaValue = rect.getArea();
    if(areaValue != 20) {
        std::cout << "error!\n";
    } else {
        std::cout << "all fine\n";
    }
}
int main() {
    Rectangle rect{ {0,0}, 0,0 };
    areaCheck( rect );          // Ausgabe: all fine
    Square square{ {0,0}, 0 };
    areaCheck( square );        // Ausgabe: error!
}

Listing 19.6: Kovarianz für Rückgabetypen

Book listing lst-0507-book.cpp:

// https://godbolt.org/z/Gxh4edc8n 
using std::vector;

struct B {};
struct D : public B {};

struct Base1 {
    virtual B& func();
};
struct Derived1 : public Base1 {
    virtual D& func() override;         // D& ist kovariant
};
struct Base2 {
    virtual B& func();
};
struct Derived2 : public Base2 {
    virtual D func() override;          //                     (ERR)  D ist nicht kovariant
};
struct Base3 {
    virtual vector<B> func();
};
struct Derived3 : public Base3 {
    virtual vector<D>& func() override; //                     (ERR)  vector<D>& ist nicht kovariant
};
struct Base4 {
    virtual vector<B*>& func();
};
struct Derived4 : public Base4 {
    virtual vector<D*>& func() override; //                     (ERR)  anderer Typ, nicht kovariant
};

Godbolt Listing lst-0507-godb.cpp, https://godbolt.org/z/Gxh4edc8n:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gxh4edc8n 
using std::vector;

struct B {};
struct D : public B {};

struct Base1 {
    virtual B& func();
};
struct Derived1 : public Base1 {
    virtual D& func() override;         // D& ist kovariant
};
struct Base2 {
    virtual B& func();
};
struct Derived2 : public Base2 {
    virtual D func() override;          //                     (ERR)  D ist nicht kovariant
};
struct Base3 {
    virtual vector<B> func();
};
struct Derived3 : public Base3 {
    virtual vector<D>& func() override; //                     (ERR)  vector<D>& ist nicht kovariant
};
struct Base4 {
    virtual vector<B*>& func();
};
struct Derived4 : public Base4 {
    virtual vector<D*>& func() override; //                     (ERR)  anderer Typ, nicht kovariant
};

GodboltId:4536hxvEK

Book listing lst-0510-book.cpp:

// https://godbolt.org/z/4536hxvEK 
int value = 42;
int& valueRef = value; // Referenz; kein Adressoperator & nötig
valueRef = 18;         // kein Dereferenzierungsoperator * nötig
cout << value << "\n"; // Ausgabe: 18

Godbolt Listing lst-0510-godb.cpp, https://godbolt.org/z/4536hxvEK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4536hxvEK 
int value = 42;
int& valueRef = value; // Referenz; kein Adressoperator & nötig
valueRef = 18;         // kein Dereferenzierungsoperator * nötig
cout << value << "\n"; // Ausgabe: 18

Listing 20.1: Zeiger können im Laufe ihres Lebens neue Adressen zugewiesen bekommen.

Book listing lst-0511-book.cpp:

// https://godbolt.org/z/qTxs8bTdz 
#include <vector>
#include <iostream>
using std::vector; using std::cout; using std::ostream;
ostream& printVector(ostream& os, const vector<int> &arg) { // Hilfsfunktion
    for(int w : arg) os << w << " "; return os;
}
int main() {
    vector<int> werte{ };
    werte.reserve(50);                      // Platz für 50 Werte garantieren
    int *groesstes = nullptr;               // mit besonderem Wert initialisieren
    for(int w : { 20, 2, 30, 15, 81, 104, 70, 2, }) {
        werte.push_back(w);
        if(!groesstes || *groesstes < w ) { // dereferenzieren zum Wert
            groesstes = &(werte.back());    // neue Adresse merken; deshalb nicht '*'
        }
    }
    printVector(cout, werte) << "\n";       // Ausgabe: 20 2 30 15 81 104 70 2
    // groesstes enthält nun die Adresse der 104:
    *groesstes = -999;                // dereferenzieren; also Wert überschreiben
    printVector(cout, werte) << "\n";       // Ausgabe: 20 2 30 15 81 –999 70 2
}

Godbolt Listing lst-0511-godb.cpp, https://godbolt.org/z/qTxs8bTdz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qTxs8bTdz 
#include <vector>
#include <iostream>
using std::vector; using std::cout; using std::ostream;
ostream& printVector(ostream& os, const vector<int> &arg) { // Hilfsfunktion
    for(int w : arg) os << w << " "; return os;
}
int main() {
    vector<int> werte{ };
    werte.reserve(50);                      // Platz für 50 Werte garantieren
    int *groesstes = nullptr;               // mit besonderem Wert initialisieren
    for(int w : { 20, 2, 30, 15, 81, 104, 70, 2, }) {
        werte.push_back(w);
        if(!groesstes || *groesstes < w ) { // dereferenzieren zum Wert
            groesstes = &(werte.back());    // neue Adresse merken; deshalb nicht '*'
        }
    }
    printVector(cout, werte) << "\n";       // Ausgabe: 20 2 30 15 81 104 70 2
    // groesstes enthält nun die Adresse der 104:
    *groesstes = -999;                // dereferenzieren; also Wert überschreiben
    printVector(cout, werte) << "\n";       // Ausgabe: 20 2 30 15 81 –999 70 2
}

Listing 20.2: Eine Rückgabe als Wert kann eine Kopie erzeugen.

Book listing lst-0514-book.cpp:

Planet erzeugePlanet(const Event &evt) { // Rückgabe als Wert
    Planet result{"Erde"};               // Stackobjekt
    result.setLocation(evt.getPosition());
    return result;                       // Rückgabe erzeugt (potenziell) Kopie
}

Listing 20.3: Eine Rückgabe als Zeiger kopiert nur den Zeiger, nicht das Objekt.

Book listing lst-0515-book.cpp:

// Rückgabe als (smarter) Pointer:
unique_ptr<Planet> erzeugePlanet(const Event &evt) {
    unique_ptr<Planet> result{ new Planet{"Venus"} };  // Heapobjekt
    result->setLocation(evt.getPosition());
    return result; // reicht Adresse weiter
}

Listing 20.4: In den folgenden Beispielen verwende ich Image als Klasse, zu der ich einen Zeiger haben will.

Book listing lst-0517-book.cpp:

// https://godbolt.org/z/ehhGPjabz 
#include <string>
#include <vector>
class Image {
    std::vector<char> bilddaten_;
public:
    explicit Image(const std::string& filename) { /* Bild laden */ }
    void draw() const { /* Bild malen */ };
};

Godbolt Listing lst-0517-godb.cpp, https://godbolt.org/z/ehhGPjabz:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ehhGPjabz 
#include <string>
#include <vector>
class Image {
    std::vector<char> bilddaten_;
public:
    explicit Image(const std::string& filename) { /* Bild laden */ }
    void draw() const { /* Bild malen */ };
};

Listing 20.5: unique_ptr als Datenfeld, Rückgabewert und lokale Variable

Book listing lst-0518-book.cpp:

// https://godbolt.org/z/Eh9ox6x9E 
#include <memory>                        // unique_ptr
#include <string>
#include <iostream>
using std::unique_ptr; using std::string;
class Component { };                     // Dummy-Fensterhierarchie
class Label : public Component { };
class Textfield : public Component { };
class Button : public Component {
public:
    int id_; // ID zur Unterscheidung der Buttons
    explicit Button(int id) : id_{id} {}
};
class Window { };
class MyDialog : public Window {
    string title_;
    unique_ptr<Label> lblVorname_{new Label{}};         // lauter Datenfelder
    unique_ptr<Textfield> txtVorname_{new Textfield{}}; // … an die Lebensdauer
    unique_ptr<Label> lblNachname_{new Label{}};        // … der Klasse gebunden
    unique_ptr<Textfield> txtNachname_{new Textfield{}};
    unique_ptr<Button> btnOk_{new Button{1}};
    unique_ptr<Button> btnAbbrechen_{new Button{2}};
public:
    explicit MyDialog(const string& title) : title_{title} {}
    unique_ptr<Button> showModal()
        { return std::move(btnOk_); }    // Platzhaltercode; OK gedrückt
};
unique_ptr<MyDialog> createDialog() {
    return unique_ptr<MyDialog>{ // temporärer Wert
        new MyDialog{"Bitte Namen eingeben"}};
}
int showDialog() {
    unique_ptr<MyDialog> dialog = createDialog();       // lokale Variable
    unique_ptr<Button> gedrueckt = dialog->showModal(); // Rückgabewert
    return gedrueckt->id_;
}
int main() {
    int gedrueckt_id = showDialog();
    if(gedrueckt_id == 1) {
        std::cout << "Danke, dass Sie OK gedrueckt haben\n";
    }
}

Godbolt Listing lst-0518-godb.cpp, https://godbolt.org/z/Eh9ox6x9E:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Eh9ox6x9E 
#include <memory>                        // unique_ptr
#include <string>
#include <iostream>
using std::unique_ptr; using std::string;
class Component { };                     // Dummy-Fensterhierarchie
class Label : public Component { };
class Textfield : public Component { };
class Button : public Component {
public:
    int id_; // ID zur Unterscheidung der Buttons
    explicit Button(int id) : id_{id} {}
};
class Window { };
class MyDialog : public Window {
    string title_;
    unique_ptr<Label> lblVorname_{new Label{}};         // lauter Datenfelder
    unique_ptr<Textfield> txtVorname_{new Textfield{}}; // … an die Lebensdauer
    unique_ptr<Label> lblNachname_{new Label{}};        // … der Klasse gebunden
    unique_ptr<Textfield> txtNachname_{new Textfield{}};
    unique_ptr<Button> btnOk_{new Button{1}};
    unique_ptr<Button> btnAbbrechen_{new Button{2}};
public:
    explicit MyDialog(const string& title) : title_{title} {}
    unique_ptr<Button> showModal()
        { return std::move(btnOk_); }    // Platzhaltercode; OK gedrückt
};
unique_ptr<MyDialog> createDialog() {
    return unique_ptr<MyDialog>{ // temporärer Wert
        new MyDialog{"Bitte Namen eingeben"}};
}
int showDialog() {
    unique_ptr<MyDialog> dialog = createDialog();       // lokale Variable
    unique_ptr<Button> gedrueckt = dialog->showModal(); // Rückgabewert
    return gedrueckt->id_;
}
int main() {
    int gedrueckt_id = showDialog();
    if(gedrueckt_id == 1) {
        std::cout << "Danke, dass Sie OK gedrueckt haben\n";
    }
}

Listing 20.6: Ein Spielfeld mit lauter verschiedenen Objekten.

Book listing lst-0520-book.cpp:

// https://godbolt.org/z/sas3b1E3b 
#include <vector>
#include <iostream>
#include <memory>                    // shared_ptr
#include <random>                    // uniform_int_distribution, random_device
namespace {                          // Beginn des anonymen Namensraums
using std::shared_ptr; using std::make_shared;
using std::vector; using std::cout;
struct Asteroid {
    int points_ = 100;
    int structure_ = 10;
};
struct Ship {
    shared_ptr<Asteroid> firedLastOn_{};
    int score_ = 0;
    int firepower = 1;
    bool fireUpon(shared_ptr<Asteroid> a);
};
struct GameBoard {
    vector<shared_ptr<Asteroid>> asteroids_;
    explicit GameBoard(int nAsteroids);
    bool shipFires(Ship& ship);
};
// Implementierung von Ship
bool Ship::fireUpon(shared_ptr<Asteroid> a) {
    if(!a) return false;             // ungültiger Asteroid
    a->structure_ -= firepower;
    if(a.get() == firedLastOn_.get())
        firepower *= 2 ;             // Schaden vergrößern
    else
        firepower = 1;               // zurücksetzen
    firedLastOn_ = a;
    return a->structure_ <= 0;       // kaputt?
}
// Implementierung von GameBoard
GameBoard::GameBoard(int nAsteroids) : asteroids_{}
{   // einige Standard-Asteroiden
    for(int idx=0; idx<nAsteroids; ++idx)
        asteroids_.push_back( make_shared<Asteroid>() );
}
int wuerfel(int min, int max) {
    /* static std::default_random_engine e{}; */   // Pseudozufallsgenerator
    static std::random_device e{};           // Zufallsgenerator
    return std::uniform_int_distribution<int>{min, max}(e); // würfeln
}
bool GameBoard::shipFires(Ship &ship) {
    int idx = wuerfel(0, asteroids_.size()-1);
    bool kaputt = ship.fireUpon(asteroids_[idx]);
    if(kaputt) {
        ship.score_ += asteroids_[idx]->points_;
        asteroids_.erase(asteroids_.begin()+idx);           // entfernen
    }
    return asteroids_.size() == 0;                          // alles kaputt
}
} // Ende des anonymen Namensraums
int main() {
    GameBoard game{10};                                     // 10 Asteroiden
    Ship ship{};
    for(int idx = 0; idx < 85; ++idx) {                     // 85 Schüsse
        if(game.shipFires(ship)) {
            cout << "Der Weltraum ist nach " << idx+1 << " Schuessen leer. ";
            break;
        }
    }
    cout << "Sie haben " << ship.score_ << " Punkte erreicht.\n";
}

Godbolt Listing lst-0520-godb.cpp, https://godbolt.org/z/sas3b1E3b:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sas3b1E3b 
#include <vector>
#include <iostream>
#include <memory>                    // shared_ptr
#include <random>                    // uniform_int_distribution, random_device
namespace {                          // Beginn des anonymen Namensraums
using std::shared_ptr; using std::make_shared;
using std::vector; using std::cout;
struct Asteroid {
    int points_ = 100;
    int structure_ = 10;
};
struct Ship {
    shared_ptr<Asteroid> firedLastOn_{};
    int score_ = 0;
    int firepower = 1;
    bool fireUpon(shared_ptr<Asteroid> a);
};
struct GameBoard {
    vector<shared_ptr<Asteroid>> asteroids_;
    explicit GameBoard(int nAsteroids);
    bool shipFires(Ship& ship);
};
// Implementierung von Ship
bool Ship::fireUpon(shared_ptr<Asteroid> a) {
    if(!a) return false;             // ungültiger Asteroid
    a->structure_ -= firepower;
    if(a.get() == firedLastOn_.get())
        firepower *= 2 ;             // Schaden vergrößern
    else
        firepower = 1;               // zurücksetzen
    firedLastOn_ = a;
    return a->structure_ <= 0;       // kaputt?
}
// Implementierung von GameBoard
GameBoard::GameBoard(int nAsteroids) : asteroids_{}
{   // einige Standard-Asteroiden
    for(int idx=0; idx<nAsteroids; ++idx)
        asteroids_.push_back( make_shared<Asteroid>() );
}
int wuerfel(int min, int max) {
    /* static std::default_random_engine e{}; */   // Pseudozufallsgenerator
    static std::random_device e{};           // Zufallsgenerator
    return std::uniform_int_distribution<int>{min, max}(e); // würfeln
}
bool GameBoard::shipFires(Ship &ship) {
    int idx = wuerfel(0, asteroids_.size()-1);
    bool kaputt = ship.fireUpon(asteroids_[idx]);
    if(kaputt) {
        ship.score_ += asteroids_[idx]->points_;
        asteroids_.erase(asteroids_.begin()+idx);           // entfernen
    }
    return asteroids_.size() == 0;                          // alles kaputt
}
} // Ende des anonymen Namensraums
int main() {
    GameBoard game{10};                                     // 10 Asteroiden
    Ship ship{};
    for(int idx = 0; idx < 85; ++idx) {                     // 85 Schüsse
        if(game.shipFires(ship)) {
            cout << "Der Weltraum ist nach " << idx+1 << " Schuessen leer. ";
            break;
        }
    }
    cout << "Sie haben " << ship.score_ << " Punkte erreicht.\n";
}

Listing 20.7: Wenn ein roher Zeiger ein Objekt besitzt, sind die möglichen Fehler oft schwer zu erkennen.

Book listing lst-0523-book.cpp:

// https://godbolt.org/z/Mqrxxs11Y 
struct StereoImage {
    Image* rechts_;        //             (ERR)  roher Zeiger
    Image* links_;         //             (ERR)  roher Zeiger
    StereoImage(const string& nameBase)           // konstruieren
      : rechts_{new Image{nameBase+"rechts.jpg"}} // okay
      , links_{new Image{nameBase+"links.jpg"}}   // gefährlich
      { }
    ~StereoImage() {       // entfernen
        delete rechts_; delete links_;
    }
    StereoImage(const StereoImage&) = delete;     // keine Kopie
    StereoImage& operator=(const StereoImage&) = delete; // keine Zuweisung
};
int main() {
    Image* bild = new Image{"bild.jpg"};          //             (ERR)  einem rohen Zeiger?
    StereoImage stereo{"3d"};
    delete bild;
}

Godbolt Listing lst-0523-godb.cpp, https://godbolt.org/z/Mqrxxs11Y:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mqrxxs11Y 
struct StereoImage {
    Image* rechts_;        //             (ERR)  roher Zeiger
    Image* links_;         //             (ERR)  roher Zeiger
    StereoImage(const string& nameBase)           // konstruieren
      : rechts_{new Image{nameBase+"rechts.jpg"}} // okay
      , links_{new Image{nameBase+"links.jpg"}}   // gefährlich
      { }
    ~StereoImage() {       // entfernen
        delete rechts_; delete links_;
    }
    StereoImage(const StereoImage&) = delete;     // keine Kopie
    StereoImage& operator=(const StereoImage&) = delete; // keine Zuweisung
};
int main() {
    Image* bild = new Image{"bild.jpg"};          //             (ERR)  einem rohen Zeiger?
    StereoImage stereo{"3d"};
    delete bild;
}

Listing 20.8: prims enthält Zeiger in einen anderen Container.

Book listing lst-0525-book.cpp:

// https://godbolt.org/z/YMe5PY6aT 
#include <vector>
#include <numeric>   // iota
#include <iostream>
using std::vector; using std::cout;
struct Zahl {        // stellvertretend für ein großes, teures Objekt
    unsigned long val_;
    Zahl(unsigned long val) : val_{val} {}
    Zahl() : val_{0} {}
};
/* ermittelt anhand bisheriger Primzahlen, ob z eine Primzahl ist */
bool isPrim(const Zahl& z, const vector<Zahl*> prims) {
    for(Zahl* p : prims) {
        if((p->val_*p->val_) > z.val_) return true;   // zu groß
        if(z.val_ % p->val_ == 0) return false;       // ist Teiler
    }
    return true;
}
int main() {
    vector<Zahl> alleZahlen(98);   // 98 mit null initialisierte Elemente
    std::iota(begin(alleZahlen), end(alleZahlen), 3); // 3..100
    /* alleZahlen enthält jetzt {3..100} */
    vector<Zahl*> prims{};         // bekommt ermittelte Primzahlen
    Zahl zwei{2};
    prims.push_back(&zwei);        // die 2 wird gebraucht
    for(Zahl &z : alleZahlen) {    // über alle Zahlen iterieren
        if(isPrim(z, prims)) {
            prims.push_back( &z ); // speichere Adresse
        }
    }
    /* Rest ausgeben */
    for(Zahl* p : prims)
        cout << p->val_ << " ";
    cout << "\n";
}

Godbolt Listing lst-0525-godb.cpp, https://godbolt.org/z/YMe5PY6aT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YMe5PY6aT 
#include <vector>
#include <numeric>   // iota
#include <iostream>
using std::vector; using std::cout;
struct Zahl {        // stellvertretend für ein großes, teures Objekt
    unsigned long val_;
    Zahl(unsigned long val) : val_{val} {}
    Zahl() : val_{0} {}
};
/* ermittelt anhand bisheriger Primzahlen, ob z eine Primzahl ist */
bool isPrim(const Zahl& z, const vector<Zahl*> prims) {
    for(Zahl* p : prims) {
        if((p->val_*p->val_) > z.val_) return true;   // zu groß
        if(z.val_ % p->val_ == 0) return false;       // ist Teiler
    }
    return true;
}
int main() {
    vector<Zahl> alleZahlen(98);   // 98 mit null initialisierte Elemente
    std::iota(begin(alleZahlen), end(alleZahlen), 3); // 3..100
    /* alleZahlen enthält jetzt {3..100} */
    vector<Zahl*> prims{};         // bekommt ermittelte Primzahlen
    Zahl zwei{2};
    prims.push_back(&zwei);        // die 2 wird gebraucht
    for(Zahl &z : alleZahlen) {    // über alle Zahlen iterieren
        if(isPrim(z, prims)) {
            prims.push_back( &z ); // speichere Adresse
        }
    }
    /* Rest ausgeben */
    for(Zahl* p : prims)
        cout << p->val_ << " ";
    cout << "\n";
}

Listing 20.9: Liefern Sie keine Adressen von funktionslokalen Objekten zurück.

Book listing lst-0528-book.cpp:

vector<Zahl*> primZeiger(unsigned long bis) { //             (ERR)  Vektor von Zeigern ist verdächtig
    vector<Zahl> alleZahlen;
    vector<Zahl*> prims{};
    // …
    for(Zahl &z : alleZahlen)
        if(isPrim(z, prims))
            prims.push_back( &z ); // speichere Adresse
    return prims; //             (ERR)  Zeiger auf funktionslokale Objekte
}

Listing 20.10: Mit rohen Zeigern, die in ein C-Array zeigen, können Sie rechnen.

Book listing lst-0533-book.cpp:

// https://godbolt.org/z/3zrK76zn8 
#include <iostream>
int main() {
    int carray[10] = { 1,1 };               // initialisiert zu { 1,1,0,0,0,0,0,0,0,0 }
    int* ende = carray+10;                  // Zeiger hinter das letzte Element
    for(int* p =carray+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);               // addiert die vorigen beiden Zahlen
    }
    for(int const * p=carray; p != ende; ++p)
        std::cout << *p << " ";
    std::cout << "\n";
}

Godbolt Listing lst-0533-godb.cpp, https://godbolt.org/z/3zrK76zn8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3zrK76zn8 
#include <iostream>
int main() {
    int carray[10] = { 1,1 };               // initialisiert zu { 1,1,0,0,0,0,0,0,0,0 }
    int* ende = carray+10;                  // Zeiger hinter das letzte Element
    for(int* p =carray+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);               // addiert die vorigen beiden Zahlen
    }
    for(int const * p=carray; p != ende; ++p)
        std::cout << *p << " ";
    std::cout << "\n";
}

Listing 20.11: C-Arrays verfallen als Parameter zu rohen Zeigern.

Book listing lst-0537-book.cpp:

// https://godbolt.org/z/1qx16Gr61 
#include <iostream>
void fibonacci(int data[], int* ende) {
    for(int* p = data+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);
    }
}
std::ostream& print(std::ostream &os, int data[], int* ende) {
    for(int const * p=data; p != ende; ++p)
        std::cout << *p << " ";
    return os;
}
int main() {
    int carray[10] = { 1,1 }; // initialisiert zu { 1,1,0,0,0,0,0,0,0,0 }
    fibonacci(carray, carray+10);
    print(std::cout, carray, carray+10) << "\n";
}

Godbolt Listing lst-0537-godb.cpp, https://godbolt.org/z/1qx16Gr61:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1qx16Gr61 
#include <iostream>
void fibonacci(int data[], int* ende) {
    for(int* p = data+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);
    }
}
std::ostream& print(std::ostream &os, int data[], int* ende) {
    for(int const * p=data; p != ende; ++p)
        std::cout << *p << " ";
    return os;
}
int main() {
    int carray[10] = { 1,1 }; // initialisiert zu { 1,1,0,0,0,0,0,0,0,0 }
    fibonacci(carray, carray+10);
    print(std::cout, carray, carray+10) << "\n";
}

Listing 20.12: »unique_ptr« arbeitet mit dem dynamischen C-Array zusammen.

Book listing lst-0541-book.cpp:

// https://godbolt.org/z/MEqcExjrY 
#include <memory>      // unique_ptr
#include <iostream>    // cout
std::unique_ptr<int[]> createData(size_t sz) {
    return std::unique_ptr<int[]>(new int[sz]);
}
void fibonacci(int data[], int* ende) {
    for(int* p = data+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);
    }
}
std::ostream& print(std::ostream &os, int data[], int* ende) {
    for(int const* p= data; p != ende; ++p)
        std::cout << *p << " ";
    return os;
}
int main() {
    std::unique_ptr<int[]> data { createData(10) };
    data[0] = 1; // setzen Sie Werte im Array durch den unique_ptr
    data[1] = 1;
    fibonacci(data.get(), data.get()+10); // holen Sie sich den C-Array-Zeiger mit get()
    print(std::cout, data.get(), data.get()+10) << "\n";
}

Godbolt Listing lst-0541-godb.cpp, https://godbolt.org/z/MEqcExjrY:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MEqcExjrY 
#include <memory>      // unique_ptr
#include <iostream>    // cout
std::unique_ptr<int[]> createData(size_t sz) {
    return std::unique_ptr<int[]>(new int[sz]);
}
void fibonacci(int data[], int* ende) {
    for(int* p = data+2; p != ende; ++p) {
        *p = *(p-1) + *(p-2);
    }
}
std::ostream& print(std::ostream &os, int data[], int* ende) {
    for(int const* p= data; p != ende; ++p)
        std::cout << *p << " ";
    return os;
}
int main() {
    std::unique_ptr<int[]> data { createData(10) };
    data[0] = 1; // setzen Sie Werte im Array durch den unique_ptr
    data[1] = 1;
    fibonacci(data.get(), data.get()+10); // holen Sie sich den C-Array-Zeiger mit get()
    print(std::cout, data.get(), data.get()+10) << "\n";
}

GodboltId:s6sss481E

Book listing lst-0545-book.cpp:

// https://godbolt.org/z/s6sss481E 
const char vimes[13] = "Samuel Vimes"; // const char[13]
const char colon[] = "Fred Colon";     // const char[11]
const char* nobby = "Nobby Nobbs";     // const char[12]

Godbolt Listing lst-0545-godb.cpp, https://godbolt.org/z/s6sss481E:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s6sss481E 
const char vimes[13] = "Samuel Vimes"; // const char[13]
const char colon[] = "Fred Colon";     // const char[11]
const char* nobby = "Nobby Nobbs";     // const char[12]

Listing 20.13: Mit »string« fällt Ihnen oft gar nicht auf, dass Textliterale »const char[]« sind.

Book listing lst-0546-book.cpp:

// https://godbolt.org/z/oKsz7d55T 
#include <string>
#include <iostream>                    // cout
using std::string; using std::cout;
string greet(string name) {
    return name + "!";                 // string operator+(string, const char*)
}
int main() {
    string name{ "Havaloc Vetinari" }; // explizit: string(const char*)
    cout << "Angua";                   // ostream& operator<<(ostream&, const char*)
    cout <<                            // ostream& operator<<(ostream, string)
      greet("Carrot Ironfoundersson"); // implizit: string(const char*)
}

Godbolt Listing lst-0546-godb.cpp, https://godbolt.org/z/oKsz7d55T:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oKsz7d55T 
#include <string>
#include <iostream>                    // cout
using std::string; using std::cout;
string greet(string name) {
    return name + "!";                 // string operator+(string, const char*)
}
int main() {
    string name{ "Havaloc Vetinari" }; // explizit: string(const char*)
    cout << "Angua";                   // ostream& operator<<(ostream&, const char*)
    cout <<                            // ostream& operator<<(ostream, string)
      greet("Carrot Ironfoundersson"); // implizit: string(const char*)
}

Listing 20.14: Iteratoren holen Sie mit »begin« und »end«.

Book listing lst-0547-book.cpp:

// https://godbolt.org/z/4nqz4ed4W 
#include <vector>
#include <iostream> // cout

using std::vector;
int main() {
    vector data{ 5,4,3,2,1 };
    vector<int>::const_iterator ende = data.end(); // oder end(data)
    for(vector<int>::const_iterator it = data.begin(); it!=ende; ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";
}

Godbolt Listing lst-0547-godb.cpp, https://godbolt.org/z/4nqz4ed4W:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4nqz4ed4W 
#include <vector>
#include <iostream> // cout

using std::vector;
int main() {
    vector data{ 5,4,3,2,1 };
    vector<int>::const_iterator ende = data.end(); // oder end(data)
    for(vector<int>::const_iterator it = data.begin(); it!=ende; ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";
}

Listing 20.15: Rohe Zeiger können Sie wie Iteratoren verwenden.

Book listing lst-0548-book.cpp:

// https://godbolt.org/z/zsqKz76cj 
#include <iostream>   // cout
#include <iterator>   // ostream_iterator
#include <algorithm>  // copy, ranges::copy
int main () {
  int data[6] = { 1, 2, 3, 7, 9, 10 };
  std::ostream_iterator<int> out_it (std::cout,", ");
  std::copy(data, data+6, out_it);           // Zeiger als Iteratoren
  std::cout << "\n";                         // Ausgabe: 1, 2, 3, 7, 9, 10
  std::ranges::copy(data, out_it);           // C-Array-Zeiger als Range
  std::cout << "\n";                         // Ausgabe: 1, 2, 3, 7, 9, 10
}

Godbolt Listing lst-0548-godb.cpp, https://godbolt.org/z/zsqKz76cj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zsqKz76cj 
#include <iostream>   // cout
#include <iterator>   // ostream_iterator
#include <algorithm>  // copy, ranges::copy
int main () {
  int data[6] = { 1, 2, 3, 7, 9, 10 };
  std::ostream_iterator<int> out_it (std::cout,", ");
  std::copy(data, data+6, out_it);           // Zeiger als Iteratoren
  std::cout << "\n";                         // Ausgabe: 1, 2, 3, 7, 9, 10
  std::ranges::copy(data, out_it);           // C-Array-Zeiger als Range
  std::cout << "\n";                         // Ausgabe: 1, 2, 3, 7, 9, 10
}

Listing 20.16: Lohnt es sich, das Freigeben von Speicher zu sparen?

Book listing lst-0549-book.cpp:

// https://godbolt.org/z/M13eYMrjG 
#include <map>
#include <memory> // unique_ptr
#include <string>
#include <iostream>
#include <chrono> // Zeitmessung
using std::map; using std::cout; using std::endl; using namespace std::chrono;
struct Node {
  std::unique_ptr<int> d_;
  Node() : Node{0}  { }
  explicit Node(int d) : d_{ new int } { *d_ = d; } // auch etwas Speicher
  friend bool operator<(const Node& a, const Node& b) {return *a.d_<*b.d_;}
  friend bool operator==(const Node& a, const Node& b) {return *a.d_==*b.d_;}
};
long long millisSeit(steady_clock::time_point start) { // Helfer zur Zeitmessung
  return duration_cast<milliseconds>(steady_clock::now()-start).count();
}

int main() {
  std::unique_ptr<map<int,Node>> riesig{ new map<int,Node>{} };
  cout << "Aufbau..." << endl;
  steady_clock::time_point start = steady_clock::now();
  for(int idx=0; idx < 100*1000*1000; ++idx) {   // massive Menge in der map
      (*riesig)[idx] = Node{idx};
  }
  cout << "Fertig: " << millisSeit(start) << " ms" << endl; // Zeitmessung hier
  start = steady_clock::now();
  riesig.reset();                                           // wegräumen hier
  cout << "Ende: " << millisSeit(start) << " ms" << endl;   // Zeitmessung hier
}

Godbolt Listing lst-0549-godb.cpp, https://godbolt.org/z/M13eYMrjG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M13eYMrjG 
#include <map>
#include <memory> // unique_ptr
#include <string>
#include <iostream>
#include <chrono> // Zeitmessung
using std::map; using std::cout; using std::endl; using namespace std::chrono;
struct Node {
  std::unique_ptr<int> d_;
  Node() : Node{0}  { }
  explicit Node(int d) : d_{ new int } { *d_ = d; } // auch etwas Speicher
  friend bool operator<(const Node& a, const Node& b) {return *a.d_<*b.d_;}
  friend bool operator==(const Node& a, const Node& b) {return *a.d_==*b.d_;}
};
long long millisSeit(steady_clock::time_point start) { // Helfer zur Zeitmessung
  return duration_cast<milliseconds>(steady_clock::now()-start).count();
}

int main() {
  std::unique_ptr<map<int,Node>> riesig{ new map<int,Node>{} };
  cout << "Aufbau..." << endl;
  steady_clock::time_point start = steady_clock::now();
  for(int idx=0; idx < 100*1000*1000; ++idx) {   // massive Menge in der map
      (*riesig)[idx] = Node{idx};
  }
  cout << "Fertig: " << millisSeit(start) << " ms" << endl; // Zeitmessung hier
  start = steady_clock::now();
  riesig.reset();                                           // wegräumen hier
  cout << "Ende: " << millisSeit(start) << " ms" << endl;   // Zeitmessung hier
}

Listing 21.1: Zeilen, die Präprozessordirektiven enthalten, beginnen mit einem #.

Book listing lst-0551-book.cpp:

// https://godbolt.org/z/MjcvochqP 
// Dateiname: meine-makros.hpp
#ifndef MEINE_MAKROS_HPP  // Include Guard
#define MEINE_MAKROS_HPP
#include <iostream> // cout, cerr
#include <vector>
#ifdef AUSGABE_AUF_STANDARD
#  define OUT std::cout
#else
#  define OUT std::cerr
#endif
#define MESSAGE(text) { (OUT) << text << "\n"; }
using container_type = std::vector<int>;
static constexpr unsigned SIZE = 10;
#endif

Godbolt Listing lst-0551-godb.cpp, https://godbolt.org/z/MjcvochqP:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MjcvochqP 
// Dateiname: meine-makros.hpp
#ifndef MEINE_MAKROS_HPP  // Include Guard
#define MEINE_MAKROS_HPP
#include <iostream> // cout, cerr
#include <vector>
#ifdef AUSGABE_AUF_STANDARD
#  define OUT std::cout
#else
#  define OUT std::cerr
#endif
#define MESSAGE(text) { (OUT) << text << "\n"; }
using container_type = std::vector<int>;
static constexpr unsigned SIZE = 10;
#endif

Listing 21.2: Ihre Hauptdatei mit »main« bindet per »#include« die Headerdatei ein.

Book listing lst-0552-book.cpp:

// https://godbolt.org/z/zG91TMEa8 
// Dateiname: makros.cpp
#define AUSGABE_AUF_STANDARD // Umschalten von cerr und cout
#include "meine-makros.hpp"
#include "meine-makros.hpp"  // Ups, aus Versehen doppelt.
int main() {
    MESSAGE("Programmstart");
    container_type data(SIZE);
    MESSAGE("Der Container hat " << data.size() << " Elemente.");
    MESSAGE("Programmende");
    OUT << "Das ging ja noch mal gut.\n";
}

Godbolt Listing lst-0552-godb.cpp, https://godbolt.org/z/zG91TMEa8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zG91TMEa8 
// Dateiname: makros.cpp
#define AUSGABE_AUF_STANDARD // Umschalten von cerr und cout
#include "meine-makros.hpp"
#include "meine-makros.hpp"  // Ups, aus Versehen doppelt.
int main() {
    MESSAGE("Programmstart");
    container_type data(SIZE);
    MESSAGE("Der Container hat " << data.size() << " Elemente.");
    MESSAGE("Programmende");
    OUT << "Das ging ja noch mal gut.\n";
}

Listing 21.3: Das Ergebnis des Präprozessordurchlaufs

Book listing lst-0557-book.cpp:

// https://godbolt.org/z/6coqbhfKM 
// …hier Inhalt von <vector>…
// …hier Inhalt von <iostream>…
using container_type = std::vector<int>;
static constexpr unsigned SIZE = 10;
int main() {
  { (std::cout) << "Programmstart" << "\n"; }
  container_type data(SIZE);
  { (std::cout) << "Der Container hat " << data.size() << " Elemente." << "\n";}
  { (std::cout) << "Programmende" << "\n"; }
  { std::cout << "Das ging ja noch mal gut.\n"; }
}

Godbolt Listing lst-0557-godb.cpp, https://godbolt.org/z/6coqbhfKM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6coqbhfKM 
// …hier Inhalt von <vector>…
// …hier Inhalt von <iostream>…
using container_type = std::vector<int>;
static constexpr unsigned SIZE = 10;
int main() {
  { (std::cout) << "Programmstart" << "\n"; }
  container_type data(SIZE);
  { (std::cout) << "Der Container hat " << data.size() << " Elemente." << "\n";}
  { (std::cout) << "Programmende" << "\n"; }
  { std::cout << "Das ging ja noch mal gut.\n"; }
}

Listing 21.5: Die rein textuelle Ersetzung führt bei Makros zur Mehrfachausführung.

Book listing lst-0565-book.cpp:

// https://godbolt.org/z/jzKfabPh3 
#include <cmath> // sin, cos
constexpr double max2(double a, double b) { return a > b ? a : b; }
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    double f = max2(sin(3.141592/2), cos(3.141592/2));
    double e = MAX2(sin(3.141592/2), cos(3.141592/2));
}

Godbolt Listing lst-0565-godb.cpp, https://godbolt.org/z/jzKfabPh3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jzKfabPh3 
#include <cmath> // sin, cos
constexpr double max2(double a, double b) { return a > b ? a : b; }
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    double f = max2(sin(3.141592/2), cos(3.141592/2));
    double e = MAX2(sin(3.141592/2), cos(3.141592/2));
}

GodboltId:YzYz3x1zx

Book listing lst-0567-book.cpp:

// https://godbolt.org/z/YzYz3x1zx 
#include <iostream>
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    int x = 0;
    int y = 0;
    int z = MAX2( ++x, ++y ); //             (ERR)  expandiert Argumente mehrfach
    std::cout << "x:"<< x << " y:"<< y << " z:"<<z << '\n';
}

Godbolt Listing lst-0567-godb.cpp, https://godbolt.org/z/YzYz3x1zx:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YzYz3x1zx 
#include <iostream>
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    int x = 0;
    int y = 0;
    int z = MAX2( ++x, ++y ); //             (ERR)  expandiert Argumente mehrfach
    std::cout << "x:"<< x << " y:"<< y << " z:"<<z << '\n';
}

GodboltId:5zrfvovaW

Book listing lst-0568-book.cpp:

// https://godbolt.org/z/5zrfvovaW 
#include <string>
#include <cmath> // sin, cos
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    double e = MAX2(sin(3.141592/2), cos(3.141592/2));
    int i = MAX2(10+12+45, 100/5+20);
    std::string s = MAX2(std::string("Ernie"), std::string("Bert"));
}

Godbolt Listing lst-0568-godb.cpp, https://godbolt.org/z/5zrfvovaW:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5zrfvovaW 
#include <string>
#include <cmath> // sin, cos
#define MAX2(a,b) ((a) > (b) ? (a) : (b))
int main() {
    double e = MAX2(sin(3.141592/2), cos(3.141592/2));
    int i = MAX2(10+12+45, 100/5+20);
    std::string s = MAX2(std::string("Ernie"), std::string("Bert"));
}

GodboltId:6xzTx83zE

Book listing lst-0569-book.cpp:

// https://godbolt.org/z/6xzTx83zE 
#include <string>
#include <cmath> // sin, cos
constexpr double max2(double a, double b) { return  a > b ? a : b; }
constexpr int max2(int a, int b) { return  a > b ? a : b; }
std::string max2(const std::string &a, const std::string &b)
    { return  a > b ? a : b; }
int main() {
    double e = max2(sin(3.141592/2), cos(3.141592/2));
    double i = max2(10+12+45, 100/5+20);
    std::string s = max2("Ernie", "Bert");
}

Godbolt Listing lst-0569-godb.cpp, https://godbolt.org/z/6xzTx83zE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6xzTx83zE 
#include <string>
#include <cmath> // sin, cos
constexpr double max2(double a, double b) { return  a > b ? a : b; }
constexpr int max2(int a, int b) { return  a > b ? a : b; }
std::string max2(const std::string &a, const std::string &b)
    { return  a > b ? a : b; }
int main() {
    double e = max2(sin(3.141592/2), cos(3.141592/2));
    double i = max2(10+12+45, 100/5+20);
    std::string s = max2("Ernie", "Bert");
}

Listing 21.6: Ein einfaches Funktionstemplate ist viel besser als ein Makro.

Book listing lst-0570-book.cpp:

// https://godbolt.org/z/acMjvxcM5 
#include <string>
#include <cmath> // sin, cos
template<typename TYP>
constexpr TYP max2(const TYP &a, const TYP &b)
    { return  a > b ? a : b; }
int main() {
    double e = max2(sin(3.141592/2), cos(3.141592/2));
    double i = max2(10+12+45, 100/5+20);
    std::string s = max2(std::string("Ernie"), std::string("Bert"));
}

Godbolt Listing lst-0570-godb.cpp, https://godbolt.org/z/acMjvxcM5:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/acMjvxcM5 
#include <string>
#include <cmath> // sin, cos
template<typename TYP>
constexpr TYP max2(const TYP &a, const TYP &b)
    { return  a > b ? a : b; }
int main() {
    double e = max2(sin(3.141592/2), cos(3.141592/2));
    double i = max2(10+12+45, 100/5+20);
    std::string s = max2(std::string("Ernie"), std::string("Bert"));
}

Listing 22.1: Das Programm »gzpack.cpp« nutzt eine C-Bibliothek. Hier sehen Sie die Sektion mit den Includes.

Book listing lst-0577-book.cpp:

// https://godbolt.org/z/9Trh8h8Mb 
#include <string>
#include <vector>
#include <span>      // C++20
#include <fstream>   // ifstream
#include <stdexcept> // runtime_error
#include <iostream>  // cerr
// C-Header:
#include <zlib.h>    // gzXyz; sudo aptitude install libz-dev
#include <cerrno>    // errno
#include <cstring>   // strerror
namespace {
using std::string; using std::span; using std::byte;

Godbolt Listing lst-0577-godb.cpp, https://godbolt.org/z/9Trh8h8Mb:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9Trh8h8Mb 
#include <string>
#include <vector>
#include <span>      // C++20
#include <fstream>   // ifstream
#include <stdexcept> // runtime_error
#include <iostream>  // cerr
// C-Header:
#include <zlib.h>    // gzXyz; sudo aptitude install libz-dev
#include <cerrno>    // errno
#include <cstring>   // strerror
namespace {
using std::string; using std::span; using std::byte;

Listing 22.2: Dieser Teil von »gzpack.cpp« enthält alle verwendeten C-Funktionen.

Book listing lst-0578-book.cpp:

// https://godbolt.org/z/Yh7j1WEGc 
class GzWriteStream {                         // RAII-Wrapper
public:
    gzFile gz_ ;                              // C-Struct aus zlib.h
    explicit GzWriteStream(const string& filename)
        : gz_{gzopen(filename.c_str(),"wb9")} // 'w': write, 'b':binary, '9':level
    {
        if(gz_==NULL) throw std::runtime_error(std::strerror(errno));
    }
    ~GzWriteStream() {
        gzclose(gz_);
    }
    GzWriteStream& operator<<(span<char> &data) {
        write(data);
        return *this;
    }
private:
    void write(span<char> data) {
        auto bytes = std::as_bytes(data); // C++20
        auto res = gzwrite(gz_, bytes.data(), size(bytes));
        if(res==0) throw std::runtime_error("Fehler beim Schreiben");
    }
    GzWriteStream(const GzWriteStream&) = delete;            // keine Kopie
    GzWriteStream& operator=(const GzWriteStream&) = delete; // keine Zuweisung
};

Godbolt Listing lst-0578-godb.cpp, https://godbolt.org/z/Yh7j1WEGc:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Yh7j1WEGc 
class GzWriteStream {                         // RAII-Wrapper
public:
    gzFile gz_ ;                              // C-Struct aus zlib.h
    explicit GzWriteStream(const string& filename)
        : gz_{gzopen(filename.c_str(),"wb9")} // 'w': write, 'b':binary, '9':level
    {
        if(gz_==NULL) throw std::runtime_error(std::strerror(errno));
    }
    ~GzWriteStream() {
        gzclose(gz_);
    }
    GzWriteStream& operator<<(span<char> &data) {
        write(data);
        return *this;
    }
private:
    void write(span<char> data) {
        auto bytes = std::as_bytes(data); // C++20
        auto res = gzwrite(gz_, bytes.data(), size(bytes));
        if(res==0) throw std::runtime_error("Fehler beim Schreiben");
    }
    GzWriteStream(const GzWriteStream&) = delete;            // keine Kopie
    GzWriteStream& operator=(const GzWriteStream&) = delete; // keine Zuweisung
};

Listing 22.3: Dieser Teil von »gzpack.cpp« behandelt das Lesen und Schreiben der Dateien.

Book listing lst-0580-book.cpp:

// https://godbolt.org/z/3P9ToPEYq 
std::vector<char> leseDatei(const string& fName) {
    std::ifstream file{ fName, std::ifstream::binary };
    if(!file) throw std::runtime_error("Fehler beim Oeffnen der Eingabe");
    file.seekg(0, file.end);          // ans Dateiende springen
    const auto laenge = file.tellg(); // aktuelle Position ist Dateigröße
    if(laenge > 1024*1024*1024)
        throw std::runtime_error("Nicht mehr als 1 GB bitte");
    file.seekg(0, file.beg);          // zurück an den Anfang
    std::vector<char> data(laenge);   // Platz schaffen
    file.read(data.data(), laenge);   // in einem Rutsch lesen
    return data;                      // wird nicht kopiert (Stichwort: RVO)
}
void packe(const string& fNameIn, const string& fNameOut) {
    auto data = leseDatei(fNameIn);   // lese Eingabe
    GzWriteStream gz{fNameOut};       // initialisiere Ausgabe
    gz << data;
}

Godbolt Listing lst-0580-godb.cpp, https://godbolt.org/z/3P9ToPEYq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3P9ToPEYq 
std::vector<char> leseDatei(const string& fName) {
    std::ifstream file{ fName, std::ifstream::binary };
    if(!file) throw std::runtime_error("Fehler beim Oeffnen der Eingabe");
    file.seekg(0, file.end);          // ans Dateiende springen
    const auto laenge = file.tellg(); // aktuelle Position ist Dateigröße
    if(laenge > 1024*1024*1024)
        throw std::runtime_error("Nicht mehr als 1 GB bitte");
    file.seekg(0, file.beg);          // zurück an den Anfang
    std::vector<char> data(laenge);   // Platz schaffen
    file.read(data.data(), laenge);   // in einem Rutsch lesen
    return data;                      // wird nicht kopiert (Stichwort: RVO)
}
void packe(const string& fNameIn, const string& fNameOut) {
    auto data = leseDatei(fNameIn);   // lese Eingabe
    GzWriteStream gz{fNameOut};       // initialisiere Ausgabe
    gz << data;
}

Listing 22.4: Mit »main« des Programms »gzpack.cpp« ist das Beispiel komplett.

Book listing lst-0581-book.cpp:

// https://godbolt.org/z/4sod8vrr6 
} // namespace
int main(int argc, const char* argv[]) {
    try {
        const std::vector<string> fNamen {argv+1, argv+argc};
        for(auto fName : fNamen) {
            std::cout << "packe " << fName << "... ";
            packe(fName, fName+".gz");
            std::cout << fName << ".gz"<< "\n";
        }
    } catch(std::runtime_error &exc) {
        std::cerr << "Fehler: " << exc.what() << "\n";
    }
}

Godbolt Listing lst-0581-godb.cpp, https://godbolt.org/z/4sod8vrr6:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4sod8vrr6 
} // namespace
int main(int argc, const char* argv[]) {
    try {
        const std::vector<string> fNamen {argv+1, argv+argc};
        for(auto fName : fNamen) {
            std::cout << "packe " << fName << "... ";
            packe(fName, fName+".gz");
            std::cout << fName << ".gz"<< "\n";
        }
    } catch(std::runtime_error &exc) {
        std::cerr << "Fehler: " << exc.what() << "\n";
    }
}

Listing 23.1: Der Aufruf eines Funktionstemplates klappt, solange der Funktionskörper mit den Templateparametern gültig ist.

Book listing lst-0591-book.cpp:

// https://godbolt.org/z/aMPj3K7EE 
#include <iostream>
struct Zahl {
    int wert_;
};
template<typename TYP>
void print(TYP value) {
    std::cout << value << "\n";
}
int main() {
    print(5);
    print(-10.25);
    print("Flamingo");
    Zahl sieben { 7 };
    print(sieben); //                                  (ERR)  cout << sieben gibt es nicht
}

Godbolt Listing lst-0591-godb.cpp, https://godbolt.org/z/aMPj3K7EE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/aMPj3K7EE 
#include <iostream>
struct Zahl {
    int wert_;
};
template<typename TYP>
void print(TYP value) {
    std::cout << value << "\n";
}
int main() {
    print(5);
    print(-10.25);
    print("Flamingo");
    Zahl sieben { 7 };
    print(sieben); //                                  (ERR)  cout << sieben gibt es nicht
}

Listing 23.2: Mit und ohne explizite Typangabe beim Aufruf

Book listing lst-0594-book.cpp:

// https://godbolt.org/z/816Ys17aT 
#include <iostream>
using std::cout;
template<typename TYP>
  void func(TYP a) { cout << a <<" TYP\n"; }
void func(int a) { cout << a << " int\n"; }
int main() {
    func<int>(8); // Ausgabe: 8 TYP
    func(8);      // Ausgabe: 8 int
}

Godbolt Listing lst-0594-godb.cpp, https://godbolt.org/z/816Ys17aT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/816Ys17aT 
#include <iostream>
using std::cout;
template<typename TYP>
  void func(TYP a) { cout << a <<" TYP\n"; }
void func(int a) { cout << a << " int\n"; }
int main() {
    func<int>(8); // Ausgabe: 8 TYP
    func(8);      // Ausgabe: 8 int
}

Listing 23.3: Ein Templateparameter kann auch eine konstante Zahl sein.

Book listing lst-0596-book.cpp:

// https://godbolt.org/z/c9xzM7EhP 
#include <array>
#include <iostream> // cout
using std::array; using std::cout;
template<size_t SIZE>
array<int,SIZE> createArray() {
    array<int,SIZE> result{};
    return result;
}
int main() {
    auto data = createArray<5>();
    data[3] = 33;
    for(auto e : data) cout << e << " ";
    cout << "\n";
}

Godbolt Listing lst-0596-godb.cpp, https://godbolt.org/z/c9xzM7EhP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/c9xzM7EhP 
#include <array>
#include <iostream> // cout
using std::array; using std::cout;
template<size_t SIZE>
array<int,SIZE> createArray() {
    array<int,SIZE> result{};
    return result;
}
int main() {
    auto data = createArray<5>();
    data[3] = 33;
    for(auto e : data) cout << e << " ";
    cout << "\n";
}

Listing 23.4: Mit auto als Templateparameter können Sie jeden einfachen Wert angeben.

Book listing lst-0598-book.cpp:

template <auto value> void f() { }
f<10>();               // value bekommt Typ int
f<'a'>();              // value bekommt Typ char

Listing 23.5: Mit »auto« und … können Sie beliebige Werte als Templateparameter angeben.

Book listing lst-0599-book.cpp:

template<auto ... vs> struct GemischteListe {};
using Drei = GemischteListe<'a', 100, 'b'>;
Drei drei{};

Listing 23.6: Für »TYP« wird vom Compiler »const&« ermittelt.

Book listing lst-0601-book.cpp:

// https://godbolt.org/z/cYsTo371z 
#include <iostream>
const int& a_oder_b(int auswahl) {
    static const int a = 42;
    static const int b = 73;
    if(auswahl==1)
        return a; // const& auf innere Variable a zurückgeben
    else
        return b; // const& auf innere Variable b zurückgeben
}
template<typename TYP>
TYP add(TYP a, TYP b) {
    return a + b;
}
int main() {
    auto res = add(
        a_oder_b(0),   // const int&
        a_oder_b(1) ); // const int&
    std::cout << res << "\n"; // Ausgabe: 115
}

Godbolt Listing lst-0601-godb.cpp, https://godbolt.org/z/cYsTo371z:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cYsTo371z 
#include <iostream>
const int& a_oder_b(int auswahl) {
    static const int a = 42;
    static const int b = 73;
    if(auswahl==1)
        return a; // const& auf innere Variable a zurückgeben
    else
        return b; // const& auf innere Variable b zurückgeben
}
template<typename TYP>
TYP add(TYP a, TYP b) {
    return a + b;
}
int main() {
    auto res = add(
        a_oder_b(0),   // const int&
        a_oder_b(1) ); // const int&
    std::cout << res << "\n"; // Ausgabe: 115
}

Listing 23.7: Auch eine Methode kann ein Template sein.

Book listing lst-0603-book.cpp:

// https://godbolt.org/z/bfofn76Ke 
#include <iostream>
class Printer {
    std::ostream& trg_;
public:
    explicit Printer(std::ostream& target)
        : trg_(target)
        {}
    template<typename TYP>
    Printer& print(const TYP& arg) {
        trg_ << arg;
        return *this;
    }
};
int main() {
    Printer normal(std::cout);
    normal.print(7).print(" ").print(3.1415).print("\n");
    Printer fehler(std::cerr);
    fehler.print(8).print(" ").print(2.7183).print("\n");
}

Godbolt Listing lst-0603-godb.cpp, https://godbolt.org/z/bfofn76Ke:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bfofn76Ke 
#include <iostream>
class Printer {
    std::ostream& trg_;
public:
    explicit Printer(std::ostream& target)
        : trg_(target)
        {}
    template<typename TYP>
    Printer& print(const TYP& arg) {
        trg_ << arg;
        return *this;
    }
};
int main() {
    Printer normal(std::cout);
    normal.print(7).print(" ").print(3.1415).print("\n");
    Printer fehler(std::cerr);
    fehler.print(8).print(" ").print(2.7183).print("\n");
}

Listing 23.8: Auch in der Standardbibliothek finden Sie allerlei Funktionstemplates.

Book listing lst-0604-book.cpp:

// https://godbolt.org/z/oTn1K4sGG 
#include <vector>
#include <iostream>  // cout, ostream
#include <algorithm> // sort, copy
#include <iterator>  // ostream_iterator
int main() {
    std::ostream_iterator<int> oit(std::cout," ");
    std::vector data { 100, 50, 1, 75, 25, 0 };       // vector<int>
    std::sort(std::begin(data), std::end(data));      // Iteratorenpaar
    std::copy(std::begin(data), std::end(data), oit); // Iteratorenpaar
    std::cout << '\n';                                // Ausgabe: 0 1 25 50 75 100
    std::ranges::reverse(data);                       // Range
    std::ranges::copy(data, oit);                     // Range
    std::cout << '\n';                                // Ausgabe: 100 75 50 25 1 0
}

Godbolt Listing lst-0604-godb.cpp, https://godbolt.org/z/oTn1K4sGG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oTn1K4sGG 
#include <vector>
#include <iostream>  // cout, ostream
#include <algorithm> // sort, copy
#include <iterator>  // ostream_iterator
int main() {
    std::ostream_iterator<int> oit(std::cout," ");
    std::vector data { 100, 50, 1, 75, 25, 0 };       // vector<int>
    std::sort(std::begin(data), std::end(data));      // Iteratorenpaar
    std::copy(std::begin(data), std::end(data), oit); // Iteratorenpaar
    std::cout << '\n';                                // Ausgabe: 0 1 25 50 75 100
    std::ranges::reverse(data);                       // Range
    std::ranges::copy(data, oit);                     // Range
    std::cout << '\n';                                // Ausgabe: 100 75 50 25 1 0
}

Listing 23.9: Eigenen Algorithmen übergeben Sie Ranges als Argumente, nicht den Container.

Book listing lst-0605-book.cpp:

// https://godbolt.org/z/h3baE65od 
#include <iostream>
#include <vector>
#include <set>
#include <bitset>
#include <ranges>
namespace rng = std::ranges;
std::ostream& druckeBinaer(std::ostream& os, rng::input_range auto&& range) {
    for(auto&& elem : range) {
        std::bitset<4> x(elem); // Zahl in bitset kopieren
        os << x << " ";
    }
    return os;
}
int main()
{
    std::vector vdata { 2, 0, 15, 12 };
    druckeBinaer(std::cout, vdata) << "\n";
    // Ausgabe: 0010 0000 1111 1100
    std::set sdata { 2, 0, 12, 15 };
    druckeBinaer(std::cout, sdata) << "\n";
    // Ausgabe: 0000 0010 1100 1111
    int adata[] = { 0,1,2,13,14,15 };
    druckeBinaer(std::cout, adata) << "\n";
    // Ausgabe: 0000 0001 0010 1101 1110 1111
}

Godbolt Listing lst-0605-godb.cpp, https://godbolt.org/z/h3baE65od:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h3baE65od 
#include <iostream>
#include <vector>
#include <set>
#include <bitset>
#include <ranges>
namespace rng = std::ranges;
std::ostream& druckeBinaer(std::ostream& os, rng::input_range auto&& range) {
    for(auto&& elem : range) {
        std::bitset<4> x(elem); // Zahl in bitset kopieren
        os << x << " ";
    }
    return os;
}
int main()
{
    std::vector vdata { 2, 0, 15, 12 };
    druckeBinaer(std::cout, vdata) << "\n";
    // Ausgabe: 0010 0000 1111 1100
    std::set sdata { 2, 0, 12, 15 };
    druckeBinaer(std::cout, sdata) << "\n";
    // Ausgabe: 0000 0010 1100 1111
    int adata[] = { 0,1,2,13,14,15 };
    druckeBinaer(std::cout, adata) << "\n";
    // Ausgabe: 0000 0001 0010 1101 1110 1111
}

Listing 23.10: Eigenen Algorithmen übergeben Sie Iteratoren als Argumente, nicht den Container.

Book listing lst-0606-book.cpp:

// https://godbolt.org/z/13eMxKTfj 
#include <iostream>
#include <vector>
#include <set>
#include <bitset>
template<typename IT>
std::ostream& druckeBinaer(std::ostream& os, IT begin, IT end)
{
    for(IT it=begin; it != end; ++it) {
        std::bitset<4> x(*it); // Zahl in bitset kopieren
        os << x << " ";
    }
    return os;
}
int main()
{
    std::vector<int> vdata { 2, 0, 15, 12 };
    druckeBinaer(std::cout, vdata.cbegin(), vdata.cend()) << "\n";
    // Ausgabe: 0010 0000 1111 1100
    std::set<int> sdata { 2, 0, 12, 15 };
    druckeBinaer(std::cout, std::begin(sdata), std::end(sdata)) << "\n";
    // Ausgabe: 0000 0010 1100 1111
    int adata[] = { 0,1,2,13,14,15 };
    druckeBinaer(std::cout, std::begin(adata), std::end(adata)) << "\n";
    // Ausgabe: 0000 0001 0010 1101 1110 1111
}

Godbolt Listing lst-0606-godb.cpp, https://godbolt.org/z/13eMxKTfj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/13eMxKTfj 
#include <iostream>
#include <vector>
#include <set>
#include <bitset>
template<typename IT>
std::ostream& druckeBinaer(std::ostream& os, IT begin, IT end)
{
    for(IT it=begin; it != end; ++it) {
        std::bitset<4> x(*it); // Zahl in bitset kopieren
        os << x << " ";
    }
    return os;
}
int main()
{
    std::vector<int> vdata { 2, 0, 15, 12 };
    druckeBinaer(std::cout, vdata.cbegin(), vdata.cend()) << "\n";
    // Ausgabe: 0010 0000 1111 1100
    std::set<int> sdata { 2, 0, 12, 15 };
    druckeBinaer(std::cout, std::begin(sdata), std::end(sdata)) << "\n";
    // Ausgabe: 0000 0010 1100 1111
    int adata[] = { 0,1,2,13,14,15 };
    druckeBinaer(std::cout, std::begin(adata), std::end(adata)) << "\n";
    // Ausgabe: 0000 0001 0010 1101 1110 1111
}

Listing 23.11: So finden Sie den Zahlenbereich der Ganzzahltypen heraus.

Book listing lst-0608-book.cpp:

// https://godbolt.org/z/oY9v9a8d6 
#include <iostream>                                  // cout
#include <limits>                                    // numeric_limits
template<typename INT_TYP>                           // Template mit Typargument
void infos(const char* name) {
    using L = typename std::numeric_limits<INT_TYP>; // kürzer umbenennen
    std::cout
        << name
        << " zahlenbits:" << L::digits               // Bits ohne Vorzeichenbit
        << " vorzeichen:" << L::is_signed            // speichert Vorzeichen?
        << " min:"<< (long long)L::min()             // kleinster möglicher Wert
        << " max:"<< (long long)L::max()             // größter möglicher Wert
        << "\n";
}
int main() {
    infos<signed char>("char");                      // kleinster int-Typ
    infos<short>("short");
    infos<int>("int");
    infos<long>("long");
    infos<long long>("long long");                   // größter int-Typ
}

Godbolt Listing lst-0608-godb.cpp, https://godbolt.org/z/oY9v9a8d6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oY9v9a8d6 
#include <iostream>                                  // cout
#include <limits>                                    // numeric_limits
template<typename INT_TYP>                           // Template mit Typargument
void infos(const char* name) {
    using L = typename std::numeric_limits<INT_TYP>; // kürzer umbenennen
    std::cout
        << name
        << " zahlenbits:" << L::digits               // Bits ohne Vorzeichenbit
        << " vorzeichen:" << L::is_signed            // speichert Vorzeichen?
        << " min:"<< (long long)L::min()             // kleinster möglicher Wert
        << " max:"<< (long long)L::max()             // größter möglicher Wert
        << "\n";
}
int main() {
    infos<signed char>("char");                      // kleinster int-Typ
    infos<short>("short");
    infos<int>("int");
    infos<long>("long");
    infos<long long>("long long");                   // größter int-Typ
}

Listing 23.12: Eine Funktion als Parameter

Book listing lst-0609-book.cpp:

#include <functional> // function
int berechne(int a, int b, std::function<int(int,int)> binop) {
    return binop(a,b);
}

Listing 23.13: Verwenden Sie den Namen einer passenden Funktion als Funktionsparameter.

Book listing lst-0612-book.cpp:

// https://godbolt.org/z/7YKjcTbhn 
#include <functional> // function
#include <iostream>   // cout
int berechne(int a, int b, std::function<int(int,int)> binop) {
    return binop(a,b);
}
int plus(int a, int b) { return a+b; }
int mal(int a, int b) { return a*b; }
int main() {
    std::cout << berechne(3, 4, plus) << "\n"; // Ausgabe: 7
    std::cout << berechne(3, 4, mal) << "\n";  // Ausgabe: 12
}

Godbolt Listing lst-0612-godb.cpp, https://godbolt.org/z/7YKjcTbhn:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7YKjcTbhn 
#include <functional> // function
#include <iostream>   // cout
int berechne(int a, int b, std::function<int(int,int)> binop) {
    return binop(a,b);
}
int plus(int a, int b) { return a+b; }
int mal(int a, int b) { return a*b; }
int main() {
    std::cout << berechne(3, 4, plus) << "\n"; // Ausgabe: 7
    std::cout << berechne(3, 4, mal) << "\n";  // Ausgabe: 12
}

Listing 23.14: Es ist egal, ob Sie beim Aufruf den Adressoperator verwenden oder nicht.

Book listing lst-0615-book.cpp:

// https://godbolt.org/z/WbnThTs8e 
#include <functional> // function
#include <iostream>   // cout
int berechne(int a, int b, std::function<int(int,int)> binop) {
    return binop(a,b);
}
int plus(int a, int b) { return a+b; }
int mal(int a, int b) { return a*b; }
int main() {
    std::cout << berechne(3, 4, plus) << "\n";  // Wert-Schreibweise
    std::cout << berechne(3, 4, mal) << "\n";   // Wert-Schreibweise
    std::cout << berechne(3, 4, &plus) << "\n"; // Zeiger-Schreibweise
    std::cout << berechne(3, 4, &mal) << "\n";  // Zeiger-Schreibweise
}

Godbolt Listing lst-0615-godb.cpp, https://godbolt.org/z/WbnThTs8e:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WbnThTs8e 
#include <functional> // function
#include <iostream>   // cout
int berechne(int a, int b, std::function<int(int,int)> binop) {
    return binop(a,b);
}
int plus(int a, int b) { return a+b; }
int mal(int a, int b) { return a*b; }
int main() {
    std::cout << berechne(3, 4, plus) << "\n";  // Wert-Schreibweise
    std::cout << berechne(3, 4, mal) << "\n";   // Wert-Schreibweise
    std::cout << berechne(3, 4, &plus) << "\n"; // Zeiger-Schreibweise
    std::cout << berechne(3, 4, &mal) << "\n";  // Zeiger-Schreibweise
}

Listing 23.15: Eine Klasse mit »operator()« erzeugt Funktionsobjekte.

Book listing lst-0616-book.cpp:

// https://godbolt.org/z/Px83WPKfq 
#include <iostream>                      // cout
using std::cout;
class Inkrement {
   int menge_;
public:
    explicit Inkrement(int menge) : menge_{menge} {}
    int operator()(int wert) const  {    // macht Instanzen aufrufbar
        return wert + menge_;
    }
    void clear() {
        menge_ = 0;
    }
};
int main() {
    Inkrement plusVier{4};               // Instanz erzeugen
    Inkrement plusElf{11};               // noch eine Instanz
    cout << plusVier(8) << "\n";         // Ausgabe: 12
    int erg = 2 * plusElf(5) - 7;        // erg ist 25
    cout << plusElf(erg/5) << "\n";      // Ausgabe: 16
    cout << 3 * Inkrement{1}(7) << "\n"; // Ausgabe: 24
    Inkrement plusNix = plusElf;
    plusNix.clear();                     // Zustand ändern
    cout << plusNix(1) << "\n";          // Ausgabe: 1
}

Godbolt Listing lst-0616-godb.cpp, https://godbolt.org/z/Px83WPKfq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Px83WPKfq 
#include <iostream>                      // cout
using std::cout;
class Inkrement {
   int menge_;
public:
    explicit Inkrement(int menge) : menge_{menge} {}
    int operator()(int wert) const  {    // macht Instanzen aufrufbar
        return wert + menge_;
    }
    void clear() {
        menge_ = 0;
    }
};
int main() {
    Inkrement plusVier{4};               // Instanz erzeugen
    Inkrement plusElf{11};               // noch eine Instanz
    cout << plusVier(8) << "\n";         // Ausgabe: 12
    int erg = 2 * plusElf(5) - 7;        // erg ist 25
    cout << plusElf(erg/5) << "\n";      // Ausgabe: 16
    cout << 3 * Inkrement{1}(7) << "\n"; // Ausgabe: 24
    Inkrement plusNix = plusElf;
    plusNix.clear();                     // Zustand ändern
    cout << plusNix(1) << "\n";          // Ausgabe: 1
}

Listing 23.16: Eine Klasse mit einer normalen Methode

Book listing lst-0619-book.cpp:

// https://godbolt.org/z/EExfde3vP 
#include <iostream>              // cout
using std::cout;

class Hinzu {
   int menge_;
public:
    explicit Hinzu(int menge) : menge_{menge} {}
    int hinzu(int wert) const  {            // statt operator()
        return wert + menge_;
    }
    void clear() {
        menge_ = 0;
    }
};
int main() {
    Hinzu plusVier{4};                      // Instanz erzeugen
    Hinzu plusElf{11};                      // noch eine Instanz
    cout << plusVier.hinzu(8) << "\n";      // Ausgabe: 12
    int erg = 2 * plusElf.hinzu(5) - 7;     // erg ist 25
    cout << plusElf.hinzu(erg/5) << "\n";   // Ausgabe: 16
    cout << 3 * Hinzu{1}.hinzu(7) << "\n";  // Ausgabe: 24
    Hinzu plusNix = plusElf;
    plusNix.clear();                        // Zustand ändern
    cout << plusNix.hinzu(1) << "\n";       // Ausgabe: 1
}

Godbolt Listing lst-0619-godb.cpp, https://godbolt.org/z/EExfde3vP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EExfde3vP 
#include <iostream>              // cout
using std::cout;

class Hinzu {
   int menge_;
public:
    explicit Hinzu(int menge) : menge_{menge} {}
    int hinzu(int wert) const  {            // statt operator()
        return wert + menge_;
    }
    void clear() {
        menge_ = 0;
    }
};
int main() {
    Hinzu plusVier{4};                      // Instanz erzeugen
    Hinzu plusElf{11};                      // noch eine Instanz
    cout << plusVier.hinzu(8) << "\n";      // Ausgabe: 12
    int erg = 2 * plusElf.hinzu(5) - 7;     // erg ist 25
    cout << plusElf.hinzu(erg/5) << "\n";   // Ausgabe: 16
    cout << 3 * Hinzu{1}.hinzu(7) << "\n";  // Ausgabe: 24
    Hinzu plusNix = plusElf;
    plusNix.clear();                        // Zustand ändern
    cout << plusNix.hinzu(1) << "\n";       // Ausgabe: 1
}

Listing 23.17: Mit »operator<« als Funktion können Sie nur eine Sortierung implementieren.

Book listing lst-0620-book.cpp:

// https://godbolt.org/z/3ch51ov87 
#include <set>
#include <string>
#include <iostream> // cout
using std::string; using std::set; using std::cout;
struct Zwerg {
    string name_;
    unsigned jahr_;
};
bool operator<(const Zwerg& a, const Zwerg& b) {
    return a.name_ < b.name_;
}
int main() {
    set zwerge{ Zwerg{"Balin", 2763}, Zwerg{"Dwalin", 2772},
        Zwerg{"Oin", 2774}, Zwerg{"Gloin", 2783}, Zwerg{"Thorin", 2746},
        Zwerg{"Fili", 2859}, Zwerg{"Kili", 2864} };
    for(const auto& z : zwerge) // sortierte Ausgabe: "Balin" bis "Thorin"
        cout << z.name_  << " ";
    cout << "\n";
}

Godbolt Listing lst-0620-godb.cpp, https://godbolt.org/z/3ch51ov87:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3ch51ov87 
#include <set>
#include <string>
#include <iostream> // cout
using std::string; using std::set; using std::cout;
struct Zwerg {
    string name_;
    unsigned jahr_;
};
bool operator<(const Zwerg& a, const Zwerg& b) {
    return a.name_ < b.name_;
}
int main() {
    set zwerge{ Zwerg{"Balin", 2763}, Zwerg{"Dwalin", 2772},
        Zwerg{"Oin", 2774}, Zwerg{"Gloin", 2783}, Zwerg{"Thorin", 2746},
        Zwerg{"Fili", 2859}, Zwerg{"Kili", 2864} };
    for(const auto& z : zwerge) // sortierte Ausgabe: "Balin" bis "Thorin"
        cout << z.name_  << " ";
    cout << "\n";
}

Listing 23.18: Ein Funktor ohne Schnickschnack, aber mit großem Nutzen

Book listing lst-0622-book.cpp:

struct NachJahr { // implementiert less-than nach Zwerg::jahr_
    bool operator()(const Zwerg& a, const Zwerg& b) const {
        return a.jahr_ < b.jahr_;
    }
};

GodboltId:53EcTMo3e

Book listing lst-0623-book.cpp:

// https://godbolt.org/z/53EcTMo3e 
set<Zwerg,NachJahr> zwerge2{begin(zwerge), end(zwerge)};
for(const auto& z : zwerge2) // anders sortierte Ausgabe
    cout << z.jahr_ << " ";

Godbolt Listing lst-0623-godb.cpp, https://godbolt.org/z/53EcTMo3e:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/53EcTMo3e 
set<Zwerg,NachJahr> zwerge2{begin(zwerge), end(zwerge)};
for(const auto& z : zwerge2) // anders sortierte Ausgabe
    cout << z.jahr_ << " ";

Listing 23.19: Viele Algorithmen der Standardbibliothek arbeiten ebenfalls mit »operator<«.

Book listing lst-0627-book.cpp:

// https://godbolt.org/z/MrcGhxTdT 
#include <vector>
#include <algorithm>  // sort
// Definitionen und weitere Includes wie zuvor
int main() {
    vector zwerge{    // initialisieren wie zuvor
    /* sortieren */
    std::sort(begin(zwerge), end(zwerge));
    // ausgeben wie zuvor …

Godbolt Listing lst-0627-godb.cpp, https://godbolt.org/z/MrcGhxTdT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MrcGhxTdT 
#include <vector>
#include <algorithm>  // sort
// Definitionen und weitere Includes wie zuvor
int main() {
    vector zwerge{    // initialisieren wie zuvor
    /* sortieren */
    std::sort(begin(zwerge), end(zwerge));
    // ausgeben wie zuvor …

Listing 23.20: Mit der Zugriffsklausel können Sie im Lambda auf äußere Variablen zugreifen.

Book listing lst-0634-book.cpp:

// https://godbolt.org/z/ers9eWPbG 
#include <vector>
#include <string>
#include <algorithm> // sort
#include <iostream>  // cout
using std::string; using std::vector; using std::cout;
// wie zuvor
int main() {
    vector zwerge{    // wie zuvor
    /* sortieren */
    bool rueckwaerts = true; // oder false. Variable außerhalb des Lambdas
    std::ranges::sort(zwerge,
        [rueckwaerts](const Zwerg& a, const Zwerg& b) {
            if(rueckwaerts)
                return a.name_ > b.name_;
            else
                return a.name_ < b.name_;
        }
    );
    /* ausgeben */
    for(const auto& z : zwerge) // rückwärts: "Thorin" bis "Balin"
        cout << z.name_  << " ";
    cout << "\n";
}

Godbolt Listing lst-0634-godb.cpp, https://godbolt.org/z/ers9eWPbG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ers9eWPbG 
#include <vector>
#include <string>
#include <algorithm> // sort
#include <iostream>  // cout
using std::string; using std::vector; using std::cout;
// wie zuvor
int main() {
    vector zwerge{    // wie zuvor
    /* sortieren */
    bool rueckwaerts = true; // oder false. Variable außerhalb des Lambdas
    std::ranges::sort(zwerge,
        [rueckwaerts](const Zwerg& a, const Zwerg& b) {
            if(rueckwaerts)
                return a.name_ > b.name_;
            else
                return a.name_ < b.name_;
        }
    );
    /* ausgeben */
    for(const auto& z : zwerge) // rückwärts: "Thorin" bis "Balin"
        cout << z.name_  << " ";
    cout << "\n";
}

Listing 23.21: Die Zugriffsklausel kann auch Referenzen enthalten.

Book listing lst-0635-book.cpp:

// https://godbolt.org/z/4zYsWW9Wq 
#include <vector>
#include <string>
#include <algorithm> // sort
#include <iostream>  // cout
using std::string; using std::vector; using std::cout;
// wie zuvor
int main() {
    vector zwerge{           // wie zuvor
    /* sortieren */
    bool rueckwaerts = true; // oder false. Variable außerhalb des Lambdas
    unsigned richtigrum = 0; // zählt < mit
    unsigned falschrum = 0;  // zählt > mit
    std::ranges::sort(zwerge,
        [rueckwaerts,&falschrum,&richtigrum](const Zwerg& a, const Zwerg& b) {
            bool result = rueckwaerts
                ? a.name_ > b.name_
                : a.name_ < b.name_;
            if(result==false) ++falschrum; else ++richtigrum;
            return result;
        }
    );
    /* ausgeben */
    cout << "Falschrum:" << falschrum << " Richtigrum: " << richtigrum << "\n";
    for(const auto& z : zwerge) // rückwärts: "Thorin" bis "Balin"
        cout << z.name_  << " ";
    cout << "\n";
}

Godbolt Listing lst-0635-godb.cpp, https://godbolt.org/z/4zYsWW9Wq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4zYsWW9Wq 
#include <vector>
#include <string>
#include <algorithm> // sort
#include <iostream>  // cout
using std::string; using std::vector; using std::cout;
// wie zuvor
int main() {
    vector zwerge{           // wie zuvor
    /* sortieren */
    bool rueckwaerts = true; // oder false. Variable außerhalb des Lambdas
    unsigned richtigrum = 0; // zählt < mit
    unsigned falschrum = 0;  // zählt > mit
    std::ranges::sort(zwerge,
        [rueckwaerts,&falschrum,&richtigrum](const Zwerg& a, const Zwerg& b) {
            bool result = rueckwaerts
                ? a.name_ > b.name_
                : a.name_ < b.name_;
            if(result==false) ++falschrum; else ++richtigrum;
            return result;
        }
    );
    /* ausgeben */
    cout << "Falschrum:" << falschrum << " Richtigrum: " << richtigrum << "\n";
    for(const auto& z : zwerge) // rückwärts: "Thorin" bis "Balin"
        cout << z.name_  << " ";
    cout << "\n";
}

Listing 23.22: »mutable« macht Wert-Captures in Lambdas veränderbar.

Book listing lst-0637-book.cpp:

// https://godbolt.org/z/zMWo69974 
#include <iostream>
int main() {
    int count = 0;
    auto plus1 = [count](int x) mutable { // count als Kopie
        std::cout << ++count; return x+1;
    };
    for(int i=0; i<5; ++i) {
        plus1(i);
    }
    std::cout << "\n";
    // Ausgabe: 12345
}

Godbolt Listing lst-0637-godb.cpp, https://godbolt.org/z/zMWo69974:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zMWo69974 
#include <iostream>
int main() {
    int count = 0;
    auto plus1 = [count](int x) mutable { // count als Kopie
        std::cout << ++count; return x+1;
    };
    for(int i=0; i<5; ++i) {
        plus1(i);
    }
    std::cout << "\n";
    // Ausgabe: 12345
}

Listing 23.23: Wenn möglich, besser ohne mutable

Book listing lst-0638-book.cpp:

// https://godbolt.org/z/8GxPMEc5o 
#include <iostream>
int main() {
    int count = 0;
    auto plus1 = [&count](int x) { // count als Referenz
        ++count; return x+1;
    };
    for(int i=0; i<5; ++i) { plus1(i); }
    std::cout << "plus1 wurde " << count << " Mal aufgerufen\n";
    // Ausgabe: plus1 wurde 5 Mal aufgerufen
}

Godbolt Listing lst-0638-godb.cpp, https://godbolt.org/z/8GxPMEc5o:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8GxPMEc5o 
#include <iostream>
int main() {
    int count = 0;
    auto plus1 = [&count](int x) { // count als Referenz
        ++count; return x+1;
    };
    for(int i=0; i<5; ++i) { plus1(i); }
    std::cout << "plus1 wurde " << count << " Mal aufgerufen\n";
    // Ausgabe: plus1 wurde 5 Mal aufgerufen
}

GodboltId:YWe15Ehd8

Book listing lst-0641-book.cpp:

// https://godbolt.org/z/YWe15Ehd8 
#include <iostream>
#include <string>
using std::cout; using std::string; using namespace std::literals;
auto min2 = [](const auto &a, const auto &b) {
    return a<b ? a : b;
};
auto min3 = [](const auto &a, const auto &b, const auto &c) {
    return min2(a, min2(b,c));
};
int main() {
    cout << min3( 3, 7, 2 ) << '\n';                  // Ausgabe: 2
    cout << min3( 8.11, 113.2, -3.1 ) << '\n';        // Ausgabe: –3.1
    cout << min3( "Zoo"s, "Affe"s, "Muli"s ) << '\n'; // Ausgabe: Affe
}

Godbolt Listing lst-0641-godb.cpp, https://godbolt.org/z/YWe15Ehd8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YWe15Ehd8 
#include <iostream>
#include <string>
using std::cout; using std::string; using namespace std::literals;
auto min2 = [](const auto &a, const auto &b) {
    return a<b ? a : b;
};
auto min3 = [](const auto &a, const auto &b, const auto &c) {
    return min2(a, min2(b,c));
};
int main() {
    cout << min3( 3, 7, 2 ) << '\n';                  // Ausgabe: 2
    cout << min3( 8.11, 113.2, -3.1 ) << '\n';        // Ausgabe: –3.1
    cout << min3( "Zoo"s, "Affe"s, "Muli"s ) << '\n'; // Ausgabe: Affe
}

GodboltId:nenW8aM81

Book listing lst-0642-book.cpp:

// https://godbolt.org/z/nenW8aM81 
auto min2 = []<typename T>(const T &a, const T &b) {
    return a<b ? a : b;
};
auto min3 = []<typename T>(const T &a, const T &b, const T &c) {
    return min2(a, min2(b,c));
};

Godbolt Listing lst-0642-godb.cpp, https://godbolt.org/z/nenW8aM81:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nenW8aM81 
auto min2 = []<typename T>(const T &a, const T &b) {
    return a<b ? a : b;
};
auto min3 = []<typename T>(const T &a, const T &b, const T &c) {
    return min2(a, min2(b,c));
};

Listing 23.24: Concepts können auf unterschiedliche Weise geschrieben werden.

Book listing lst-0643-book.cpp:

// https://godbolt.org/z/W6cdra8K9 
#include <concepts>  // integral
#include <iostream>
using namespace std;
// Concept explizit mit requires
template<typename T> requires integral<T>
auto add_1(T val) { return val+1; }
// abgekürztes Concept
template<integral T>
auto add_2(T val) { return val+2; }
// abgekürztes Funktionstemplate mit Concept
auto add_3(integral auto val) { return val+3; }
// Ad-hoc-requires für Funktionstemplate
auto add_4(auto val) requires integral<decltype(val)>
{ return val+4; }
int main() {
  cout << add_1(1) << '\n';              // Ausgabe: 2
  cout << add_2(1) << '\n';              // Ausgabe: 3
  cout << add_3(1) << '\n';              // Ausgabe: 4
  cout << add_4(1) << '\n';              // Ausgabe: 5
  cout << add_3("text") << '\n';         //                                  (ERR)  Fehler
  integral auto val = add_1(99);         // auch für auto-Variablen
  cout << val << '\n';                   // Ausgabe: 100
}

Godbolt Listing lst-0643-godb.cpp, https://godbolt.org/z/W6cdra8K9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/W6cdra8K9 
#include <concepts>  // integral
#include <iostream>
using namespace std;
// Concept explizit mit requires
template<typename T> requires integral<T>
auto add_1(T val) { return val+1; }
// abgekürztes Concept
template<integral T>
auto add_2(T val) { return val+2; }
// abgekürztes Funktionstemplate mit Concept
auto add_3(integral auto val) { return val+3; }
// Ad-hoc-requires für Funktionstemplate
auto add_4(auto val) requires integral<decltype(val)>
{ return val+4; }
int main() {
  cout << add_1(1) << '\n';              // Ausgabe: 2
  cout << add_2(1) << '\n';              // Ausgabe: 3
  cout << add_3(1) << '\n';              // Ausgabe: 4
  cout << add_4(1) << '\n';              // Ausgabe: 5
  cout << add_3("text") << '\n';         //                                  (ERR)  Fehler
  integral auto val = add_1(99);         // auch für auto-Variablen
  cout << val << '\n';                   // Ausgabe: 100
}

Listing 23.25: Mit Concepts können Sie einzelne Überladungen einschränken.

Book listing lst-0644-book.cpp:

// https://godbolt.org/z/Kxrz5ETh6 
#include <concepts>  // integral, floating_point
#include <iostream>
using namespace std;
int64_t trunc_to_10(integral auto val) { return (val/10)*10; }
int64_t trunc_to_10(floating_point auto val) { return int64_t(val/10)*10; }
int main() {
  cout << trunc_to_10(144) << '\n';    // Ausgabe: 140
  cout << trunc_to_10(122.2) << '\n';  // Ausgabe: 120
}

Godbolt Listing lst-0644-godb.cpp, https://godbolt.org/z/Kxrz5ETh6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Kxrz5ETh6 
#include <concepts>  // integral, floating_point
#include <iostream>
using namespace std;
int64_t trunc_to_10(integral auto val) { return (val/10)*10; }
int64_t trunc_to_10(floating_point auto val) { return int64_t(val/10)*10; }
int main() {
  cout << trunc_to_10(144) << '\n';    // Ausgabe: 140
  cout << trunc_to_10(122.2) << '\n';  // Ausgabe: 120
}

GodboltId:eaGre4bqr

Book listing lst-0646-book.cpp:

// https://godbolt.org/z/eaGre4bqr 
auto min2(const std::integral auto &a, const std::integral auto &b) {
    return a<b ? a : b;
};

auto min3 = []<std::integral T>(const T &a, const T &b, const T &c) {
    return min2(a, min2(b,c));
};

int main() {
    cout << min3( 3, 7, 2 ) << '\n';
    cout << min3( 8.11, 113.2, -3.1 ) << '\n'; //                                  (ERR)  Fehler: kein integraler Typ

Godbolt Listing lst-0646-godb.cpp, https://godbolt.org/z/eaGre4bqr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eaGre4bqr 
auto min2(const std::integral auto &a, const std::integral auto &b) {
    return a<b ? a : b;
};

auto min3 = []<std::integral T>(const T &a, const T &b, const T &c) {
    return min2(a, min2(b,c));
};

int main() {
    cout << min3( 3, 7, 2 ) << '\n';
    cout << min3( 8.11, 113.2, -3.1 ) << '\n'; //                                  (ERR)  Fehler: kein integraler Typ

Listing 23.26: Geben Sie weitere Bedingungen mit requires an.

Book listing lst-0647-book.cpp:

// https://godbolt.org/z/orTK9daa3 
#include <concepts>
#include <iostream>
#include <string>
using namespace std; using namespace std::literals;

string mk_string(integral auto val) { return to_string(val); }
string mk_string(string val) { return '['+val+']'; }
template<typename T>
  requires copyable<T> &&                            // Typanforderung
  requires (T t) { mk_string(t) + mk_string(t); } && // einfache Anforderung
  requires (T t) {                     // zusammengesetzte Anforderung
    {mk_string(t)} -> same_as<string>; // gültiger Ausdruck muss Bedingung erfüllen
  }
string dbl_quote(const T& val) {
  T val2{val};                      // Kopie erzeugen (nur zu Demozwecken)
  return '"' + mk_string(val) + mk_string(val2) + '"';
}
int main() {
  cout << dbl_quote(10) << '\n';    // Ausgabe: "1010"
  cout << dbl_quote("ab"s) << '\n'; // Ausgabe: "[ab][ab]"
  cout << dbl_quote(3.14) << '\n';  //                                  (ERR)  Fehler: keine passende mk_string-Überladung
}

Godbolt Listing lst-0647-godb.cpp, https://godbolt.org/z/orTK9daa3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/orTK9daa3 
#include <concepts>
#include <iostream>
#include <string>
using namespace std; using namespace std::literals;

string mk_string(integral auto val) { return to_string(val); }
string mk_string(string val) { return '['+val+']'; }
template<typename T>
  requires copyable<T> &&                            // Typanforderung
  requires (T t) { mk_string(t) + mk_string(t); } && // einfache Anforderung
  requires (T t) {                     // zusammengesetzte Anforderung
    {mk_string(t)} -> same_as<string>; // gültiger Ausdruck muss Bedingung erfüllen
  }
string dbl_quote(const T& val) {
  T val2{val};                      // Kopie erzeugen (nur zu Demozwecken)
  return '"' + mk_string(val) + mk_string(val2) + '"';
}
int main() {
  cout << dbl_quote(10) << '\n';    // Ausgabe: "1010"
  cout << dbl_quote("ab"s) << '\n'; // Ausgabe: "[ab][ab]"
  cout << dbl_quote(3.14) << '\n';  //                                  (ERR)  Fehler: keine passende mk_string-Überladung
}

Listing 23.27: Definieren Sie wiederkehrende Anforderungen mit concept.

Book listing lst-0648-book.cpp:

// https://godbolt.org/z/Tcxnr6jTM 
template<typename T>
  concept dbl_quotable = copyable<T> &&
  requires (T t) { mk_string(t) + mk_string(t); } &&
  requires(T t) {
    {mk_string(t)} -> same_as<string>;
  };
string dbl_quote(const dbl_quotable auto& val) {
  auto val2{val}; // Kopie erzeugen (nur zu Demozwecken)
  return '"' + mk_string(val) + mk_string(val2) + '"';
}

Godbolt Listing lst-0648-godb.cpp, https://godbolt.org/z/Tcxnr6jTM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Tcxnr6jTM 
template<typename T>
  concept dbl_quotable = copyable<T> &&
  requires (T t) { mk_string(t) + mk_string(t); } &&
  requires(T t) {
    {mk_string(t)} -> same_as<string>;
  };
string dbl_quote(const dbl_quotable auto& val) {
  auto val2{val}; // Kopie erzeugen (nur zu Demozwecken)
  return '"' + mk_string(val) + mk_string(val2) + '"';
}

GodboltId:9qsGW6M8Y

Book listing lst-0649-book.cpp:

// https://godbolt.org/z/9qsGW6M8Y 
template<std::ranges::range T>         // eine Range über Typ T
using ValueTypeOfRange = std::ranges::range_value_t<T>;
// oder
template<typename T>
requires std::ranges::range<T>         // eine Range über Typ T
using ValueTypeOfRange = std::ranges::range_value_t<T>;
// ergibt:
ValueTypeOfRange<std::vector<int>> x;  // x ist int
ValueTypeOfRange<std::string> y;       // y ist char
ValueTypeOfRange<std::list<double>> z; // z ist double
ValueTypeOfRange<int> w;               //                                  (ERR)  int ist keine Range

Godbolt Listing lst-0649-godb.cpp, https://godbolt.org/z/9qsGW6M8Y:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9qsGW6M8Y 
template<std::ranges::range T>         // eine Range über Typ T
using ValueTypeOfRange = std::ranges::range_value_t<T>;
// oder
template<typename T>
requires std::ranges::range<T>         // eine Range über Typ T
using ValueTypeOfRange = std::ranges::range_value_t<T>;
// ergibt:
ValueTypeOfRange<std::vector<int>> x;  // x ist int
ValueTypeOfRange<std::string> y;       // y ist char
ValueTypeOfRange<std::list<double>> z; // z ist double
ValueTypeOfRange<int> w;               //                                  (ERR)  int ist keine Range

Listing 23.28: So verwenden Sie Concepts in einem constexpr if.

Book listing lst-0650-book.cpp:

if constexpr std::integral<T> {
  // T ist ein integraler Typ
} else if constexpr std::floating_point<T> {
  // T ist ein Gleitkommatyp
} else {
  // T ist weder noch
}

Listing 23.29: Ein Klassentemplate erhält einen Typ als formalen Parameter.

Book listing lst-0654-book.cpp:

// https://godbolt.org/z/jqzTMxYKv 
template <std::copyable T>      // C++20-Concept
class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; }
    T getData() const { return data_; }
};

Godbolt Listing lst-0654-godb.cpp, https://godbolt.org/z/jqzTMxYKv:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jqzTMxYKv 
template <std::copyable T>      // C++20-Concept
class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; }
    T getData() const { return data_; }
};

Listing 23.30: Methodendefinitionen außerhalb des Körpers eines Klassentemplates sind syntaktisch etwas aufwendiger.

Book listing lst-0656-book.cpp:

// https://godbolt.org/z/4fK5WdoG8 
template <std::copyable T>
class MyContainer {
    T data_;
public:
    void setData(const T& d);
    T getData() const;
};
template <std::copyable T>
void MyContainer<T>::setData(const T& d) {
    data_ = d;
}
template <std::copyable T>
T MyContainer<T>::getData() const {
    return data_;
}

Godbolt Listing lst-0656-godb.cpp, https://godbolt.org/z/4fK5WdoG8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4fK5WdoG8 
template <std::copyable T>
class MyContainer {
    T data_;
public:
    void setData(const T& d);
    T getData() const;
};
template <std::copyable T>
void MyContainer<T>::setData(const T& d) {
    data_ = d;
}
template <std::copyable T>
T MyContainer<T>::getData() const {
    return data_;
}

Listing 23.31: Klassentemplate-Methoden wie Funktionstemplates spezialisieren.

Book listing lst-0657-book.cpp:

// https://godbolt.org/z/M6earoWMn 
#include <iostream>
#include <string>
#include <concepts>    // copyable, C++20
template <std::copyable T>
class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; } // allgemeiner Fall
    T getData() const { return data_; }     // allgemeiner Fall
};
template<>                                  // Spezialisierung
void MyContainer<std::string>::setData(const std::string& d) {
    data_ = "[" + d + "]";
}
int main() {
    MyContainer<std::string> mcString;
    mcString.setData("Geschichte");
    std::cout << mcString.getData() << '\n';  // Ausgabe: [Geschichte]
    MyContainer<int> mcInt;
    mcInt.setData(5);
    std::cout << mcInt.getData() << '\n';     // Ausgabe: 5
}

Godbolt Listing lst-0657-godb.cpp, https://godbolt.org/z/M6earoWMn:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M6earoWMn 
#include <iostream>
#include <string>
#include <concepts>    // copyable, C++20
template <std::copyable T>
class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; } // allgemeiner Fall
    T getData() const { return data_; }     // allgemeiner Fall
};
template<>                                  // Spezialisierung
void MyContainer<std::string>::setData(const std::string& d) {
    data_ = "[" + d + "]";
}
int main() {
    MyContainer<std::string> mcString;
    mcString.setData("Geschichte");
    std::cout << mcString.getData() << '\n';  // Ausgabe: [Geschichte]
    MyContainer<int> mcInt;
    mcInt.setData(5);
    std::cout << mcInt.getData() << '\n';     // Ausgabe: 5
}

Listing 23.32: So erzeugen Sie Instanzen aus einer Templateklasse.

Book listing lst-0658-book.cpp:

// https://godbolt.org/z/9vP3o68bW 
#include <iostream>
#include <string>
#include <concepts>    // copyable, C++20
template <std::copyable T>

class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; }
    T getData() const { return data_; }
};

class IntValue {
    int val_;
public:
    explicit IntValue(int val=0) : val_(val) {}
    int getInt() const { return val_; }
};
int main() {
    // C-Array mit drei MyContainer<double>-Instanzen
    MyContainer<double> dcont[3];
    dcont[0].setData(123.123);
    dcont[1].setData(234.234);
    std::cout << dcont[0].getData() << std::endl;
    std::cout << dcont[1].getData() << std::endl;
    // eigener Datentyp als formaler Parameter
    IntValue ival{100'000};
    MyContainer<IntValue> scont;
    scont.setData(ival);
    std::cout << scont.getData().getInt() << std::endl;
    // string als formaler Parameter
    std::string str("Text");
    MyContainer<std::string> strCont;
    strCont.setData(str);
    std::cout << strCont.getData() << std::endl;
}

Godbolt Listing lst-0658-godb.cpp, https://godbolt.org/z/9vP3o68bW:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9vP3o68bW 
#include <iostream>
#include <string>
#include <concepts>    // copyable, C++20
template <std::copyable T>

class MyContainer {
    T data_;
public:
    void setData(const T& d) { data_ = d; }
    T getData() const { return data_; }
};

class IntValue {
    int val_;
public:
    explicit IntValue(int val=0) : val_(val) {}
    int getInt() const { return val_; }
};
int main() {
    // C-Array mit drei MyContainer<double>-Instanzen
    MyContainer<double> dcont[3];
    dcont[0].setData(123.123);
    dcont[1].setData(234.234);
    std::cout << dcont[0].getData() << std::endl;
    std::cout << dcont[1].getData() << std::endl;
    // eigener Datentyp als formaler Parameter
    IntValue ival{100'000};
    MyContainer<IntValue> scont;
    scont.setData(ival);
    std::cout << scont.getData().getInt() << std::endl;
    // string als formaler Parameter
    std::string str("Text");
    MyContainer<std::string> strCont;
    strCont.setData(str);
    std::cout << strCont.getData() << std::endl;
}

Listing 23.33: Aus Konstruktorargumenten auf Templateparameter schließen

Book listing lst-0659-book.cpp:

// https://godbolt.org/z/7KzcWE8Pz 
#include <string>
#include <vector>
#include <set>
#include <tuple>
#include <memory> // shared_ptr
template <typename T>
class MyStuff {
    T data_;
public:
    MyStuff() : data_{} {}             // default c'tor
    MyStuff(const T& d) : data_{d} { } // copy c'tor
    T getStuff() const { return data_; }
};
class IntValue {
    int val_;
public:
    explicit IntValue(int val=0) : val_(val) {}
    int getInt() const { return val_; }
};
int main() {
    MyStuff intStuff(12);              // wird zu MyStuff<int>
    std::vector vs{ 1,2,3,4 };         // wird zu vector<int>
    MyStuff ivalStuff{ IntValue{33} }; // wird zu MyStuff<IntValue>
    std::tuple tpl{ 23, 'a' };         // wird zu tuple<int,char>
    std::set zweiDrei (vs.begin()+1, vs.end()-1); // wird zu set<int>
    // Kann der Compiler nicht deduzieren:
    MyStuff<double> dblStuff;              // kein Konstruktorargument
    std::vector<char> vcs(10);             // Größe 10, aber von welchem Typ?
    std::shared_ptr<int> ptr{new int{88}}; // keine Regel für int*
}

Godbolt Listing lst-0659-godb.cpp, https://godbolt.org/z/7KzcWE8Pz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7KzcWE8Pz 
#include <string>
#include <vector>
#include <set>
#include <tuple>
#include <memory> // shared_ptr
template <typename T>
class MyStuff {
    T data_;
public:
    MyStuff() : data_{} {}             // default c'tor
    MyStuff(const T& d) : data_{d} { } // copy c'tor
    T getStuff() const { return data_; }
};
class IntValue {
    int val_;
public:
    explicit IntValue(int val=0) : val_(val) {}
    int getInt() const { return val_; }
};
int main() {
    MyStuff intStuff(12);              // wird zu MyStuff<int>
    std::vector vs{ 1,2,3,4 };         // wird zu vector<int>
    MyStuff ivalStuff{ IntValue{33} }; // wird zu MyStuff<IntValue>
    std::tuple tpl{ 23, 'a' };         // wird zu tuple<int,char>
    std::set zweiDrei (vs.begin()+1, vs.end()-1); // wird zu set<int>
    // Kann der Compiler nicht deduzieren:
    MyStuff<double> dblStuff;              // kein Konstruktorargument
    std::vector<char> vcs(10);             // Größe 10, aber von welchem Typ?
    std::shared_ptr<int> ptr{new int{88}}; // keine Regel für int*
}

Listing 23.34: Sie können make_-Hilfsfunktionen und auto schon lange verwenden.

Book listing lst-0660-book.cpp:

auto tpl = std::make_tuple( 5, 'x' );
auto ptr = std::make_shared( 5 );

GodboltId:dMTnbT1v4

Book listing lst-0661-book.cpp:

// https://godbolt.org/z/dMTnbT1v4 
#include <iostream>
#include <concepts>    // copyable, C+20
template<std::copyable T, std::copyable U>
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t,const U& u) : data01_{t}, data02_{u} {}
    void print(std::ostream& os) const {
        os << data01_ << " : " << data02_ << std::endl;
    }
};
int main() {
    std::string month{"Januar"};
    int temp = -5;
    MyPair<std::string, int> temperatur{month, temp};
    temperatur.print(std::cout);
}

Godbolt Listing lst-0661-godb.cpp, https://godbolt.org/z/dMTnbT1v4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dMTnbT1v4 
#include <iostream>
#include <concepts>    // copyable, C+20
template<std::copyable T, std::copyable U>
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t,const U& u) : data01_{t}, data02_{u} {}
    void print(std::ostream& os) const {
        os << data01_ << " : " << data02_ << std::endl;
    }
};
int main() {
    std::string month{"Januar"};
    int temp = -5;
    MyPair<std::string, int> temperatur{month, temp};
    temperatur.print(std::cout);
}

GodboltId:jbafeEdoW

Book listing lst-0662-book.cpp:

// https://godbolt.org/z/jbafeEdoW 
#include <iostream>
#include <concepts>    // copyable, C++20
template<std::copyable T, std::copyable U=T>
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t,const U& u) : data01_{t}, data02_{u} {}
    void print(std::ostream& os) const {
        os << data01_ << " : " << data02_ << std::endl;
    }
};
int main() {
    MyPair<double> zahlen{11.11, 22.22};
    zahlen.print(std::cout);
}

Godbolt Listing lst-0662-godb.cpp, https://godbolt.org/z/jbafeEdoW:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jbafeEdoW 
#include <iostream>
#include <concepts>    // copyable, C++20
template<std::copyable T, std::copyable U=T>
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t,const U& u) : data01_{t}, data02_{u} {}
    void print(std::ostream& os) const {
        os << data01_ << " : " << data02_ << std::endl;
    }
};
int main() {
    MyPair<double> zahlen{11.11, 22.22};
    zahlen.print(std::cout);
}

GodboltId:xPrheoeEd

Book listing lst-0665-book.cpp:

// https://godbolt.org/z/xPrheoeEd 
#include <iostream>
template <typename T, size_t n=1>    // Non-Type-Parameter mit Defaultwert
class FixedArray {
    T data_[n] {0};                  // Non-Type-Parameter verwenden
public:
    T& operator[](size_t index) { return data_[index]; }
    static constexpr size_t size() { return n; }
    void print(std::ostream &os) const {
        for(auto it : data_)
            os << it << ' ';
        os << '\n';
    }
};
int main() {
    FixedArray<int,10> vals {};        // n = 10
    for(size_t idx=0; idx < vals.size(); ++idx) {
        vals[idx] = idx+idx;
    }
    vals.print(std::cout);             // Ausgabe: 0 2 4 6 8 10 12 14 16 18
    FixedArray<double> dvals;          // Defaultparameter für n
    std::cout << dvals.size() << '\n'; // Ausgabe: 1
}

Godbolt Listing lst-0665-godb.cpp, https://godbolt.org/z/xPrheoeEd:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xPrheoeEd 
#include <iostream>
template <typename T, size_t n=1>    // Non-Type-Parameter mit Defaultwert
class FixedArray {
    T data_[n] {0};                  // Non-Type-Parameter verwenden
public:
    T& operator[](size_t index) { return data_[index]; }
    static constexpr size_t size() { return n; }
    void print(std::ostream &os) const {
        for(auto it : data_)
            os << it << ' ';
        os << '\n';
    }
};
int main() {
    FixedArray<int,10> vals {};        // n = 10
    for(size_t idx=0; idx < vals.size(); ++idx) {
        vals[idx] = idx+idx;
    }
    vals.print(std::cout);             // Ausgabe: 0 2 4 6 8 10 12 14 16 18
    FixedArray<double> dvals;          // Defaultparameter für n
    std::cout << dvals.size() << '\n'; // Ausgabe: 1
}

GodboltId:Y6v6cKE3v

Book listing lst-0670-book.cpp:

// https://godbolt.org/z/Y6v6cKE3v 
#include <string>
#include <tuple>
#include <concepts>             // copyable, C++20
template <std::copyable T, std::copyable U=T> // allgemeiner Fall
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t, const U& u) : data01_{t}, data02_{u} {}
};
template <std::copyable T>      // teilweise Spezialisierung, T bleibt formal
class MyPair<T, std::string> {  // U ist auf string spezialisiert
    std::tuple<T,std::string> data_;
public:
    MyPair(const T& t, const std::string& str) : data_{t, str} { }
};
template <std::copyable U>      // teilweise Spezialisierung, U bleibt formal
class MyPair<std::string, U> {  // T ist auf string spezialisiert
    std::tuple<std::string, U> data_;
public:
    MyPair(const std::string& str, const U& u) : data_{str, u} { }
};
int main() {
  // nutzt partielle Spezialisierung
  MyPair<int,std::string> intString{1, "a"};
  MyPair<std::string,int> stringInt{"b", 2};

  MyPair<int,int> intInt{3,4};                     // nutzt allgemeinen Fall
  MyPair intInt2{3,4};                             // auch MyPair<int,int>
  MyPair<std::string,std::string> strStr{"c","d"}; //                                          (ERR)  mehrdeutig
}

Godbolt Listing lst-0670-godb.cpp, https://godbolt.org/z/Y6v6cKE3v:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y6v6cKE3v 
#include <string>
#include <tuple>
#include <concepts>             // copyable, C++20
template <std::copyable T, std::copyable U=T> // allgemeiner Fall
class MyPair {
    T data01_;
    U data02_;
public:
    MyPair(const T& t, const U& u) : data01_{t}, data02_{u} {}
};
template <std::copyable T>      // teilweise Spezialisierung, T bleibt formal
class MyPair<T, std::string> {  // U ist auf string spezialisiert
    std::tuple<T,std::string> data_;
public:
    MyPair(const T& t, const std::string& str) : data_{t, str} { }
};
template <std::copyable U>      // teilweise Spezialisierung, U bleibt formal
class MyPair<std::string, U> {  // T ist auf string spezialisiert
    std::tuple<std::string, U> data_;
public:
    MyPair(const std::string& str, const U& u) : data_{str, u} { }
};
int main() {
  // nutzt partielle Spezialisierung
  MyPair<int,std::string> intString{1, "a"};
  MyPair<std::string,int> stringInt{"b", 2};

  MyPair<int,int> intInt{3,4};                     // nutzt allgemeinen Fall
  MyPair intInt2{3,4};                             // auch MyPair<int,int>
  MyPair<std::string,std::string> strStr{"c","d"}; //                                          (ERR)  mehrdeutig
}

GodboltId:baPeoTbM8

Book listing lst-0671-book.cpp:

// https://godbolt.org/z/baPeoTbM8 
template<>   // vollständige Spezialisierung
class MyPair<std::string, std::string> {
    std::vector<std::string> data_;
public:
    MyPair(const std::string& t, const std::string& u) : data_{t, u} { }
};
int main() {
    // nutzt die vollständige Spezialisierung:
    MyPair<std::string,std::string> strStr{"c","d"};
}

Godbolt Listing lst-0671-godb.cpp, https://godbolt.org/z/baPeoTbM8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/baPeoTbM8 
template<>   // vollständige Spezialisierung
class MyPair<std::string, std::string> {
    std::vector<std::string> data_;
public:
    MyPair(const std::string& t, const std::string& u) : data_{t, u} { }
};
int main() {
    // nutzt die vollständige Spezialisierung:
    MyPair<std::string,std::string> strStr{"c","d"};
}

Listing 23.35: Ein Template mit einer variablen Anzahl von Argumenten

Book listing lst-0672-book.cpp:

// https://godbolt.org/z/c6W6EWb1K 
#include <typeinfo>               // operator typeid
#include <typeindex>              // type_index
#include <map>
#include <string>
#include <iostream>
template <typename T>
void output(std::ostream& os, T val) { // einen Typnamen ausgeben
    // static: beim ersten Mal initialisiert
    static const std::map<std::type_index,std::string> type_names {
        { std::type_index(typeid(const char*)), "const char*"},
        { std::type_index(typeid(char)), "char"},
        { std::type_index(typeid(int)), "int"},
        { std::type_index(typeid(double)), "double"},
        { std::type_index(typeid(bool)), "bool"},
    };
    const std::string name = type_names.at(std::type_index(typeid(T)));
    os << name << ": " << val << '\n';
}
// rekursives variadisches Funktionstemplate:
template<typename First, typename ... Rest>
void output(std::ostream &os, First first, Rest ... rest) {
    output(os, first);           // einzelner Aufruf mit vorderstem Element
    output(os, rest ...);        // Rekursion mit Rest der Elemente
}
int main() {
  output(std::cout, 3.1415);                      // normales Template
  output(std::cout, "ende", 2, 3.14, 'A', false); // rekursive variadische Funktion
}

Godbolt Listing lst-0672-godb.cpp, https://godbolt.org/z/c6W6EWb1K:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/c6W6EWb1K 
#include <typeinfo>               // operator typeid
#include <typeindex>              // type_index
#include <map>
#include <string>
#include <iostream>
template <typename T>
void output(std::ostream& os, T val) { // einen Typnamen ausgeben
    // static: beim ersten Mal initialisiert
    static const std::map<std::type_index,std::string> type_names {
        { std::type_index(typeid(const char*)), "const char*"},
        { std::type_index(typeid(char)), "char"},
        { std::type_index(typeid(int)), "int"},
        { std::type_index(typeid(double)), "double"},
        { std::type_index(typeid(bool)), "bool"},
    };
    const std::string name = type_names.at(std::type_index(typeid(T)));
    os << name << ": " << val << '\n';
}
// rekursives variadisches Funktionstemplate:
template<typename First, typename ... Rest>
void output(std::ostream &os, First first, Rest ... rest) {
    output(os, first);           // einzelner Aufruf mit vorderstem Element
    output(os, rest ...);        // Rekursion mit Rest der Elemente
}
int main() {
  output(std::cout, 3.1415);                      // normales Template
  output(std::cout, "ende", 2, 3.14, 'A', false); // rekursive variadische Funktion
}

GodboltId:8oYaWYnbx

Book listing lst-0678-book.cpp:

// https://godbolt.org/z/8oYaWYnbx 
#include <tuple>
#include <iostream>
template<typename ... Args>
auto conv2tuple(Args ... args) {
    return std::make_tuple(args...);
}
int main() {
    auto mytuple = conv2tuple("ende", 2, 3.14, 'A', false);
    std::cout << std::get<2>(mytuple) << '\n'; // Ausgabe: 3.14
}

Godbolt Listing lst-0678-godb.cpp, https://godbolt.org/z/8oYaWYnbx:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8oYaWYnbx 
#include <tuple>
#include <iostream>
template<typename ... Args>
auto conv2tuple(Args ... args) {
    return std::make_tuple(args...);
}
int main() {
    auto mytuple = conv2tuple("ende", 2, 3.14, 'A', false);
    std::cout << std::get<2>(mytuple) << '\n'; // Ausgabe: 3.14
}

Listing 23.36: Eigene Literaloperatoren

Book listing lst-0679-book.cpp:

// https://godbolt.org/z/cjx49ef19 
namespace my {
  Complex operator"" _i(const char*); // 0+ni
  Complex operator"" _j(long double); // n+0i
  Puzzle operator"" _puzzle(const char*, size_t);
}
using namespace my;
Complex imag4 = 4_i;      // operator"" _i(const char*)
Complex real3 = 3.331_j;  // operator"" _j(long double)

Puzzle p1 = "oXo"         // operator"" _puzzle(const char*, size_t)
            "XoX"_puzzle;

Godbolt Listing lst-0679-godb.cpp, https://godbolt.org/z/cjx49ef19:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cjx49ef19 
namespace my {
  Complex operator"" _i(const char*); // 0+ni
  Complex operator"" _j(long double); // n+0i
  Puzzle operator"" _puzzle(const char*, size_t);
}
using namespace my;
Complex imag4 = 4_i;      // operator"" _i(const char*)
Complex real3 = 3.331_j;  // operator"" _j(long double)

Puzzle p1 = "oXo"         // operator"" _puzzle(const char*, size_t)
            "XoX"_puzzle;

Listing 23.37: Welches Literal führt zu welchem Operatoraufruf?

Book listing lst-0680-book.cpp:

// https://godbolt.org/z/Mevoshb3o 
namespace lits {
  long double operator"" _w(long double);
  string      operator"" _w(const char16_t*, size_t);
  unsigned    operator"" _w(const char*);
}
int main() {
  using namespace lits;
  1.2_w;       // operator"" _w(long double), mit (1.2L)
  u"one"_w;    // operator"" _w(char16_t, size_t), mit (u"one", 3)
  12_w;        // operator"" _w(const char*), mit "12"
  "two"_w;     //                                  (ERR)  operator"" _w(const char*, size_t) nicht definiert
}

Godbolt Listing lst-0680-godb.cpp, https://godbolt.org/z/Mevoshb3o:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mevoshb3o 
namespace lits {
  long double operator"" _w(long double);
  string      operator"" _w(const char16_t*, size_t);
  unsigned    operator"" _w(const char*);
}
int main() {
  using namespace lits;
  1.2_w;       // operator"" _w(long double), mit (1.2L)
  u"one"_w;    // operator"" _w(char16_t, size_t), mit (u"one", 3)
  12_w;        // operator"" _w(const char*), mit "12"
  "two"_w;     //                                  (ERR)  operator"" _w(const char*, size_t) nicht definiert
}

Listing 23.38: Ein Template für Literale der exakten Länge zwei

Book listing lst-0681-book.cpp:

// https://godbolt.org/z/5rdzn8YP4 
namespace lits {
  // allgemeines Template
  template<char...> int operator"" _bin2();
  // Spezialisierungen
  template<> int operator"" _bin2<'0','0'>() { return 0; }
  template<> int operator"" _bin2<'0','1'>() { return 1; }
  template<> int operator"" _bin2<'1','0'>() { return 2; }
  template<> int operator"" _bin2<'1','1'>() { return 3; }
}
int main() {
  using namespace lits;
  int one   = 01_bin2;
  int three = 11_bin2;
}

Godbolt Listing lst-0681-godb.cpp, https://godbolt.org/z/5rdzn8YP4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5rdzn8YP4 
namespace lits {
  // allgemeines Template
  template<char...> int operator"" _bin2();
  // Spezialisierungen
  template<> int operator"" _bin2<'0','0'>() { return 0; }
  template<> int operator"" _bin2<'0','1'>() { return 1; }
  template<> int operator"" _bin2<'1','0'>() { return 2; }
  template<> int operator"" _bin2<'1','1'>() { return 3; }
}
int main() {
  using namespace lits;
  int one   = 01_bin2;
  int three = 11_bin2;
}

Listing 23.39: Rekursive Definition für beliebige Literallängen

Book listing lst-0682-book.cpp:

// https://godbolt.org/z/sbxojqjqs 
namespace lits {
  // Templatehilfsfunktion für ein Argument
  template<char C> int bin();  // allgemeiner Fall
  template<>       int bin<'1'>() { return 1; } // Spezialisierung.
  template<>       int bin<'0'>() { return 0; } // Spezialisierung.
  // Templatehilfsfunktion ab zwei Argumente
  template<char C, char D, char... ES>
  int bin() {
    return bin<C>() << (sizeof...(ES)+1) | bin<D,ES...>(); // Bit-Shift, Bit-Oder
  }
  // eigentlicher operator""
  template<char...CS> int operator"" _bin()
    { return bin<CS...>(); };
}
int main() {
  using namespace lits;
  int eins = 1_bin;
  int acht = 1000_bin;
  int neun = 1001_bin;
  int zehn = 1010_bin;
  int elf  = 1011_bin;
  int hundertachtundzwanzig = 10000000_bin;
}

Godbolt Listing lst-0682-godb.cpp, https://godbolt.org/z/sbxojqjqs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sbxojqjqs 
namespace lits {
  // Templatehilfsfunktion für ein Argument
  template<char C> int bin();  // allgemeiner Fall
  template<>       int bin<'1'>() { return 1; } // Spezialisierung.
  template<>       int bin<'0'>() { return 0; } // Spezialisierung.
  // Templatehilfsfunktion ab zwei Argumente
  template<char C, char D, char... ES>
  int bin() {
    return bin<C>() << (sizeof...(ES)+1) | bin<D,ES...>(); // Bit-Shift, Bit-Oder
  }
  // eigentlicher operator""
  template<char...CS> int operator"" _bin()
    { return bin<CS...>(); };
}
int main() {
  using namespace lits;
  int eins = 1_bin;
  int acht = 1000_bin;
  int neun = 1001_bin;
  int zehn = 1010_bin;
  int elf  = 1011_bin;
  int hundertachtundzwanzig = 10000000_bin;
}

Listing 23.40: Das neue if constexpr spart Funktionsspezialisierungen.

Book listing lst-0683-book.cpp:

// https://godbolt.org/z/KvsGh4f1v 
namespace lits {
  // Templatehilfsfunktion für ein Argument
  template<char C> int bin() {  // allgemeiner Fall
    if constexpr (C=='0') return 0;
    else if constexpr (C=='1') return 1;
  }
  // Templatehilfsfunktion ab zwei Argumente
  // …
}

Godbolt Listing lst-0683-godb.cpp, https://godbolt.org/z/KvsGh4f1v:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KvsGh4f1v 
namespace lits {
  // Templatehilfsfunktion für ein Argument
  template<char C> int bin() {  // allgemeiner Fall
    if constexpr (C=='0') return 0;
    else if constexpr (C=='1') return 1;
  }
  // Templatehilfsfunktion ab zwei Argumente
  // …
}

Listing 23.41: Mit Faltausdrücken werden variadische Templates einfacher.

Book listing lst-0684-book.cpp:

// https://godbolt.org/z/cPoEjqzM7 
#include <iostream>
#include <string>
namespace lits {
    // operator"" _sx
    template<char...CS> std::string operator"" _sx() {
        return (std::string{} + ... + CS); // ein Faltausdruck
    };
}
int main() {
    using namespace lits;
    std::cout << 10000000_sx << '\n';     // Ausgabe: 10000000
    std::cout << 10'000'000_sx << '\n';   // Ausgabe: 10'000'000
    std::cout << 0x00af_sx << '\n';       // Ausgabe: 0x00af
    std::cout << 0x0'c'0'a'f_sx << '\n';  // Ausgabe: 0x0'c'0'a'f
    std::cout << 007_sx << '\n';          // Ausgabe: 007
    std::cout << 0b01_sx << '\n';         // Ausgabe: 0b01
}

Godbolt Listing lst-0684-godb.cpp, https://godbolt.org/z/cPoEjqzM7:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cPoEjqzM7 
#include <iostream>
#include <string>
namespace lits {
    // operator"" _sx
    template<char...CS> std::string operator"" _sx() {
        return (std::string{} + ... + CS); // ein Faltausdruck
    };
}
int main() {
    using namespace lits;
    std::cout << 10000000_sx << '\n';     // Ausgabe: 10000000
    std::cout << 10'000'000_sx << '\n';   // Ausgabe: 10'000'000
    std::cout << 0x00af_sx << '\n';       // Ausgabe: 0x00af
    std::cout << 0x0'c'0'a'f_sx << '\n';  // Ausgabe: 0x0'c'0'a'f
    std::cout << 007_sx << '\n';          // Ausgabe: 007
    std::cout << 0b01_sx << '\n';         // Ausgabe: 0b01
}

Listing 23.42: Ob vorverarbeitet oder roh besser ist, hängt von der Anwendung ab.

Book listing lst-0685-book.cpp:

// https://godbolt.org/z/Yd4sser5j 
#include <complex>
// rohe Form
int operator"" _dual(const char*);
int answer = 101010_dual;    // dezimal 42
// vorverarbeitete Form
std::complex<long double> operator"" _i(long double d) {
  return std::complex<long double>(0, d);
}
auto val = 3.14_i; // val = std::complex<long double>(0, 3.14)

Godbolt Listing lst-0685-godb.cpp, https://godbolt.org/z/Yd4sser5j:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Yd4sser5j 
#include <complex>
// rohe Form
int operator"" _dual(const char*);
int answer = 101010_dual;    // dezimal 42
// vorverarbeitete Form
std::complex<long double> operator"" _i(long double d) {
  return std::complex<long double>(0, d);
}
auto val = 3.14_i; // val = std::complex<long double>(0, 3.14)

Listing 24.1: Für Bereiche nutzen Sie Iteratorpaare oder ab C++23 Ranges.

Book listing lst-0694-book.cpp:

// https://godbolt.org/z/qGrYPrqYn 
#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector nums{ 1,2,3 };
    vector vier{ 4,5,6 };
    vector sieben{ 7,8,9 } ;
    nums.insert(nums.begin(), vier.begin(), vier.end());
    cout << nums.size() << "\n";                      // Ausgabe: 9
    nums.insert_range(nums.begin(), sieben);          // C++23
}

Godbolt Listing lst-0694-godb.cpp, https://godbolt.org/z/qGrYPrqYn:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qGrYPrqYn 
#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector nums{ 1,2,3 };
    vector vier{ 4,5,6 };
    vector sieben{ 7,8,9 } ;
    nums.insert(nums.begin(), vier.begin(), vier.end());
    cout << nums.size() << "\n";                      // Ausgabe: 9
    nums.insert_range(nums.begin(), sieben);          // C++23
}

Listing 24.2: Ein Paar Iteratoren definiert einen Bereich von Elementen.

Book listing lst-0695-book.cpp:

// https://godbolt.org/z/M1d9jEP74 
#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector numbers{ 1,2,3,4,5 };
    numbers.erase(numbers.begin(), numbers.end());
    cout << numbers.size() << "\n"; // Ausgabe: 0
}

Godbolt Listing lst-0695-godb.cpp, https://godbolt.org/z/M1d9jEP74:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M1d9jEP74 
#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector numbers{ 1,2,3,4,5 };
    numbers.erase(numbers.begin(), numbers.end());
    cout << numbers.size() << "\n"; // Ausgabe: 0
}

Listing 24.3: Verwendet indirekt begin() und end() des Containers

Book listing lst-0696-book.cpp:

// https://godbolt.org/z/Yv3vcxPv5 
#include <vector>
#include <iostream>
int main() {
    std::vector<int> numbers{ 1,2,3,4,5 };
    for(auto val : numbers) {
        std::cout << val << ' ';
    }
    std::cout << '\n';
}

Godbolt Listing lst-0696-godb.cpp, https://godbolt.org/z/Yv3vcxPv5:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Yv3vcxPv5 
#include <vector>
#include <iostream>
int main() {
    std::vector<int> numbers{ 1,2,3,4,5 };
    for(auto val : numbers) {
        std::cout << val << ' ';
    }
    std::cout << '\n';
}

GodboltId:babK485oT

Book listing lst-0697-book.cpp:

// https://godbolt.org/z/babK485oT 
#include <vector>
#include <iostream>
int main() {
    std::vector<int> numbers{ 1,2,3,4,5 };
    for(auto it = begin(numbers); it != end(numbers); ++it) {
        auto val = *it;
        std::cout << val << ' ';
    }
    std::cout << '\n';
}

Godbolt Listing lst-0697-godb.cpp, https://godbolt.org/z/babK485oT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/babK485oT 
#include <vector>
#include <iostream>
int main() {
    std::vector<int> numbers{ 1,2,3,4,5 };
    for(auto it = begin(numbers); it != end(numbers); ++it) {
        auto val = *it;
        std::cout << val << ' ';
    }
    std::cout << '\n';
}

GodboltId:nj14e6Wq4

Book listing lst-0698-book.cpp:

// https://godbolt.org/z/nj14e6Wq4 
#include <set>
#include <iostream>
int main() {
    std::set<int> numbers{ 10, 20, 90 };
    auto nein = numbers.find(30);
    if(nein == numbers.end()) { std::cout << "nicht da.\n"; }
    auto ja = numbers.find(20);
    if(ja != numbers.end()) { std::cout << *ja << '\n'; }
}

Godbolt Listing lst-0698-godb.cpp, https://godbolt.org/z/nj14e6Wq4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nj14e6Wq4 
#include <set>
#include <iostream>
int main() {
    std::set<int> numbers{ 10, 20, 90 };
    auto nein = numbers.find(30);
    if(nein == numbers.end()) { std::cout << "nicht da.\n"; }
    auto ja = numbers.find(20);
    if(ja != numbers.end()) { std::cout << *ja << '\n'; }
}

Listing 24.4: Ein Algorithmus nach dem anderen mit Iteratoren

Book listing lst-0699-book.cpp:

// https://godbolt.org/z/arfee3TTP 
using namespace std;
vector in { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
vector<int> tmp{};
vector<int> out{};
copy_if(in.begin(), in.end(), back_inserter(tmp), [](int i) { return i%3 == 0; });
transform(tmp.begin(), tmp.end(), back_inserter(out), [](int i) {return i*i; });

Godbolt Listing lst-0699-godb.cpp, https://godbolt.org/z/arfee3TTP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/arfee3TTP 
using namespace std;
vector in { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
vector<int> tmp{};
vector<int> out{};
copy_if(in.begin(), in.end(), back_inserter(tmp), [](int i) { return i%3 == 0; });
transform(tmp.begin(), tmp.end(), back_inserter(out), [](int i) {return i*i; });

Listing 24.5: Eine Pipeline aus Views statt Algorithmen

Book listing lst-0700-book.cpp:

// https://godbolt.org/z/TG1qd31Mq 
using namespace std; namespace views = std::ranges::views;
vector in { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
auto out = in
    | views::filter([](int i) { return i%3 == 0; })
    | views::transform([](int i) {return i*i; });

Godbolt Listing lst-0700-godb.cpp, https://godbolt.org/z/TG1qd31Mq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TG1qd31Mq 
using namespace std; namespace views = std::ranges::views;
vector in { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
auto out = in
    | views::filter([](int i) { return i%3 == 0; })
    | views::transform([](int i) {return i*i; });

Listing 24.8: Für »const«-Objekte liefern »begin()« und »end()« einen »const_iterator« zurück.

Book listing lst-0702-book.cpp:

// https://godbolt.org/z/dxb98rWzo 
#include <iostream>                // cout
#include <vector>
using std::vector;

vector<int> createData(size_t sz) {
    return vector<int>(sz);        // sz x null
}
void fibonacci(vector<int> &data) {
    for(auto it = begin(data)+2; it != end(data); ++it) { // iterator it
        *it = *(it-1) + *(it-2);
    }
}

std::ostream& show(std::ostream &os, const vector<int> &data) {
    for(auto it=begin(data); it != end(data); ++it)       // const_iterator it
        std::cout << *it << " ";
    return os;
}

int main() {
    vector<int> data = createData(10);
    data[0] = 1;
    data[1] = 1;
    fibonacci(data);
    show(std::cout, data) << "\n";
}

Godbolt Listing lst-0702-godb.cpp, https://godbolt.org/z/dxb98rWzo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dxb98rWzo 
#include <iostream>                // cout
#include <vector>
using std::vector;

vector<int> createData(size_t sz) {
    return vector<int>(sz);        // sz x null
}
void fibonacci(vector<int> &data) {
    for(auto it = begin(data)+2; it != end(data); ++it) { // iterator it
        *it = *(it-1) + *(it-2);
    }
}

std::ostream& show(std::ostream &os, const vector<int> &data) {
    for(auto it=begin(data); it != end(data); ++it)       // const_iterator it
        std::cout << *it << " ";
    return os;
}

int main() {
    vector<int> data = createData(10);
    data[0] = 1;
    data[1] = 1;
    fibonacci(data);
    show(std::cout, data) << "\n";
}

Listing 24.9: Iteratoradapter verändern das Verhalten von Operationen.

Book listing lst-0706-book.cpp:

// https://godbolt.org/z/7xYcqqh68 
#include <vector>
#include <iostream>   // cout
#include <iterator>   // ostream_iterator
#include <algorithm>  // copy

int main() {
  std::vector data { 1, 2, 3, 7, 9, 10 };
  std::ostream_iterator<int> out_it (std::cout,", "); // bei Zuweisung nach cout
  std::copy(data.begin(), data.end(), out_it); // alle Elemente in den Iterator
  std::cout << "\n";                           // Ausgabe: 1, 2, 3, 7, 9, 10,
  // oder ab C++20 mit Ranges:
  std::ranges::copy(data, out_it);
  std::cout << "\n";                           // Ausgabe: 1, 2, 3, 7, 9, 10,
}

Godbolt Listing lst-0706-godb.cpp, https://godbolt.org/z/7xYcqqh68:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7xYcqqh68 
#include <vector>
#include <iostream>   // cout
#include <iterator>   // ostream_iterator
#include <algorithm>  // copy

int main() {
  std::vector data { 1, 2, 3, 7, 9, 10 };
  std::ostream_iterator<int> out_it (std::cout,", "); // bei Zuweisung nach cout
  std::copy(data.begin(), data.end(), out_it); // alle Elemente in den Iterator
  std::cout << "\n";                           // Ausgabe: 1, 2, 3, 7, 9, 10,
  // oder ab C++20 mit Ranges:
  std::ranges::copy(data, out_it);
  std::cout << "\n";                           // Ausgabe: 1, 2, 3, 7, 9, 10,
}

Listing 24.10: Ein (zu) einfacher Allokator und sein Einsatz

Book listing lst-0707-book.cpp:

// https://godbolt.org/z/TzvK9hTsj 
#include <set>
#include <vector>
#include <iostream>
template<class T> class HappsAllocator  {
public:
    using value_type = T;
    T* allocate(size_t count) {
        size_t add = sizeof(T)*count;
        std::cout << "allocate("<<add<<"/"<<(buf_.size()-current_)<<")\n";
        if(current_+add > buf_.size()) throw std::bad_alloc{};
        char* result = buf_.data()+current_;
        current_ += add;
        return reinterpret_cast<T*>(result);
    }
    void deallocate(T* p, size_t count) {
        size_t del = sizeof(T)*count;
        std::cout << "deallocate("<<del<<")\n";
        if(del==current_ && p==reinterpret_cast<T*>(buf_.data())) {
            std::cout << "...alles frei.\n";
            current_ = 0;// alles wieder freigeben
        }
    }
    HappsAllocator() : HappsAllocator{1024} {}
    explicit HappsAllocator(size_t mx)
      : buf_(mx, 0), current_{0} { }
private:
       std::vector<char> buf_;
       size_t current_;
};
int main() {
    constexpr size_t ANZ = 1*1000*1000;
    using Happs = HappsAllocator<int>;
    try {
        Happs happs(ANZ*sizeof(int)); // Allokator vorbereiten
        std::vector<int,Happs> data(happs);
        data.reserve(ANZ);            // Speicher in einem Schwung holen
        for(int val=0; val < (int)ANZ; ++val)
            data.push_back(val);
    } catch(std::bad_alloc &ex) {
        std::cout << "Speicher alle.\n";
    }
}

Godbolt Listing lst-0707-godb.cpp, https://godbolt.org/z/TzvK9hTsj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TzvK9hTsj 
#include <set>
#include <vector>
#include <iostream>
template<class T> class HappsAllocator  {
public:
    using value_type = T;
    T* allocate(size_t count) {
        size_t add = sizeof(T)*count;
        std::cout << "allocate("<<add<<"/"<<(buf_.size()-current_)<<")\n";
        if(current_+add > buf_.size()) throw std::bad_alloc{};
        char* result = buf_.data()+current_;
        current_ += add;
        return reinterpret_cast<T*>(result);
    }
    void deallocate(T* p, size_t count) {
        size_t del = sizeof(T)*count;
        std::cout << "deallocate("<<del<<")\n";
        if(del==current_ && p==reinterpret_cast<T*>(buf_.data())) {
            std::cout << "...alles frei.\n";
            current_ = 0;// alles wieder freigeben
        }
    }
    HappsAllocator() : HappsAllocator{1024} {}
    explicit HappsAllocator(size_t mx)
      : buf_(mx, 0), current_{0} { }
private:
       std::vector<char> buf_;
       size_t current_;
};
int main() {
    constexpr size_t ANZ = 1*1000*1000;
    using Happs = HappsAllocator<int>;
    try {
        Happs happs(ANZ*sizeof(int)); // Allokator vorbereiten
        std::vector<int,Happs> data(happs);
        data.reserve(ANZ);            // Speicher in einem Schwung holen
        for(int val=0; val < (int)ANZ; ++val)
            data.push_back(val);
    } catch(std::bad_alloc &ex) {
        std::cout << "Speicher alle.\n";
    }
}

Listing 24.11: Typaliase sind manchmal klarer als die konkreten Typen.

Book listing lst-0709-book.cpp:

// https://godbolt.org/z/c97qra3M7 
#include <vector>
#include <map>
#include <iostream>
using std::cout; using std::ostream;
template<typename K, typename T>
ostream& operator<<(ostream& os, std::pair<const K,T> value) {
    return os << '[' << value.first << ':' << value.second << ']';
}
int main() {
  {
    using Cont = std::vector<int>;
    Cont cont{ 1, 2, 3, 4, 5, 6 };
    Cont::size_type sz = cont.size();
    cout << "size=" << sz << " content= ";
    for(Cont::const_iterator it = cont.begin(); it != cont.end(); ++it) 
        cout << *it << ' ';
    cout << '\n';
  }
  {
    using Cont = std::map<int,char>;
    Cont cont{ {1,'a'}, {2,'b'}, {3,'c'}, {4,'d'}, {5,'e'}, {6,'f'} };
    Cont::size_type sz = cont.size();
    cout << "size=" << sz << " content= ";
    for(Cont::const_iterator it = cont.begin(); it != cont.end(); ++it) 
        cout << *it << ' ';
    cout << '\n';
  }
}

Godbolt Listing lst-0709-godb.cpp, https://godbolt.org/z/c97qra3M7:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/c97qra3M7 
#include <vector>
#include <map>
#include <iostream>
using std::cout; using std::ostream;
template<typename K, typename T>
ostream& operator<<(ostream& os, std::pair<const K,T> value) {
    return os << '[' << value.first << ':' << value.second << ']';
}
int main() {
  {
    using Cont = std::vector<int>;
    Cont cont{ 1, 2, 3, 4, 5, 6 };
    Cont::size_type sz = cont.size();
    cout << "size=" << sz << " content= ";
    for(Cont::const_iterator it = cont.begin(); it != cont.end(); ++it) 
        cout << *it << ' ';
    cout << '\n';
  }
  {
    using Cont = std::map<int,char>;
    Cont cont{ {1,'a'}, {2,'b'}, {3,'c'}, {4,'d'}, {5,'e'}, {6,'f'} };
    Cont::size_type sz = cont.size();
    cout << "size=" << sz << " content= ";
    for(Cont::const_iterator it = cont.begin(); it != cont.end(); ++it) 
        cout << *it << ' ';
    cout << '\n';
  }
}

Listing 24.12: Dies ist die Schablone für die Beispiellistings dieses Abschnitts zu vector.

Book listing lst-0710-book.cpp:

// https://godbolt.org/z/WK86eaz1x 
#include <vector>
#include <iostream>
using std::vector; using std::cout;
template<typename T>
std::ostream& operator<<(std::ostream&os, const vector<T>& data) {
    for(const auto &e : data) {
        os << e << ' ';
    }
    return os;
}
int main() {h
   // Beispielcode hier
}

Godbolt Listing lst-0710-godb.cpp, https://godbolt.org/z/WK86eaz1x:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WK86eaz1x 
#include <vector>
#include <iostream>
using std::vector; using std::cout;
template<typename T>
std::ostream& operator<<(std::ostream&os, const vector<T>& data) {
    for(const auto &e : data) {
        os << e << ' ';
    }
    return os;
}
int main() {h
   // Beispielcode hier
}

Listing 24.13: Der Standardkonstruktor initialisiert einen vector leer.

Book listing lst-0711-book.cpp:

// https://godbolt.org/z/7zMP5fo7c 
vector<int> dataA;
vector<int> dataB{};
vector<int> dataC = {};   // keine Zuweisung
cout << format("{} {} {}\n", dataA.size(), dataB.size(), dataC.size()); // 0 0 0

Godbolt Listing lst-0711-godb.cpp, https://godbolt.org/z/7zMP5fo7c:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7zMP5fo7c 
vector<int> dataA;
vector<int> dataB{};
vector<int> dataC = {};   // keine Zuweisung
cout << format("{} {} {}\n", dataA.size(), dataB.size(), dataC.size()); // 0 0 0

Listing 24.14: Sie kopieren einen »vector« mittels des Konstruktors oder implizit.

Book listing lst-0712-book.cpp:

// https://godbolt.org/z/cE6G1aErs 
auto zaehle(vector<int> arg) { return arg.size(); }
// …
vector input{1,2,3};           // vector<int>
vector outputA(input);         // Kopie
vector outputB = input;        // auch Kopie, keine Zuweisung
cout << zaehle(input) << '\n'; // Aufruf per Copy-by-Value

Godbolt Listing lst-0712-godb.cpp, https://godbolt.org/z/cE6G1aErs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cE6G1aErs 
auto zaehle(vector<int> arg) { return arg.size(); }
// …
vector input{1,2,3};           // vector<int>
vector outputA(input);         // Kopie
vector outputB = input;        // auch Kopie, keine Zuweisung
cout << zaehle(input) << '\n'; // Aufruf per Copy-by-Value

Listing 24.15: Bei Rückgabewerten kann der Compiler auch oft verschieben.

Book listing lst-0713-book.cpp:

// https://godbolt.org/z/EK4e7Trv3 
#include <list>
#include <string>
#include <iterator>                      // make_move_iterator
using std::make_move_iterator; using std::string;
vector<int> erzeuge() { return vector<int>{8, 9, 10}; }
size_t zaehle(vector<int> d) { return d.size(); }
// …
vector input{1,2,3};
vector outputA(std::move(input));       // Verschiebung
vector outputB = std::move(input);      // auch Verschiebung, keine Zuweisung
vector data = erzeuge();                // Return-Value-Optimization
cout << zaehle(input) << '\n';          // Aufruf per Copy-by-Value
// elementweise aus einem anderen Container verschieben
std::list<string> quelle{ "a", "a", "a", "BB", "CC", "DD", "b", "b" };
auto von = quelle.begin();
std::advance(von, 3); // 3 vorwärts, bei list aber langsam
auto bis = von;
std::advance(bis, 3); // noch mal 3 vorwärts
vector ziel(make_move_iterator(von), make_move_iterator(bis));
// quelle ist nun {"a", "a", "a", "", "", "", "b", "b"}, ziel ist nun {"BB", "CC", "DD"}

Godbolt Listing lst-0713-godb.cpp, https://godbolt.org/z/EK4e7Trv3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EK4e7Trv3 
#include <list>
#include <string>
#include <iterator>                      // make_move_iterator
using std::make_move_iterator; using std::string;
vector<int> erzeuge() { return vector<int>{8, 9, 10}; }
size_t zaehle(vector<int> d) { return d.size(); }
// …
vector input{1,2,3};
vector outputA(std::move(input));       // Verschiebung
vector outputB = std::move(input);      // auch Verschiebung, keine Zuweisung
vector data = erzeuge();                // Return-Value-Optimization
cout << zaehle(input) << '\n';          // Aufruf per Copy-by-Value
// elementweise aus einem anderen Container verschieben
std::list<string> quelle{ "a", "a", "a", "BB", "CC", "DD", "b", "b" };
auto von = quelle.begin();
std::advance(von, 3); // 3 vorwärts, bei list aber langsam
auto bis = von;
std::advance(bis, 3); // noch mal 3 vorwärts
vector ziel(make_move_iterator(von), make_move_iterator(bis));
// quelle ist nun {"a", "a", "a", "", "", "", "b", "b"}, ziel ist nun {"BB", "CC", "DD"}

Listing 24.16: Mit einer Initialisierungsliste befüllen Sie einen vector vorab. Achten Sie auf die korrekten Typen in der Liste.

Book listing lst-0714-book.cpp:

// https://godbolt.org/z/4T7fjxdPa 
vector<int> prims{ 2,3,5,7,11 };
vector gerade{ 2,4,6,8,10 };
vector<int> soNicht{ 'a', 4.3, 8L };     //                                          (ERR)  "Narrowing" double nicht okay
vector<string> namen{ "sind", "nur" };   // konvertiert Argumente
vector schall{ "rauch", "qualm" };       // gefährlich: vector<const char[]>
vector nass{ "regen"s, "wasser"s };      // vector<string>
vector kalt{ "eis"sv, "pol"sv };         // vector<string_view>

Godbolt Listing lst-0714-godb.cpp, https://godbolt.org/z/4T7fjxdPa:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4T7fjxdPa 
vector<int> prims{ 2,3,5,7,11 };
vector gerade{ 2,4,6,8,10 };
vector<int> soNicht{ 'a', 4.3, 8L };     //                                          (ERR)  "Narrowing" double nicht okay
vector<string> namen{ "sind", "nur" };   // konvertiert Argumente
vector schall{ "rauch", "qualm" };       // gefährlich: vector<const char[]>
vector nass{ "regen"s, "wasser"s };      // vector<string>
vector kalt{ "eis"sv, "pol"sv };         // vector<string_view>

Listing 24.17: Kopieren Sie bei der Initialisierung Werte aus einem beliebigen anderen Container oder C-Array.

Book listing lst-0715-book.cpp:

// https://godbolt.org/z/foPadWsKs 
#include <deque>
#include <ranges>                       // C++20
// …
std::deque in{1,2,33,34,35,99};
vector dreissig(in.begin()+2, in.begin()+5);
for(auto &e : dreissig) {
    cout << e << ' ';
}
cout << '\n';
namespace vs = std::ranges::views;      // C++20
auto v = in | vs::drop(2) | vs::take(3);
vector otuz(v.begin(), v.end());
vector trente(std::from_range, in);     // C++23

Godbolt Listing lst-0715-godb.cpp, https://godbolt.org/z/foPadWsKs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/foPadWsKs 
#include <deque>
#include <ranges>                       // C++20
// …
std::deque in{1,2,33,34,35,99};
vector dreissig(in.begin()+2, in.begin()+5);
for(auto &e : dreissig) {
    cout << e << ' ';
}
cout << '\n';
namespace vs = std::ranges::views;      // C++20
auto v = in | vs::drop(2) | vs::take(3);
vector otuz(v.begin(), v.end());
vector trente(std::from_range, in);     // C++23

Listing 24.18: Vorinitialisieren mit einer festen Anzahl von Werten gibt es (fast) nur bei »vector«.

Book listing lst-0716-book.cpp:

// https://godbolt.org/z/addobjfsK 
vector<int> zeros(10);        // 10 Nullen
vector<int> sechsen(10, 6);   // 10 Sechsen
vector<int> zehn{10};         //                                          (ERR)  Achtung! Nur eine 10
vector<int> zehnSechs{10, 6}; //                                          (ERR)  Achtung! Zwei Elemente 10 und 6

Godbolt Listing lst-0716-godb.cpp, https://godbolt.org/z/addobjfsK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/addobjfsK 
vector<int> zeros(10);        // 10 Nullen
vector<int> sechsen(10, 6);   // 10 Sechsen
vector<int> zehn{10};         //                                          (ERR)  Achtung! Nur eine 10
vector<int> zehnSechs{10, 6}; //                                          (ERR)  Achtung! Zwei Elemente 10 und 6

Listing 24.19: »vector« können Sie zuweisen oder mit »assign« später reinitialisieren.

Book listing lst-0717-book.cpp:

// https://godbolt.org/z/Yb4jEdaKj 
vector<int> von{ 2,3,4 };
vector<int> nach{};
nach = von;                         // Zuweisung mit operator=, nun beide gleich

vector<int> abfluss{};
abfluss = std::move(von);           // Verschieben, nun ist 'von' leer
vector<int> v;
v.assign(4, 100);                   // v ist nun {100, 100, 100, 100}
v.assign(nach.begin(), nach.end()); // v ist nun {2,3,4}
int z[] = { 10, 20, 30, 40 };
v.assign(z+1, z+4);                 // v ist nun {20, 30, 40}

Godbolt Listing lst-0717-godb.cpp, https://godbolt.org/z/Yb4jEdaKj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Yb4jEdaKj 
vector<int> von{ 2,3,4 };
vector<int> nach{};
nach = von;                         // Zuweisung mit operator=, nun beide gleich

vector<int> abfluss{};
abfluss = std::move(von);           // Verschieben, nun ist 'von' leer
vector<int> v;
v.assign(4, 100);                   // v ist nun {100, 100, 100, 100}
v.assign(nach.begin(), nach.end()); // v ist nun {2,3,4}
int z[] = { 10, 20, 30, 40 };
v.assign(z+1, z+4);                 // v ist nun {20, 30, 40}

Listing 24.20: Mit »begin«, »end« und deren Verwandten erhalten Sie Iteratoren.

Book listing lst-0718-book.cpp:

// https://godbolt.org/z/6ahzhdjva 
vector vokale { 'A', 'e', 'i', 'o', 'u' };
const vector gerade { '0', '2', '4', '6', '8' };
auto it1 = vokale.begin();                 // vector<char>::iterator
*it1 = 'a';                                // '*it1' liefert 'char&' zurück
auto it2 = gerade.begin();                 // vector<char>::const_iterator
auto it3 = vokale.cbegin();                // erzwingt const_iterator
*i2 = '9'; *i3 = 'x';                      //                                          (ERR)  'const char&' ist nicht veränderbar
for(auto it=vokale.cbegin()+1; it!=vokale.cend(); ++it)
    { cout << *it; } cout << '\n';         // Ausgabe: eiou
for(auto it=vokale.crbegin()+1; it!=vokale.crend(); ++it) // ++ trotz reverse!
    { cout << *it; } cout << '\n';         // Ausgabe: oiea

Godbolt Listing lst-0718-godb.cpp, https://godbolt.org/z/6ahzhdjva:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6ahzhdjva 
vector vokale { 'A', 'e', 'i', 'o', 'u' };
const vector gerade { '0', '2', '4', '6', '8' };
auto it1 = vokale.begin();                 // vector<char>::iterator
*it1 = 'a';                                // '*it1' liefert 'char&' zurück
auto it2 = gerade.begin();                 // vector<char>::const_iterator
auto it3 = vokale.cbegin();                // erzwingt const_iterator
*i2 = '9'; *i3 = 'x';                      //                                          (ERR)  'const char&' ist nicht veränderbar
for(auto it=vokale.cbegin()+1; it!=vokale.cend(); ++it)
    { cout << *it; } cout << '\n';         // Ausgabe: eiou
for(auto it=vokale.crbegin()+1; it!=vokale.crend(); ++it) // ++ trotz reverse!
    { cout << *it; } cout << '\n';         // Ausgabe: oiea

Listing 24.21: Mit »vector«-Iteratoren können Sie wahlfrei rechnen.

Book listing lst-0719-book.cpp:

// https://godbolt.org/z/vMa8bPaob 
#include <vector>
#include <iostream>
#include <algorithm>                // ranges::sort
using std::vector; using std::cout;
double median(vector<int> daten) {  // kopiert
    std::ranges::sort(daten);       // C++20, sonst std::sort()
    auto it = daten.begin();
    auto sz = daten.size();
    if(sz==0) return 0;             // Sonderfall
    // Median ermitteln:
    auto m = (it+sz/2);             // ungefähr die Mitte
    if(sz%2 != 0) {                 // ungerade Anzahl Elemente
        return *m;
    } else {                        // gerade Anzahl Elemente
        return double(*m + *(m-1)) / 2;
    }
}
int main() {
    vector daten1 { 12, 22, 34, 10, 1, 99, 33 };
    cout << median(daten1) << '\n'; // 22
    vector daten2 { 30, 2, 80, 99, 31, 3 };
    cout << median(daten2) << '\n'; // 30.5
}

Godbolt Listing lst-0719-godb.cpp, https://godbolt.org/z/vMa8bPaob:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vMa8bPaob 
#include <vector>
#include <iostream>
#include <algorithm>                // ranges::sort
using std::vector; using std::cout;
double median(vector<int> daten) {  // kopiert
    std::ranges::sort(daten);       // C++20, sonst std::sort()
    auto it = daten.begin();
    auto sz = daten.size();
    if(sz==0) return 0;             // Sonderfall
    // Median ermitteln:
    auto m = (it+sz/2);             // ungefähr die Mitte
    if(sz%2 != 0) {                 // ungerade Anzahl Elemente
        return *m;
    } else {                        // gerade Anzahl Elemente
        return double(*m + *(m-1)) / 2;
    }
}
int main() {
    vector daten1 { 12, 22, 34, 10, 1, 99, 33 };
    cout << median(daten1) << '\n'; // 22
    vector daten2 { 30, 2, 80, 99, 31, 3 };
    cout << median(daten2) << '\n'; // 30.5
}

Listing 24.22: Der Normalfall ist Zugriff mit »[]«, weil Sie die Grenzen schon woanders überprüfen.

Book listing lst-0720-book.cpp:

// https://godbolt.org/z/aW3McGofx 
vector d{ 1, 2, 4, -1, 1, 2, -2 };
for(size_t idx=0; idx < d.size(); ) { // prüft vector-Grenze
    cout << d[idx] << ' ';            // zusätzliche Prüfung mit at nicht nötig
    idx += d[idx];                    // hier ebenso wenig
}
cout << '\n';
// Ausgabe: 1 2 -1 4 -2 1 2

Godbolt Listing lst-0720-godb.cpp, https://godbolt.org/z/aW3McGofx:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/aW3McGofx 
vector d{ 1, 2, 4, -1, 1, 2, -2 };
for(size_t idx=0; idx < d.size(); ) { // prüft vector-Grenze
    cout << d[idx] << ' ';            // zusätzliche Prüfung mit at nicht nötig
    idx += d[idx];                    // hier ebenso wenig
}
cout << '\n';
// Ausgabe: 1 2 -1 4 -2 1 2

Listing 24.23: Konstanter Container liefert konstante Referenz zurück.

Book listing lst-0721-book.cpp:

// https://godbolt.org/z/jGx51caTj 
#include <vector>
#include <iostream>
void printAndMore(const std::vector<int>& data) { // by-const-ref
    std::cout << data[0] << std::endl;
    data[0] = 666;  //                                          (ERR)  geht nicht, weil 'const int&'
}
int main() {
    std::vector zahlen {1,2,3};
    printAndMore(zahlen);
}

Godbolt Listing lst-0721-godb.cpp, https://godbolt.org/z/jGx51caTj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jGx51caTj 
#include <vector>
#include <iostream>
void printAndMore(const std::vector<int>& data) { // by-const-ref
    std::cout << data[0] << std::endl;
    data[0] = 666;  //                                          (ERR)  geht nicht, weil 'const int&'
}
int main() {
    std::vector zahlen {1,2,3};
    printAndMore(zahlen);
}

Listing 24.24: insert verschiebt hier alle Elemente um eins nach hinten.

Book listing lst-0722-book.cpp:

// https://godbolt.org/z/YhYs3z5Ex 
vector<string> autos{ "Diesel", "Benzin", "Super", "Gas" };
cout << autos[1] << '\n';             // Ausgabe: Benzin
autos.insert(autos.begin(), "Strom"); // verschiebt alles um eins nach hinten
cout << autos[1] << '\n';             // Ausgabe: Diesel

Godbolt Listing lst-0722-godb.cpp, https://godbolt.org/z/YhYs3z5Ex:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YhYs3z5Ex 
vector<string> autos{ "Diesel", "Benzin", "Super", "Gas" };
cout << autos[1] << '\n';             // Ausgabe: Benzin
autos.insert(autos.begin(), "Strom"); // verschiebt alles um eins nach hinten
cout << autos[1] << '\n';             // Ausgabe: Diesel

Listing 24.25: Verwenden Sie data() als Schnittstelle zu C.

Book listing lst-0723-book.cpp:

// https://godbolt.org/z/evse4x8zK 
#include <vector>
#include <iostream>
#include <cstdio> // fopen, fclose, fwrite, fread, remove
using namespace std;
ostream& operator<<(ostream&os, const vector<int>&data) {
    for(auto &e : data) os << e << ' '; return os;
}
static const char* FILENAME = "nums.dat";
int main() {
  const vector nums{10,11,22,34};
  { // Schreiben
    auto out = fopen(FILENAME, "wb"); // Datei mit C zum Schreiben öffnen
    if(out==nullptr) {
        cerr << "Fehler beim Oeffnen\n"; return -1;
    }
    auto ok = fwrite(nums.data(), sizeof(int), nums.size(), out);
    if(ok!=nums.size()) {
        cerr << "Fehler beim Schreiben\n"; return -1;
    }
    fclose(out); // In C muss man explizit schließen. Ehrlich.
  }
  vector<int> gelesen{};
  { // Lesen
    auto in = fopen(FILENAME, "rb"); // Datei mit C zum Lesen öffnen
    if(in==nullptr) {
        cerr << "Fehler beim Oeffnen\n"; return -1;
    }
    const size_t sz = 4; // angenommen, wir wissen, wir lesen 4 Elemente …
    gelesen.resize(sz);  // Platz schaffen für zu lesende Daten
    auto ok = fread(gelesen.data(), sizeof(int), sz, in);
    if(ok!=sz) {
        cerr << "Fehler beim Lesen\n"; return -1;
    }
    fclose(in);
  }
  { // Vergleichen
    cout << nums << '\n';    // 10 11 22 34
    cout << gelesen << '\n'; // 10 11 22 34
  }
  if(remove(FILENAME) == -1) {
      cerr << "Warning: Fehler beim Loeschen\n";
  }
}

Godbolt Listing lst-0723-godb.cpp, https://godbolt.org/z/evse4x8zK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/evse4x8zK 
#include <vector>
#include <iostream>
#include <cstdio> // fopen, fclose, fwrite, fread, remove
using namespace std;
ostream& operator<<(ostream&os, const vector<int>&data) {
    for(auto &e : data) os << e << ' '; return os;
}
static const char* FILENAME = "nums.dat";
int main() {
  const vector nums{10,11,22,34};
  { // Schreiben
    auto out = fopen(FILENAME, "wb"); // Datei mit C zum Schreiben öffnen
    if(out==nullptr) {
        cerr << "Fehler beim Oeffnen\n"; return -1;
    }
    auto ok = fwrite(nums.data(), sizeof(int), nums.size(), out);
    if(ok!=nums.size()) {
        cerr << "Fehler beim Schreiben\n"; return -1;
    }
    fclose(out); // In C muss man explizit schließen. Ehrlich.
  }
  vector<int> gelesen{};
  { // Lesen
    auto in = fopen(FILENAME, "rb"); // Datei mit C zum Lesen öffnen
    if(in==nullptr) {
        cerr << "Fehler beim Oeffnen\n"; return -1;
    }
    const size_t sz = 4; // angenommen, wir wissen, wir lesen 4 Elemente …
    gelesen.resize(sz);  // Platz schaffen für zu lesende Daten
    auto ok = fread(gelesen.data(), sizeof(int), sz, in);
    if(ok!=sz) {
        cerr << "Fehler beim Lesen\n"; return -1;
    }
    fclose(in);
  }
  { // Vergleichen
    cout << nums << '\n';    // 10 11 22 34
    cout << gelesen << '\n'; // 10 11 22 34
  }
  if(remove(FILENAME) == -1) {
      cerr << "Warning: Fehler beim Loeschen\n";
  }
}

Listing 24.26: So verwenden Sie span.

Book listing lst-0728-book.cpp:

// https://godbolt.org/z/h7jf4KM1q 
#include <vector>
#include <span>
#include <iostream>
using namespace std;
int sum(span<const int> bereich) { // C++20: span
   int sum = 0;
   for(auto e : bereich) {         // algorithm wäre besser …
    sum += e;
   }
   return sum;
}
int main() {
    vector data {1,2,3,4,5};
    cout << sum(data) << "\n";            // implizit Container zu span
    auto [b, e, sz] = make_tuple(begin(data), end(data), size(data));
    cout << sum(span{b,   sz-1}) << "\n"; // 1..4 (Iter, size)
    cout << sum(span{b+1, sz-1}) << "\n"; // 2..5 (Iter, size)
    cout << sum(span{b,   e-2}) << "\n";  // 1..3 (Iter, Iter)
    cout << sum(span{b+1, e-1}) << "\n";  // 2..4 (Iter, Iter)
    cout << sum(span{b+2, e  }) << "\n";  // 3..5 (Iter, Iter)
    return 0;
}

Godbolt Listing lst-0728-godb.cpp, https://godbolt.org/z/h7jf4KM1q:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h7jf4KM1q 
#include <vector>
#include <span>
#include <iostream>
using namespace std;
int sum(span<const int> bereich) { // C++20: span
   int sum = 0;
   for(auto e : bereich) {         // algorithm wäre besser …
    sum += e;
   }
   return sum;
}
int main() {
    vector data {1,2,3,4,5};
    cout << sum(data) << "\n";            // implizit Container zu span
    auto [b, e, sz] = make_tuple(begin(data), end(data), size(data));
    cout << sum(span{b,   sz-1}) << "\n"; // 1..4 (Iter, size)
    cout << sum(span{b+1, sz-1}) << "\n"; // 2..5 (Iter, size)
    cout << sum(span{b,   e-2}) << "\n";  // 1..3 (Iter, Iter)
    cout << sum(span{b+1, e-1}) << "\n";  // 2..4 (Iter, Iter)
    cout << sum(span{b+2, e  }) << "\n";  // 3..5 (Iter, Iter)
    return 0;
}

Listing 24.27: Dies sind span mit fester Größe.

Book listing lst-0731-book.cpp:

// https://godbolt.org/z/a3qqr1YPM 
int car[5]  {1,2,3,4,5};
span span_1 = car;          // direkt aus einem C-Array
array arr   {1,2,3,4,5};
span span_2 {arr};          // direkt aus einem std::array
vector vec  {1,2,3,4,5};
span<int,3> span_3 {vec};   // mit 'Extent' aus einem std::vector

Godbolt Listing lst-0731-godb.cpp, https://godbolt.org/z/a3qqr1YPM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a3qqr1YPM 
int car[5]  {1,2,3,4,5};
span span_1 = car;          // direkt aus einem C-Array
array arr   {1,2,3,4,5};
span span_2 {arr};          // direkt aus einem std::array
vector vec  {1,2,3,4,5};
span<int,3> span_3 {vec};   // mit 'Extent' aus einem std::vector

Listing 24.28: Durch eine »span« kann man auch schreiben.

Book listing lst-0733-book.cpp:

// https://godbolt.org/z/6Ez5GdozG 
#include <vector>
#include <span>
#include <iostream>
using namespace std;
void inc(span<int> span) {
   for(auto& e :span) {  // Referenz
     e += 1;             // schreiben
   }
}
int main() {
    vector data {1,2,3,4,5};
    span ganz{data};              //    1,2,3,4,5
    inc(ganz.first(3));           // -> 2,3,4,4,5
    inc(ganz.last(3));            // -> 2,3,5,5,6
    inc(ganz.last(4).first(3));   // -> 2,4,6,6,6
    inc(ganz.subspan(1,3));       // -> 2,5,7,7,6
    for(auto i: ganz) cout << i << ' '; cout << '\n'; // Ausgabe: 2 5 7 7 6
    return 0;
}

Godbolt Listing lst-0733-godb.cpp, https://godbolt.org/z/6Ez5GdozG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6Ez5GdozG 
#include <vector>
#include <span>
#include <iostream>
using namespace std;
void inc(span<int> span) {
   for(auto& e :span) {  // Referenz
     e += 1;             // schreiben
   }
}
int main() {
    vector data {1,2,3,4,5};
    span ganz{data};              //    1,2,3,4,5
    inc(ganz.first(3));           // -> 2,3,4,4,5
    inc(ganz.last(3));            // -> 2,3,5,5,6
    inc(ganz.last(4).first(3));   // -> 2,4,6,6,6
    inc(ganz.subspan(1,3));       // -> 2,5,7,7,6
    for(auto i: ganz) cout << i << ' '; cout << '\n'; // Ausgabe: 2 5 7 7 6
    return 0;
}

Listing 24.29: So funktioniert die in C++23 hinzugekommene »mdspan«.

Book listing lst-0734-book.cpp:

// https://godbolt.org/z/n8jn7v5vb 
#include <mdspan>
#include <iostream>
#include <vector>
using namespace std;
int main() {
    // 1D: 12 Elemente
    vector v{1,2,3,4,5,6,7,8,9,10,11,12};
    // 2D: als 2 Zeilen mit je 6 ints
    auto ms2 = mdspan(v.data(), 2, 6);
    // 3D: als Quader mit 2 Ebenen, 3 Reihen, 2 Spalten
    auto ms3 = mdspan(v.data(), 2, 3, 2);
    // via 2D-Ansicht schreiben
    for (auto i = 0; i != ms2.extent(0); ++i)
      for (auto j = 0; j != ms2.extent(1); ++j)
        ms2[i, j] = i * 100 + j;  // schreiben via mehrdimensionalen Index
    // via 3D-Ansicht lesen
    for (auto i = 0; i != ms3.extent(0); ++i) {
      cout << "Ebene " << i << ":\n";
      for (auto j = 0; j != ms3.extent(1); ++j) {
        for (auto k = 0; k != ms3.extent(2); ++k)
          cout << " " << ms3[i, j, k];  // lesen via mehrdimensionalen Index
        cout << '\n';
      }
    }
    // Ausgabe: Ebene 0: 0 1, 2 3, 4 5, Ebene 1: 100 101, 102 103, 104 105
}

Godbolt Listing lst-0734-godb.cpp, https://godbolt.org/z/n8jn7v5vb:

//#(compile) c++; compiler:gsnapshot; options:"-std=c++23"; libs:-
// https://godbolt.org/z/n8jn7v5vb 
#include <mdspan>
#include <iostream>
#include <vector>
using namespace std;
int main() {
    // 1D: 12 Elemente
    vector v{1,2,3,4,5,6,7,8,9,10,11,12};
    // 2D: als 2 Zeilen mit je 6 ints
    auto ms2 = mdspan(v.data(), 2, 6);
    // 3D: als Quader mit 2 Ebenen, 3 Reihen, 2 Spalten
    auto ms3 = mdspan(v.data(), 2, 3, 2);
    // via 2D-Ansicht schreiben
    for (auto i = 0; i != ms2.extent(0); ++i)
      for (auto j = 0; j != ms2.extent(1); ++j)
        ms2[i, j] = i * 100 + j;  // schreiben via mehrdimensionalen Index
    // via 3D-Ansicht lesen
    for (auto i = 0; i != ms3.extent(0); ++i) {
      cout << "Ebene " << i << ":\n";
      for (auto j = 0; j != ms3.extent(1); ++j) {
        for (auto k = 0; k != ms3.extent(2); ++k)
          cout << " " << ms3[i, j, k];  // lesen via mehrdimensionalen Index
        cout << '\n';
      }
    }
    // Ausgabe: Ebene 0: 0 1, 2 3, 4 5, Ebene 1: 100 101, 102 103, 104 105
}

Listing 24.30: Typischerweise fügen Sie am Ende bei vector an.

Book listing lst-0735-book.cpp:

// https://godbolt.org/z/P6MrKfaj9 
#include <vector>
#include <string>
struct Praesident {
  std::string name_; int jahr_;
  Praesident(std::string name,  int jahr)    // name ist by Value
    : name_{std::move(name)}, jahr_{jahr}    // move spart hier eine weitere Kopie
    { }
};
int main() {
    using namespace std; // Stringliterale ermöglichen
    vector<Praesident> praesidenten{};
    praesidenten.emplace_back("Heuss"s, 1949);
    praesidenten.emplace_back("Luebke"s, 1959);
    praesidenten.emplace_back("Heinemann"s, 1969);
    // …
    vector<int> v{};
    v.reserve(100);
    for(int idx = 0; idx < 100; ++idx)
        v.push_back(idx);
    // …
}

Godbolt Listing lst-0735-godb.cpp, https://godbolt.org/z/P6MrKfaj9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/P6MrKfaj9 
#include <vector>
#include <string>
struct Praesident {
  std::string name_; int jahr_;
  Praesident(std::string name,  int jahr)    // name ist by Value
    : name_{std::move(name)}, jahr_{jahr}    // move spart hier eine weitere Kopie
    { }
};
int main() {
    using namespace std; // Stringliterale ermöglichen
    vector<Praesident> praesidenten{};
    praesidenten.emplace_back("Heuss"s, 1949);
    praesidenten.emplace_back("Luebke"s, 1959);
    praesidenten.emplace_back("Heinemann"s, 1969);
    // …
    vector<int> v{};
    v.reserve(100);
    for(int idx = 0; idx < 100; ++idx)
        v.push_back(idx);
    // …
}

GodboltId:6836bdczd

Book listing lst-0738-book.cpp:

// https://godbolt.org/z/6836bdczd 
std::vector v{ 1, 2, 3, 4, 5, 6 };
for(auto it=v.begin(); it!=v.end(); ++it) {
  it = v.erase(it);
}
// Hier ist v: { 2, 4, 6 }

Godbolt Listing lst-0738-godb.cpp, https://godbolt.org/z/6836bdczd:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6836bdczd 
std::vector v{ 1, 2, 3, 4, 5, 6 };
for(auto it=v.begin(); it!=v.end(); ++it) {
  it = v.erase(it);
}
// Hier ist v: { 2, 4, 6 }

Listing 24.31: erase mit zwei Parametern löscht einen ganzen Bereich.

Book listing lst-0739-book.cpp:

// https://godbolt.org/z/fe8bev9Y9 
std::vector v{ 1, 2, 3, 4, 5, 6 };
v.erase(v.begin()+2, v.begin()+5); // v ist nun {1, 6}
v.erase(v.begin(), v.end());       // löscht den Rest

Godbolt Listing lst-0739-godb.cpp, https://godbolt.org/z/fe8bev9Y9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fe8bev9Y9 
std::vector v{ 1, 2, 3, 4, 5, 6 };
v.erase(v.begin()+2, v.begin()+5); // v ist nun {1, 6}
v.erase(v.begin(), v.end());       // löscht den Rest

Listing 24.32: Operationen rund um Größe und Kapazität von »vector«.

Book listing lst-0741-book.cpp:

// https://godbolt.org/z/xYsherrjs 
#include <vector>
#include <iostream>
#include <format> // C++20
using namespace std;
ostream& operator<<(ostream&os, const vector<int> &vec) {
  for(auto &elem : vec) { os << elem << ' '; } return os;
}
int main() {
  vector<int> data {};     // erzeugt einen leeren vector
  data.reserve(3);         // Platz für 3 Elemente
  cout << format("{}/{}\n", data.size(), data.capacity()); // 0/3
  data.push_back(111);     // ein Element hinzufügen
  data.resize(3);          // Größe verändern; hier fügt es neue Elemente an
  data.push_back(999);     // noch ein Element hinzufügen
  cout << format("{}/{}\n", data.size(), data.capacity()); // 4/6
  cout << data << '\n';    // 111, 0, 0, 999
  data.push_back(333);     // noch ein Element anfügen
  cout << data << '\n';    // 111, 0, 0, 999, 333
  data.reserve(1);         // nichts passiert, denn capacity() > 1
  data.resize(3);          // schrumpfen; Elemente werden entfernt
  cout << data << '\n';    // 111, 0, 0
  cout << format("{}/{}\n", data.size(), data.capacity()); // 3/6
  data.resize(6, 44);      // noch mal vergrößern, mit 44en auffüllen
  cout << data << '\n';    // 111, 0, 0, 44, 44, 44
}

Godbolt Listing lst-0741-godb.cpp, https://godbolt.org/z/xYsherrjs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xYsherrjs 
#include <vector>
#include <iostream>
#include <format> // C++20
using namespace std;
ostream& operator<<(ostream&os, const vector<int> &vec) {
  for(auto &elem : vec) { os << elem << ' '; } return os;
}
int main() {
  vector<int> data {};     // erzeugt einen leeren vector
  data.reserve(3);         // Platz für 3 Elemente
  cout << format("{}/{}\n", data.size(), data.capacity()); // 0/3
  data.push_back(111);     // ein Element hinzufügen
  data.resize(3);          // Größe verändern; hier fügt es neue Elemente an
  data.push_back(999);     // noch ein Element hinzufügen
  cout << format("{}/{}\n", data.size(), data.capacity()); // 4/6
  cout << data << '\n';    // 111, 0, 0, 999
  data.push_back(333);     // noch ein Element anfügen
  cout << data << '\n';    // 111, 0, 0, 999, 333
  data.reserve(1);         // nichts passiert, denn capacity() > 1
  data.resize(3);          // schrumpfen; Elemente werden entfernt
  cout << data << '\n';    // 111, 0, 0
  cout << format("{}/{}\n", data.size(), data.capacity()); // 3/6
  data.resize(6, 44);      // noch mal vergrößern, mit 44en auffüllen
  cout << data << '\n';    // 111, 0, 0, 44, 44, 44
}

GodboltId:Y1W8WfxYn

Book listing lst-0742-book.cpp:

// https://godbolt.org/z/Y1W8WfxYn 
#include <array>
void berechne(const std::array<int,4>& data) { /* ... */ }
void berechne(const std::array<int,5>& data) { /* ... */ }

Godbolt Listing lst-0742-godb.cpp, https://godbolt.org/z/Y1W8WfxYn:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y1W8WfxYn 
#include <array>
void berechne(const std::array<int,4>& data) { /* ... */ }
void berechne(const std::array<int,5>& data) { /* ... */ }

Listing 24.33: Unterschiedliche »arrays« als Parameter benötigen Templateprogrammierung.

Book listing lst-0743-book.cpp:

// https://godbolt.org/z/nqbKT9GEa 
#include <array>
#include <numeric> // accumulate
#include <iostream>
template<size_t SZ>
int sumSz(const std::array<int,SZ>& data) {
    int result = 0;
    for(auto i=0uz; i<SZ; ++i)           // uz ist das Suffix für size_t seit C++23
        result += data[i];
    return result;
}
template<typename Elem, size_t SZ>
Elem sumElem(const std::array<Elem,SZ>& data) {
    Elem result {0};
    for(auto i=0uz; i<SZ; ++i)
        result += data[i];
    return result;
}
// C++20-Concept input_iterator, sonst typename
template<std::input_iterator It>
int sumIt(It begin, It end) {
    return std::accumulate(begin, end, 0);
}
int sumAuto(std::input_iterator auto begin, std::input_iterator auto end) {
    return std::accumulate(begin, end, 0);
}
// abgekürztes funktionstemplate mit auto
int main() {
   using namespace std;
   array<int,4> a4 { 1, 2, 5, 8 };
   cout << sumSz<4>(a4) << '\n';                  // Ausgabe: 16
   array<int,5> a5 { 1, -5, 3, 7, 2 };
   cout << sumElem(a5) << '\n';                   // Ausgabe: 8
   array<int,6> a6 { 1,2,3, 4,5,6 };
   cout << sumIt(a6.begin(), a6.end()) << '\n';   // Ausgabe: 21
   array a7 { 1,2,3, 4,5,6, 7 };                  // array<int,7>
   cout << sumIt(a7.begin(), a7.end()) << '\n';   // Ausgabe: 28
   cout << sumAuto(a7.begin(), a7.end()) << '\n'; // Ausgabe: 28
}

Godbolt Listing lst-0743-godb.cpp, https://godbolt.org/z/nqbKT9GEa:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nqbKT9GEa 
#include <array>
#include <numeric> // accumulate
#include <iostream>
template<size_t SZ>
int sumSz(const std::array<int,SZ>& data) {
    int result = 0;
    for(auto i=0uz; i<SZ; ++i)           // uz ist das Suffix für size_t seit C++23
        result += data[i];
    return result;
}
template<typename Elem, size_t SZ>
Elem sumElem(const std::array<Elem,SZ>& data) {
    Elem result {0};
    for(auto i=0uz; i<SZ; ++i)
        result += data[i];
    return result;
}
// C++20-Concept input_iterator, sonst typename
template<std::input_iterator It>
int sumIt(It begin, It end) {
    return std::accumulate(begin, end, 0);
}
int sumAuto(std::input_iterator auto begin, std::input_iterator auto end) {
    return std::accumulate(begin, end, 0);
}
// abgekürztes funktionstemplate mit auto
int main() {
   using namespace std;
   array<int,4> a4 { 1, 2, 5, 8 };
   cout << sumSz<4>(a4) << '\n';                  // Ausgabe: 16
   array<int,5> a5 { 1, -5, 3, 7, 2 };
   cout << sumElem(a5) << '\n';                   // Ausgabe: 8
   array<int,6> a6 { 1,2,3, 4,5,6 };
   cout << sumIt(a6.begin(), a6.end()) << '\n';   // Ausgabe: 21
   array a7 { 1,2,3, 4,5,6, 7 };                  // array<int,7>
   cout << sumIt(a7.begin(), a7.end()) << '\n';   // Ausgabe: 28
   cout << sumAuto(a7.begin(), a7.end()) << '\n'; // Ausgabe: 28
}

Listing 24.34: Schablone für die Beispiellistings dieses Abschnitts zu »array«

Book listing lst-0744-book.cpp:

// https://godbolt.org/z/PrM4fGcWo 
#include <array>
#include <iostream>
using std::array; using std::cout;
template<typename Elem, size_t SZ>
std::ostream& operator<<(std::ostream&os, const array<Elem,SZ>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os;
}
int main() {
   // Beispielcode hier
}

Godbolt Listing lst-0744-godb.cpp, https://godbolt.org/z/PrM4fGcWo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PrM4fGcWo 
#include <array>
#include <iostream>
using std::array; using std::cout;
template<typename Elem, size_t SZ>
std::ostream& operator<<(std::ostream&os, const array<Elem,SZ>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os;
}
int main() {
   // Beispielcode hier
}

Listing 24.36: »array« unterstützt »get« von »tuple«.

Book listing lst-0745-book.cpp:

// https://godbolt.org/z/KrbTrx1aG 
array<int,5> data{ 10, 11, 12, 13, 14};
cout << std::get<2>(data) << '\n'; // 12

Godbolt Listing lst-0745-godb.cpp, https://godbolt.org/z/KrbTrx1aG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KrbTrx1aG 
array<int,5> data{ 10, 11, 12, 13, 14};
cout << std::get<2>(data) << '\n'; // 12

Listing 24.37: Ein Array unterstützt strukturiertes Binden.

Book listing lst-0746-book.cpp:

// https://godbolt.org/z/h6nrPYWfM 
#include <array>
#include <iostream>
int main() {
    std::array ports { 80, 443  };          // array<int>
    auto [ http, https ] = ports;           // deklariert Variablen und bindet sie
    std::cout << http << " " << https << "\n";
    auto const& [ rhttp, rhttps ] = ports;  // Referenz und const sind möglich
    std::cout << rhttp << " " << rhttps << "\n";
}

Godbolt Listing lst-0746-godb.cpp, https://godbolt.org/z/h6nrPYWfM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h6nrPYWfM 
#include <array>
#include <iostream>
int main() {
    std::array ports { 80, 443  };          // array<int>
    auto [ http, https ] = ports;           // deklariert Variablen und bindet sie
    std::cout << http << " " << https << "\n";
    auto const& [ rhttp, rhttps ] = ports;  // Referenz und const sind möglich
    std::cout << rhttp << " " << rhttps << "\n";
}

Listing 24.38: Arrays können Sie lexikografisch vergleichen.

Book listing lst-0747-book.cpp:

// https://godbolt.org/z/n16WYf58h 
template<typename E, size_t SZ>
void alle(const array<int,4>& a, const array<int,4>& b) { // absichtlich array& 
                                                          // als Argumente
     cout << "{"<<a<<"} verglichen mit {"<<b<<"} ist "
       << (a < b ? "<, " : "")
       << (a <= b ? "<=, " : "")
       << (a > b ? ">, " : "")
       << (a >= b ? ">=, " : "")
       << (a == b ? "==, " : "")
       << (a != b ? "!=, " : "")
       << '\n';
}
int main() {
    array a{10,10,10,10};
    array b{20, 5, 5, 5};
    array c{10,10,5,21};
    array d{10,10,10,10};
    cout << (a < b ? "kleiner\n" : "nicht kleiner\n"); // "kleiner", weil 10 < 20
    cout << (a < c ? "kleiner\n" : "nicht kleiner\n"); // "nicht …", weil nicht 10 < 5
    cout << (a == d ? "gleich\n" : "nicht gleich\n");  // "gleich", weil alles 10
    for(auto &x : {a,b,c}) {
        for(auto &y : {a,b,c}) {
            alle(x,y);
        }
    }
}

Godbolt Listing lst-0747-godb.cpp, https://godbolt.org/z/n16WYf58h:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n16WYf58h 
template<typename E, size_t SZ>
void alle(const array<int,4>& a, const array<int,4>& b) { // absichtlich array& 
                                                          // als Argumente
     cout << "{"<<a<<"} verglichen mit {"<<b<<"} ist "
       << (a < b ? "<, " : "")
       << (a <= b ? "<=, " : "")
       << (a > b ? ">, " : "")
       << (a >= b ? ">=, " : "")
       << (a == b ? "==, " : "")
       << (a != b ? "!=, " : "")
       << '\n';
}
int main() {
    array a{10,10,10,10};
    array b{20, 5, 5, 5};
    array c{10,10,5,21};
    array d{10,10,10,10};
    cout << (a < b ? "kleiner\n" : "nicht kleiner\n"); // "kleiner", weil 10 < 20
    cout << (a < c ? "kleiner\n" : "nicht kleiner\n"); // "nicht …", weil nicht 10 < 5
    cout << (a == d ? "gleich\n" : "nicht gleich\n");  // "gleich", weil alles 10
    for(auto &x : {a,b,c}) {
        for(auto &y : {a,b,c}) {
            alle(x,y);
        }
    }
}

Listing 24.39: Wir entfernen paarweise vorne und hinten und vergleichen.

Book listing lst-0748-book.cpp:

// https://godbolt.org/z/rc1f3Yd9r 
#include <deque>
#include <iostream>
#include <string>
#include <cctype>   // toupper
#include <iomanip>  // boolalpha
using namespace std;
bool isPalindrome(string_view word) {
    // von beiden Enden gleichzeitig prüfen
    deque<char> deq{};
    for(char ch : word) {
        deq.push_back(toupper(ch));   // Großbuchstaben
    }
    auto ok = true;
    while(deq.size()>1 && ok) {
       if(deq.front() != deq.back()) {
           ok = false;
       }
       deq.pop_front();               // Hallo deque!
       deq.pop_back();
    }
    return ok;
}
int main() {
    cout << boolalpha; // Drucke 'true' und 'false' statt '1' und '0'
    cout << isPalindrome("Abrakadabra") << '\n';   // false
    cout << isPalindrome("Kajak") << '\n';         // true
    cout << isPalindrome("Lagerregal") << '\n';    // true
    cout << isPalindrome("Reliefpfeiler") << '\n'; // true
    cout << isPalindrome("Rentner") << '\n';       // true
    cout << isPalindrome("") << '\n';              // true
}

Godbolt Listing lst-0748-godb.cpp, https://godbolt.org/z/rc1f3Yd9r:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rc1f3Yd9r 
#include <deque>
#include <iostream>
#include <string>
#include <cctype>   // toupper
#include <iomanip>  // boolalpha
using namespace std;
bool isPalindrome(string_view word) {
    // von beiden Enden gleichzeitig prüfen
    deque<char> deq{};
    for(char ch : word) {
        deq.push_back(toupper(ch));   // Großbuchstaben
    }
    auto ok = true;
    while(deq.size()>1 && ok) {
       if(deq.front() != deq.back()) {
           ok = false;
       }
       deq.pop_front();               // Hallo deque!
       deq.pop_back();
    }
    return ok;
}
int main() {
    cout << boolalpha; // Drucke 'true' und 'false' statt '1' und '0'
    cout << isPalindrome("Abrakadabra") << '\n';   // false
    cout << isPalindrome("Kajak") << '\n';         // true
    cout << isPalindrome("Lagerregal") << '\n';    // true
    cout << isPalindrome("Reliefpfeiler") << '\n'; // true
    cout << isPalindrome("Rentner") << '\n';       // true
    cout << isPalindrome("") << '\n';              // true
}

Listing 24.40: Was die »deque« so alles kann!

Book listing lst-0750-book.cpp:

// https://godbolt.org/z/7P1Ef7jj4 
#include <deque>
#include <iostream>
#include <iterator>  // ostream_iterator
#include <algorithm> // copy
using namespace std;
ostream& operator<<=(ostream& os, int val) { return os<<val<<'\n'; }
int main() {
    deque d{ 4, 6 };           // deque<int> mit Elementen erzeugen
    // Einfügen
    d.push_front(3);           // am Kopf: effizient
    d.insert(d.begin()+2, 5);  // mittendrin: langsam
    d.push_back(7);            // am Ende: effizient
    // Zugriff
    cout <<= d.front();        // vom Kopf: effizient
    cout <<= d[3];             // mittendrin: effizient
    cout <<= d.back();         // vom Ende: effizient
    // Größe
    cout <<= d.size();         // Größe lesen
    d.resize(4);               // Größe kappen (oder erweitern)
    // Iteratoren
    copy(d.begin(), d.end(), ostream_iterator<int>(cout, " "));
    cout << '\n';              // Ausgabe: 3 4 5 6
    // Entfernen
    d.pop_front();             // am Kopf: effizient
    d.erase(d.begin()+1);      // mittendrin: langsam
    d.pop_back();              // am Ende: effizient
    d.clear();                 // leeren
}

Godbolt Listing lst-0750-godb.cpp, https://godbolt.org/z/7P1Ef7jj4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7P1Ef7jj4 
#include <deque>
#include <iostream>
#include <iterator>  // ostream_iterator
#include <algorithm> // copy
using namespace std;
ostream& operator<<=(ostream& os, int val) { return os<<val<<'\n'; }
int main() {
    deque d{ 4, 6 };           // deque<int> mit Elementen erzeugen
    // Einfügen
    d.push_front(3);           // am Kopf: effizient
    d.insert(d.begin()+2, 5);  // mittendrin: langsam
    d.push_back(7);            // am Ende: effizient
    // Zugriff
    cout <<= d.front();        // vom Kopf: effizient
    cout <<= d[3];             // mittendrin: effizient
    cout <<= d.back();         // vom Ende: effizient
    // Größe
    cout <<= d.size();         // Größe lesen
    d.resize(4);               // Größe kappen (oder erweitern)
    // Iteratoren
    copy(d.begin(), d.end(), ostream_iterator<int>(cout, " "));
    cout << '\n';              // Ausgabe: 3 4 5 6
    // Entfernen
    d.pop_front();             // am Kopf: effizient
    d.erase(d.begin()+1);      // mittendrin: langsam
    d.pop_back();              // am Ende: effizient
    d.clear();                 // leeren
}

Listing 24.41: »splice« ist die Spezialität von »list« und verbindet zwei Listen effizient.

Book listing lst-0751-book.cpp:

// https://godbolt.org/z/so5Gebb4M 
#include <list>
#include <iostream>
using std::list; using std::cout; using std::ostream;

ostream& operator<<=(ostream&os, const list<int> &data)
    { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main() {
    list numa { 1, 3, 5, 7, 9 };
    list numb { 2, 4, 6, 8 };
    auto wo = numa.end();
    numa.splice(wo, numb); // transferieren in O(1)
    cout <<= numa; // Ausgabe: 1 3 5 7 9 2 4 6 8
    cout <<= numb; // Ausgabe: (keine)
    numa.sort();   // sort als Methode, nicht aus <algorithm>
    cout <<= numa; // Ausgabe: 1 2 3 4 5 6 7 8 9
}

Godbolt Listing lst-0751-godb.cpp, https://godbolt.org/z/so5Gebb4M:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/so5Gebb4M 
#include <list>
#include <iostream>
using std::list; using std::cout; using std::ostream;

ostream& operator<<=(ostream&os, const list<int> &data)
    { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main() {
    list numa { 1, 3, 5, 7, 9 };
    list numb { 2, 4, 6, 8 };
    auto wo = numa.end();
    numa.splice(wo, numb); // transferieren in O(1)
    cout <<= numa; // Ausgabe: 1 3 5 7 9 2 4 6 8
    cout <<= numb; // Ausgabe: (keine)
    numa.sort();   // sort als Methode, nicht aus <algorithm>
    cout <<= numa; // Ausgabe: 1 2 3 4 5 6 7 8 9
}

Listing 24.42: »before_begin« können Sie als Argument für »insert_after« nehmen.

Book listing lst-0752-book.cpp:

// https://godbolt.org/z/9b9fY4Mve 
#include <iostream>
#include <forward_list>
int main()     {
    std::forward_list mylist = {20, 30, 40, 50};
    mylist.insert_after(mylist.before_begin(), 11 );
    for (int& x: mylist) std::cout << ' ' << x; // Ausgabe: 11 20 30 40 50
    std::cout << '\n';
}

Godbolt Listing lst-0752-godb.cpp, https://godbolt.org/z/9b9fY4Mve:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9b9fY4Mve 
#include <iostream>
#include <forward_list>
int main()     {
    std::forward_list mylist = {20, 30, 40, 50};
    mylist.insert_after(mylist.before_begin(), 11 );
    for (int& x: mylist) std::cout << ' ' << x; // Ausgabe: 11 20 30 40 50
    std::cout << '\n';
}

Listing 24.43: »erase_after« kann einen Bereich von Elementen löschen.

Book listing lst-0753-book.cpp:

// https://godbolt.org/z/ajn3haEcY 
#include <forward_list>
#include <iostream>
#include <iterator> // next
using std::cout; using std::forward_list; using std::ostream;
ostream& operator<<=(ostream&os, const forward_list<int> &data)
    { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main()     {
    forward_list zahlen {40, 50, 60, 70};
    cout <<= zahlen;                        // Ausgabe: 40 50 60 70
    zahlen.insert_after(zahlen.before_begin(), {10, 20, 30});
    cout <<= zahlen;                        // Ausgabe: 10 20 30 40 50 60 70
    auto wo = std::next(zahlen.begin(), 2); // zwei Elemente weiter
    auto bis = std::next(wo, 3);            // drei Elemente nach wo
    zahlen.erase_after(wo, bis);
    cout <<= zahlen;                        // Ausgabe: 10 20 30 60 70
}

Godbolt Listing lst-0753-godb.cpp, https://godbolt.org/z/ajn3haEcY:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ajn3haEcY 
#include <forward_list>
#include <iostream>
#include <iterator> // next
using std::cout; using std::forward_list; using std::ostream;
ostream& operator<<=(ostream&os, const forward_list<int> &data)
    { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main()     {
    forward_list zahlen {40, 50, 60, 70};
    cout <<= zahlen;                        // Ausgabe: 40 50 60 70
    zahlen.insert_after(zahlen.before_begin(), {10, 20, 30});
    cout <<= zahlen;                        // Ausgabe: 10 20 30 40 50 60 70
    auto wo = std::next(zahlen.begin(), 2); // zwei Elemente weiter
    auto bis = std::next(wo, 3);            // drei Elemente nach wo
    zahlen.erase_after(wo, bis);
    cout <<= zahlen;                        // Ausgabe: 10 20 30 60 70
}

Listing 24.44: »splice_after« kann sehr effizient Listen zusammenfügen.

Book listing lst-0754-book.cpp:

// https://godbolt.org/z/Ka47W5Wjh 
#include <forward_list>
#include <iostream>
using std::cout; using std::forward_list; using std::ostream;

ostream& operator<<=(ostream&os, const forward_list<int> &data)
  { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main() {
  {
    forward_list fw1 {10, 20, 30, 40};
    forward_list fw2 {5, 6, 7, 8};
    fw1.splice_after(fw1.begin(), fw2);  // transferiert alles
    cout <<= fw1;                 // Ausgabe: 10 5 6 7 8 20 30 40
    cout <<= fw2;                 // Ausgabe:
  }
  {
    forward_list fw1 {10, 20, 30, 40};
    forward_list fw2 {5, 6, 7, 8};
    // ein Element übrig:
    fw1.splice_after(fw1.begin(), fw2,fw2.begin(),fw2.end());
    cout <<= fw1;                 // Ausgabe: 10 6 7 8 20 30 40
    cout <<= fw2;                 // Ausgabe: 5
  }
}

Godbolt Listing lst-0754-godb.cpp, https://godbolt.org/z/Ka47W5Wjh:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ka47W5Wjh 
#include <forward_list>
#include <iostream>
using std::cout; using std::forward_list; using std::ostream;

ostream& operator<<=(ostream&os, const forward_list<int> &data)
  { for(auto &e:data) os<<e<<' '; return os<<'\n'; }

int main() {
  {
    forward_list fw1 {10, 20, 30, 40};
    forward_list fw2 {5, 6, 7, 8};
    fw1.splice_after(fw1.begin(), fw2);  // transferiert alles
    cout <<= fw1;                 // Ausgabe: 10 5 6 7 8 20 30 40
    cout <<= fw2;                 // Ausgabe:
  }
  {
    forward_list fw1 {10, 20, 30, 40};
    forward_list fw2 {5, 6, 7, 8};
    // ein Element übrig:
    fw1.splice_after(fw1.begin(), fw2,fw2.begin(),fw2.end());
    cout <<= fw1;                 // Ausgabe: 10 6 7 8 20 30 40
    cout <<= fw2;                 // Ausgabe: 5
  }
}

Listing 24.45: Dies ist die Schablone für die Beispiellistings dieses Abschnitts zu »set«.

Book listing lst-0755-book.cpp:

// https://godbolt.org/z/h51oT7r3h 
#include <set>
#include <iostream>
using std::set; using std::cout;
template<typename Elem, typename Comp>
std::ostream& operator<<=(std::ostream&os, const set<Elem,Comp>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Godbolt Listing lst-0755-godb.cpp, https://godbolt.org/z/h51oT7r3h:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h51oT7r3h 
#include <set>
#include <iostream>
using std::set; using std::cout;
template<typename Elem, typename Comp>
std::ostream& operator<<=(std::ostream&os, const set<Elem,Comp>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Listing 24.46: Wenn Sie die Vergleichsoperation falsch definieren, funktioniert »set« nicht mehr.

Book listing lst-0757-book.cpp:

// https://godbolt.org/z/GbPsraKxa 
using std::cout; using std::ostream; using std::set;
auto vergl = [](auto e, auto f) { return e <= f; }; //                                          (ERR)  ungültig definiert!
std::set<int,decltype(vergl)> data(vergl);
data.insert({ 9,5,7,2,3,6,8 });
cout <<= data;                     // Ausgabe mit Glück: 2 3 5 6 7 8 9
auto wo = data.find(7);
if(wo != data.end()) {
    cout << "hab es: " << *wo << '\n';
} else {
    cout << "weg isses!" << '\n'; // wahrscheinlich landen Sie hier
}

Godbolt Listing lst-0757-godb.cpp, https://godbolt.org/z/GbPsraKxa:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GbPsraKxa 
using std::cout; using std::ostream; using std::set;
auto vergl = [](auto e, auto f) { return e <= f; }; //                                          (ERR)  ungültig definiert!
std::set<int,decltype(vergl)> data(vergl);
data.insert({ 9,5,7,2,3,6,8 });
cout <<= data;                     // Ausgabe mit Glück: 2 3 5 6 7 8 9
auto wo = data.find(7);
if(wo != data.end()) {
    cout << "hab es: " << *wo << '\n';
} else {
    cout << "weg isses!" << '\n'; // wahrscheinlich landen Sie hier
}

Listing 24.47: Die Vergleichsoperation darf Elemente zusammenfassen.

Book listing lst-0758-book.cpp:

// https://godbolt.org/z/MeGnEez15 
auto vergl = [](auto e, auto f) {return e/10<f/10;}; // zusammenfassen ist okay
std::set<int,decltype(vergl)> data(vergl);
data.insert({ 14,23,56,71 });
cout <<= data;                         // Ausgabe: 14 23 56 71
auto wo = data.find(29);               // 29 findet nun auch die 23
if(wo != data.end()) {
    cout << "hab es: " << *wo << '\n'; // Ausgabe: hab es: 23
}
data.insert(79);                       // nichts passiert, denn 71 ist schon drin
cout <<= data;                         // Ausgabe: 14 23 56 71

Godbolt Listing lst-0758-godb.cpp, https://godbolt.org/z/MeGnEez15:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MeGnEez15 
auto vergl = [](auto e, auto f) {return e/10<f/10;}; // zusammenfassen ist okay
std::set<int,decltype(vergl)> data(vergl);
data.insert({ 14,23,56,71 });
cout <<= data;                         // Ausgabe: 14 23 56 71
auto wo = data.find(29);               // 29 findet nun auch die 23
if(wo != data.end()) {
    cout << "hab es: " << *wo << '\n'; // Ausgabe: hab es: 23
}
data.insert(79);                       // nichts passiert, denn 71 ist schon drin
cout <<= data;                         // Ausgabe: 14 23 56 71

Listing 24.48: Ein eigener Spaceship-Operator für die »set«-Kompatibilität

Book listing lst-0759-book.cpp:

// https://godbolt.org/z/a3cnTn3zz 
#include <iostream>
#include <set>
#include <string>
struct Dwarf {
  std::string name;
  int height;
  auto operator<=>(const Dwarf& other) const {
    return height <=> other.height;
  }
};
int main() {
  std::set<Dwarf> dwarves {
    {"Thorin", 140}, {"Balin", 136}, {"Kili", 138},
    {"Dwalin", 139}, {"Oin", 135},   {"Gloin", 137},
  };
  for(auto &d: dwarves) {
    std::cout << d.name << ' ';
  } // Ausgabe: Oin Balin Kili Gloin Dwalin Thorin
}

Godbolt Listing lst-0759-godb.cpp, https://godbolt.org/z/a3cnTn3zz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a3cnTn3zz 
#include <iostream>
#include <set>
#include <string>
struct Dwarf {
  std::string name;
  int height;
  auto operator<=>(const Dwarf& other) const {
    return height <=> other.height;
  }
};
int main() {
  std::set<Dwarf> dwarves {
    {"Thorin", 140}, {"Balin", 136}, {"Kili", 138},
    {"Dwalin", 139}, {"Oin", 135},   {"Gloin", 137},
  };
  for(auto &d: dwarves) {
    std::cout << d.name << ' ';
  } // Ausgabe: Oin Balin Kili Gloin Dwalin Thorin
}

Listing 24.49: Es gibt verschiedene Möglichkeiten, einen Comparator anzugeben.

Book listing lst-0761-book.cpp:

// https://godbolt.org/z/1Eoh9aoas 
#include <set>
#include <functional> // function
using std::set; using std::function; using std::initializer_list;
bool fcompZehner(int a, int b) { return a%10 < b%10; }
struct Fuenfer {
    bool operator()(int a, int b) const { return a%5 < b% 5; }
};

int main() {
    // Funktor
    set<int, Fuenfer> ff1;
    ff1.insert(5);
    set ff2({5}, Fuenfer{}); 
    set ff3(initializer_list<int>({}), Fuenfer{});
    // Lambda
    set<int,function<bool(int,int)>> ll1([](auto a,auto b){return a%3<b%3;});
    ll1.insert(3);
    auto lcomp = [](int a, int b) { return a%3 < b%3; };
    set<int, decltype(lcomp)> ll2(lcomp);
    ll2.insert(3);
    set ll3({3}, lcomp); 
    // Funktionszeiger
    set<int, bool(*)(int,int)> zz1(&fcompZehner);        // C-Stil
    zz1.insert(10);
    set<int, function<bool(int,int)>> zz2(&fcompZehner); // C++-Stil
    zz2.insert(10);
    set<int, decltype(&fcompZehner)> zz3(&fcompZehner);  // C++-Stil
    zz3.insert(10);
}

Godbolt Listing lst-0761-godb.cpp, https://godbolt.org/z/1Eoh9aoas:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1Eoh9aoas 
#include <set>
#include <functional> // function
using std::set; using std::function; using std::initializer_list;
bool fcompZehner(int a, int b) { return a%10 < b%10; }
struct Fuenfer {
    bool operator()(int a, int b) const { return a%5 < b% 5; }
};

int main() {
    // Funktor
    set<int, Fuenfer> ff1;
    ff1.insert(5);
    set ff2({5}, Fuenfer{}); 
    set ff3(initializer_list<int>({}), Fuenfer{});
    // Lambda
    set<int,function<bool(int,int)>> ll1([](auto a,auto b){return a%3<b%3;});
    ll1.insert(3);
    auto lcomp = [](int a, int b) { return a%3 < b%3; };
    set<int, decltype(lcomp)> ll2(lcomp);
    ll2.insert(3);
    set ll3({3}, lcomp); 
    // Funktionszeiger
    set<int, bool(*)(int,int)> zz1(&fcompZehner);        // C-Stil
    zz1.insert(10);
    set<int, function<bool(int,int)>> zz2(&fcompZehner); // C++-Stil
    zz2.insert(10);
    set<int, decltype(&fcompZehner)> zz3(&fcompZehner);  // C++-Stil
    zz3.insert(10);
}

Listing 24.50: Es gibt wieder mehrere Möglichkeiten, beim Konstruieren Elemente anzugeben.

Book listing lst-0762-book.cpp:

// https://godbolt.org/z/56rb9qfed 
// ohne Argumente
set<int> leer{};
cout <<= leer;           // Ausgabe:
// Initialisierungsliste
set liste{ 1,1,2,2,3,3,4,4,5,5 };  // set übernimmt keine Doppelten
cout <<= liste;          // Ausgabe: 1 2 3 4 5
// Kopie
set copy(liste);
cout <<= copy;           // Ausgabe: 1 2 3 4 5
// Iteratorpaar
set from_to( std::next(liste.begin()), std::prev(liste.end()));
cout <<= from_to;        // Ausgabe: 2 3 4
// Range
set gerade(from_range, liste | vs::filter([](int i){ return i%2; }));
cout <<= from_to;        // Ausgabe: 2 4

Godbolt Listing lst-0762-godb.cpp, https://godbolt.org/z/56rb9qfed:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/56rb9qfed 
// ohne Argumente
set<int> leer{};
cout <<= leer;           // Ausgabe:
// Initialisierungsliste
set liste{ 1,1,2,2,3,3,4,4,5,5 };  // set übernimmt keine Doppelten
cout <<= liste;          // Ausgabe: 1 2 3 4 5
// Kopie
set copy(liste);
cout <<= copy;           // Ausgabe: 1 2 3 4 5
// Iteratorpaar
set from_to( std::next(liste.begin()), std::prev(liste.end()));
cout <<= from_to;        // Ausgabe: 2 3 4
// Range
set gerade(from_range, liste | vs::filter([](int i){ return i%2; }));
cout <<= from_to;        // Ausgabe: 2 4

GodboltId:1dTPEd3nP

Book listing lst-0763-book.cpp:

// https://godbolt.org/z/1dTPEd3nP 
set quelle{1,2,3,4,5};
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
set ziel( std::move(quelle) ); // verschieben statt kopieren
cout <<= quelle;           // Ausgabe:
cout <<= ziel;             // Ausgabe: 1 2 3 4 5

Godbolt Listing lst-0763-godb.cpp, https://godbolt.org/z/1dTPEd3nP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1dTPEd3nP 
set quelle{1,2,3,4,5};
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
set ziel( std::move(quelle) ); // verschieben statt kopieren
cout <<= quelle;           // Ausgabe:
cout <<= ziel;             // Ausgabe: 1 2 3 4 5

GodboltId:8eGvWY45o

Book listing lst-0764-book.cpp:

// https://godbolt.org/z/8eGvWY45o 
set quelle{1,2,3,4,5};
set<int> ziel{};
set<int> ziel2{};
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
cout <<= ziel;             // Ausgabe:
cout <<= ziel2;            // Ausgabe:
ziel = quelle;             // nachträglich kopieren
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
cout <<= ziel;             // Ausgabe: 1 2 3 4 5
ziel2 = std::move(quelle); // verschieben
cout <<= quelle;           // Ausgabe:
cout <<= ziel2;            // Ausgabe: 1 2 3 4 5

Godbolt Listing lst-0764-godb.cpp, https://godbolt.org/z/8eGvWY45o:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8eGvWY45o 
set quelle{1,2,3,4,5};
set<int> ziel{};
set<int> ziel2{};
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
cout <<= ziel;             // Ausgabe:
cout <<= ziel2;            // Ausgabe:
ziel = quelle;             // nachträglich kopieren
cout <<= quelle;           // Ausgabe: 1 2 3 4 5
cout <<= ziel;             // Ausgabe: 1 2 3 4 5
ziel2 = std::move(quelle); // verschieben
cout <<= quelle;           // Ausgabe:
cout <<= ziel2;            // Ausgabe: 1 2 3 4 5

Listing 24.51: Statt »assign« können Sie das Copy-and-swap-Idiom verwenden.

Book listing lst-0765-book.cpp:

// https://godbolt.org/z/1vGPo9a99 
#include <vector>
// …
set data{1,2,3,4,5};
std::vector quelle{10, 20, 30, 40, 50};

// Es gibt kein set::assign:
data.assign(quelle.begin(), quelle.end());   //                                          (ERR)  kein set::assign
// Simulieren Sie es also mittels eines temporären set:
set temp(quelle.begin(), quelle.end());      // aus Quelle kopieren …
data.swap(temp);                             // … Inhalte effizient vertauschen
cout <<= data; // Ausgabe: 10 20 30 40 50
// … oder per vorherigem clear und darauffolgendem insert:
data.clear();                                // leeren …
data.insert(quelle.begin(), quelle.end());   // … und einfügen
cout <<= data; // Ausgabe: 10 20 30 40 50

Godbolt Listing lst-0765-godb.cpp, https://godbolt.org/z/1vGPo9a99:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1vGPo9a99 
#include <vector>
// …
set data{1,2,3,4,5};
std::vector quelle{10, 20, 30, 40, 50};

// Es gibt kein set::assign:
data.assign(quelle.begin(), quelle.end());   //                                          (ERR)  kein set::assign
// Simulieren Sie es also mittels eines temporären set:
set temp(quelle.begin(), quelle.end());      // aus Quelle kopieren …
data.swap(temp);                             // … Inhalte effizient vertauschen
cout <<= data; // Ausgabe: 10 20 30 40 50
// … oder per vorherigem clear und darauffolgendem insert:
data.clear();                                // leeren …
data.insert(quelle.begin(), quelle.end());   // … und einfügen
cout <<= data; // Ausgabe: 10 20 30 40 50

Listing 24.52: Zum Einfügen eines einzelnen Elements nehmen Sie »insert« oder »emplace«.

Book listing lst-0766-book.cpp:

// https://godbolt.org/z/PjEKKben4 
// …
template<typename IT> ostream& operator<<(ostream& os,const pair<IT,bool> wo)
  { return os << (wo.second ? "ja" : "nein"); }
struct Punkt {
    double x_, y_;
    Punkt(double x, double y) : x_{x}, y_{y} {}
    auto operator<=>(const Punkt&) const = default;
    friend ostream& operator<<(ostream &os, const Punkt &a) {
        return os << "(" << a.x_ << ',' << a.y_<< ")";
    }
};
int main() {
    set data{ 10, 20, 30, 40, 50, 60, 70 };
    auto wo = data.insert(35);         // fügt zwischen 30 und 40 ein
    cout << "neu? " << wo << '\n';     // Ausgabe: neu? ja
    wo = data.insert(40);              // gibt es schon, fügt also nicht ein
    cout << "neu? " << wo << '\n';     // Ausgabe: neu? nein
    set<Punkt> punkte{};
    punkte.insert( Punkt{3.50,7.25} ); // temporärer Wert
    punkte.emplace(1.25, 2.00);        // Konstruktorargumente
    cout <<= punkte;                   // Ausgabe: (1.25,2) (3.5,7.25)
}

Godbolt Listing lst-0766-godb.cpp, https://godbolt.org/z/PjEKKben4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PjEKKben4 
// …
template<typename IT> ostream& operator<<(ostream& os,const pair<IT,bool> wo)
  { return os << (wo.second ? "ja" : "nein"); }
struct Punkt {
    double x_, y_;
    Punkt(double x, double y) : x_{x}, y_{y} {}
    auto operator<=>(const Punkt&) const = default;
    friend ostream& operator<<(ostream &os, const Punkt &a) {
        return os << "(" << a.x_ << ',' << a.y_<< ")";
    }
};
int main() {
    set data{ 10, 20, 30, 40, 50, 60, 70 };
    auto wo = data.insert(35);         // fügt zwischen 30 und 40 ein
    cout << "neu? " << wo << '\n';     // Ausgabe: neu? ja
    wo = data.insert(40);              // gibt es schon, fügt also nicht ein
    cout << "neu? " << wo << '\n';     // Ausgabe: neu? nein
    set<Punkt> punkte{};
    punkte.insert( Punkt{3.50,7.25} ); // temporärer Wert
    punkte.emplace(1.25, 2.00);        // Konstruktorargumente
    cout <<= punkte;                   // Ausgabe: (1.25,2) (3.5,7.25)
}

Listing 24.53: Die Rückgabe können Sie beim Einfügen sortierter Bereiche wiederverwenden.

Book listing lst-0767-book.cpp:

// https://godbolt.org/z/qzaj79bor 
set data{ 10, 20, 30, 40, 50, 60, 70 };
set<int> ziel;
auto hinweis = ziel.begin();
for(auto &e : data) {
    hinweis =                    // Einfügeposition in nächster Runde nutzen
        ziel.insert(hinweis, e); // Hinweis hilft, weil data sortiert ist
}

Godbolt Listing lst-0767-godb.cpp, https://godbolt.org/z/qzaj79bor:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qzaj79bor 
set data{ 10, 20, 30, 40, 50, 60, 70 };
set<int> ziel;
auto hinweis = ziel.begin();
for(auto &e : data) {
    hinweis =                    // Einfügeposition in nächster Runde nutzen
        ziel.insert(hinweis, e); // Hinweis hilft, weil data sortiert ist
}

Listing 24.54: Nehmen Sie das gleiche insert bei sequenziellen und assoziativen Containern.

Book listing lst-0768-book.cpp:

// https://godbolt.org/z/nW3Gxe5Ye 
#include <set>
#include <vector>
#include <iostream>
using std::cout; using std::ostream; using std::set; using std::vector;

template<typename Container>
void insFive(Container& cont, int a, int b, int c, int d, int e) {
    auto it = cont.end();
    for(int x : { a, b, c, d, e }) {
        it = cont.insert(it, x); // geht mit vector, set etc.
    }
}
int main() {
    vector<int> dataVec{ };
    insFive(dataVec, 9, 2, 2, 0, 4 );
    for(auto e : dataVec) cout <<e<<' ';
    cout << '\n'; // Ausgabe: 4 0 2 2 9
    set<int> dataSet{ };
    insFive(dataSet, 9, 4, 2, 2, 0);
    for(auto e : dataSet) cout <<e<<' ';
    cout << '\n'; // Ausgabe: 0 2 4 9
}

Godbolt Listing lst-0768-godb.cpp, https://godbolt.org/z/nW3Gxe5Ye:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nW3Gxe5Ye 
#include <set>
#include <vector>
#include <iostream>
using std::cout; using std::ostream; using std::set; using std::vector;

template<typename Container>
void insFive(Container& cont, int a, int b, int c, int d, int e) {
    auto it = cont.end();
    for(int x : { a, b, c, d, e }) {
        it = cont.insert(it, x); // geht mit vector, set etc.
    }
}
int main() {
    vector<int> dataVec{ };
    insFive(dataVec, 9, 2, 2, 0, 4 );
    for(auto e : dataVec) cout <<e<<' ';
    cout << '\n'; // Ausgabe: 4 0 2 2 9
    set<int> dataSet{ };
    insFive(dataSet, 9, 4, 2, 2, 0);
    for(auto e : dataSet) cout <<e<<' ';
    cout << '\n'; // Ausgabe: 0 2 4 9
}

Listing 24.55: Sie können auch mehrere Elemente einfügen.

Book listing lst-0769-book.cpp:

// https://godbolt.org/z/rTvovhr5M 
#include <vector>
set data{ 10, 20, 30, };
data.insert( { 40, 50, 60, 70 }); // Initialisierungsliste
std::vector neu{ 5, 25, 35, 15, 25, 75, 95 };
data.insert( neu.cbegin()+1, neu.cend()-1 ); // Bereich
cout <<= data; // Ausgabe: 10 15 20 25 30 35 40 50 60 70 75

Godbolt Listing lst-0769-godb.cpp, https://godbolt.org/z/rTvovhr5M:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rTvovhr5M 
#include <vector>
set data{ 10, 20, 30, };
data.insert( { 40, 50, 60, 70 }); // Initialisierungsliste
std::vector neu{ 5, 25, 35, 15, 25, 75, 95 };
data.insert( neu.cbegin()+1, neu.cend()-1 ); // Bereich
cout <<= data; // Ausgabe: 10 15 20 25 30 35 40 50 60 70 75

Listing 24.56: Dies sind die »set«-Suchfunktionen.

Book listing lst-0770-book.cpp:

// https://godbolt.org/z/xnv9Wbxbz 
#include <set>
#include <iostream>
using std::cout; using std::ostream; using std::set;
void suchmal(const set<int>&data, int was, ostream&os) {
    os << was << "? ";
    // enthält
    auto drin = data.contains(was);  // C++20
    os << "drin:" << (drin ? "ja." : "nein."); // enthält prüfen
    auto wo = data.find(was);
    if(wo != data.end()) {
        os << " gefunden:" << *wo << " ";
    } else {
        os << " nicht gefunden. ";
    }
    auto lo = data.lower_bound(was);
    if(lo != data.end()) {
        os << "lo:" << *lo;
    } else {
        os << "lo:-";
    }
    auto up = data.upper_bound(was);
    if(up != data.end()) {
        os << " up:" << *up;
    } else {
        os << " up:-";
    }
    // [lo,up] ist nun das Gleiche, was equal_range geliefert hätte
    os << " Bereich:{";
    for( ; lo != up; ++ lo) {
      os << *lo << ' ';
    }
    os << "}";
    // zählen
    os << " C:" << data.count(was) // Treffer zählen
       << "\n";
}
int main() {
    set data{ 10, 20, 30, 40, 50, 60 };
    suchmal(data, 20, cout); // 20? drin:ja. gefunden:20 lo:20 up:30 Bereich:{20 } C:1
    suchmal(data, 25, cout); // 25? drin:nein. lo:30 up:30 Bereich:{} C:0
    suchmal(data, 10, cout); // 10? drin:ja. gefunden:10 lo:10 up:20 Bereich:{10 } C:1
    suchmal(data, 60, cout); // 60? drin:ja. gefunden:60 lo:60 up:- Bereich:{60 } C:1
    suchmal(data, 5, cout);  // 5? drin:nein. lo:10 up:10 Bereich:{} C:0
    suchmal(data, 99, cout); // 99? drin:nein. lo:- up:- Bereich:{} C:0
}

Godbolt Listing lst-0770-godb.cpp, https://godbolt.org/z/xnv9Wbxbz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xnv9Wbxbz 
#include <set>
#include <iostream>
using std::cout; using std::ostream; using std::set;
void suchmal(const set<int>&data, int was, ostream&os) {
    os << was << "? ";
    // enthält
    auto drin = data.contains(was);  // C++20
    os << "drin:" << (drin ? "ja." : "nein."); // enthält prüfen
    auto wo = data.find(was);
    if(wo != data.end()) {
        os << " gefunden:" << *wo << " ";
    } else {
        os << " nicht gefunden. ";
    }
    auto lo = data.lower_bound(was);
    if(lo != data.end()) {
        os << "lo:" << *lo;
    } else {
        os << "lo:-";
    }
    auto up = data.upper_bound(was);
    if(up != data.end()) {
        os << " up:" << *up;
    } else {
        os << " up:-";
    }
    // [lo,up] ist nun das Gleiche, was equal_range geliefert hätte
    os << " Bereich:{";
    for( ; lo != up; ++ lo) {
      os << *lo << ' ';
    }
    os << "}";
    // zählen
    os << " C:" << data.count(was) // Treffer zählen
       << "\n";
}
int main() {
    set data{ 10, 20, 30, 40, 50, 60 };
    suchmal(data, 20, cout); // 20? drin:ja. gefunden:20 lo:20 up:30 Bereich:{20 } C:1
    suchmal(data, 25, cout); // 25? drin:nein. lo:30 up:30 Bereich:{} C:0
    suchmal(data, 10, cout); // 10? drin:ja. gefunden:10 lo:10 up:20 Bereich:{10 } C:1
    suchmal(data, 60, cout); // 60? drin:ja. gefunden:60 lo:60 up:- Bereich:{60 } C:1
    suchmal(data, 5, cout);  // 5? drin:nein. lo:10 up:10 Bereich:{} C:0
    suchmal(data, 99, cout); // 99? drin:nein. lo:- up:- Bereich:{} C:0
}

Listing 24.57: Sie können mit nicht identischen Schlüsseln suchen, wenn diese äquivalent sind.

Book listing lst-0771-book.cpp:

// https://godbolt.org/z/jGfeT94as 
#include <string>
#include <set>
#include <iostream>
#include <tuple> // tuple, tie
using std::string; using std::set; using std::cout; using std::tie;
struct Hobbit {
  string vorname;
  string nachname;
  Hobbit(const string v, const string n) : vorname{v}, nachname{n} {}
};
struct CompNachname {
  bool operator()(const Hobbit& x, const Hobbit& y) const { // normales <
    return tie(x.nachname, x.vorname) < tie(y.nachname, y.vorname);
  }
  using is_transparent = std::true_type; // für find erlaubt
  bool operator()(const Hobbit& x, const string& y) const { // für find etc.
    return x.nachname < y;
  }
  bool operator()(const string& x, const Hobbit& y) const { // für find etc.
    return x < y.nachname;
  }
};
int main() {
    using namespace std::literals; // erlaube "…"s
    set<Hobbit,CompNachname> hobbits;
    hobbits.emplace( "Frodo", "Baggins" );
    hobbits.emplace( "Sam", "Gamgee" );
    auto f1 = hobbits.find( Hobbit{"Frodo", "Baggins"} ); // ganzer Schlüssel
    if(f1 != hobbits.end()) {
        cout << "gefunden: " << f1->vorname << '\n'; // Frodo
    }
    auto f2 = hobbits.find( "Gamgee"s );             // äquivalenter Schlüssel
    if(f2 != hobbits.end()) {
        cout << "gefunden: " << f2->vorname << '\n'; // Sam
    }
}

Godbolt Listing lst-0771-godb.cpp, https://godbolt.org/z/jGfeT94as:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jGfeT94as 
#include <string>
#include <set>
#include <iostream>
#include <tuple> // tuple, tie
using std::string; using std::set; using std::cout; using std::tie;
struct Hobbit {
  string vorname;
  string nachname;
  Hobbit(const string v, const string n) : vorname{v}, nachname{n} {}
};
struct CompNachname {
  bool operator()(const Hobbit& x, const Hobbit& y) const { // normales <
    return tie(x.nachname, x.vorname) < tie(y.nachname, y.vorname);
  }
  using is_transparent = std::true_type; // für find erlaubt
  bool operator()(const Hobbit& x, const string& y) const { // für find etc.
    return x.nachname < y;
  }
  bool operator()(const string& x, const Hobbit& y) const { // für find etc.
    return x < y.nachname;
  }
};
int main() {
    using namespace std::literals; // erlaube "…"s
    set<Hobbit,CompNachname> hobbits;
    hobbits.emplace( "Frodo", "Baggins" );
    hobbits.emplace( "Sam", "Gamgee" );
    auto f1 = hobbits.find( Hobbit{"Frodo", "Baggins"} ); // ganzer Schlüssel
    if(f1 != hobbits.end()) {
        cout << "gefunden: " << f1->vorname << '\n'; // Frodo
    }
    auto f2 = hobbits.find( "Gamgee"s );             // äquivalenter Schlüssel
    if(f2 != hobbits.end()) {
        cout << "gefunden: " << f2->vorname << '\n'; // Sam
    }
}

Listing 24.58: »erase« löscht ein oder mehrere Elemente.

Book listing lst-0773-book.cpp:

// https://godbolt.org/z/xW9bTqfG4 
set data{ 10, 20, 30, 40, 50, 60, 70 };
auto lo = data.lower_bound(35);
auto up = data.upper_bound(55);
data.erase(lo, up);      // löscht alle Zahlen zwischen 35 und 55
cout <<= data;           // Ausgabe: 10 20 30 60 70
lo = data.lower_bound(20);
up = data.upper_bound(60);
data.erase(lo, up);      // löscht inklusive 60, weil up auf 70 verweist
cout <<= data;           // Ausgabe: 10 70
auto n = data.erase(69); // löscht nichts
cout << "Anzahl entfernter Elemente: "<< n << '\n'; // Ausgabe: Anzahl … 0
n = data.erase(70);      // löscht ein Element
cout << "Anzahl entfernter Elemente: "<< n << '\n';  // Ausgabe: Anzahl … 1
cout <<= data;           // Ausgabe: 10

Godbolt Listing lst-0773-godb.cpp, https://godbolt.org/z/xW9bTqfG4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xW9bTqfG4 
set data{ 10, 20, 30, 40, 50, 60, 70 };
auto lo = data.lower_bound(35);
auto up = data.upper_bound(55);
data.erase(lo, up);      // löscht alle Zahlen zwischen 35 und 55
cout <<= data;           // Ausgabe: 10 20 30 60 70
lo = data.lower_bound(20);
up = data.upper_bound(60);
data.erase(lo, up);      // löscht inklusive 60, weil up auf 70 verweist
cout <<= data;           // Ausgabe: 10 70
auto n = data.erase(69); // löscht nichts
cout << "Anzahl entfernter Elemente: "<< n << '\n'; // Ausgabe: Anzahl … 0
n = data.erase(70);      // löscht ein Element
cout << "Anzahl entfernter Elemente: "<< n << '\n';  // Ausgabe: Anzahl … 1
cout <<= data;           // Ausgabe: 10

Listing 24.59: Mit »[]« erzeugen Sie als Seiteneffekt eventuell einen Eintrag.

Book listing lst-0774-book.cpp:

// https://godbolt.org/z/zWa58dYYq 
#include <map>
#include <iostream>
using std::map; using std::cout;
int main() {
    map<int,char> alpha;
    cout << alpha.size() << '\n';       // 0 natürlich
    if( alpha[5] == '3' ) { /* ... */ }
    cout << alpha.size() << '\n';       // nun 1
    char x = alpha[99];                 // klappt
    cout << alpha.size() << '\n';       // und nun 2
}

Godbolt Listing lst-0774-godb.cpp, https://godbolt.org/z/zWa58dYYq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zWa58dYYq 
#include <map>
#include <iostream>
using std::map; using std::cout;
int main() {
    map<int,char> alpha;
    cout << alpha.size() << '\n';       // 0 natürlich
    if( alpha[5] == '3' ) { /* ... */ }
    cout << alpha.size() << '\n';       // nun 1
    char x = alpha[99];                 // klappt
    cout << alpha.size() << '\n';       // und nun 2
}

Listing 24.60: Dies ist die Schablone für die Beispiellistings dieses Abschnitts zur »map«.

Book listing lst-0775-book.cpp:

// https://godbolt.org/z/Eovd71TbT 
#include <map>        // die Hauptsache
#include <iostream>   // zur Ausgabe
#include <string>     // gerne mal Schlüssel oder Ziel
using std::map; using std::cout; using std::string;
template<typename Key, typename Trg, typename Comp>
std::ostream& operator<<=(std::ostream&os, const map<Key,Trg,Comp>&data) {
    for(auto &e : data) os << e.first << ":" << e.second << ' ';
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Godbolt Listing lst-0775-godb.cpp, https://godbolt.org/z/Eovd71TbT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Eovd71TbT 
#include <map>        // die Hauptsache
#include <iostream>   // zur Ausgabe
#include <string>     // gerne mal Schlüssel oder Ziel
using std::map; using std::cout; using std::string;
template<typename Key, typename Trg, typename Comp>
std::ostream& operator<<=(std::ostream&os, const map<Key,Trg,Comp>&data) {
    for(auto &e : data) os << e.first << ":" << e.second << ' ';
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Listing 24.61: Auch bei einer »map« können Sie eine eigene Vergleichsfunktion mitgeben.

Book listing lst-0776-book.cpp:

// https://godbolt.org/z/nfs15n1Mn 
#include <cstdio> // toupper, tolower
// …
auto comp = [](char a, char b) { return toupper(a) < toupper(b); };
map<char,int,decltype(comp)> lets(comp); // als Templateparameter und Argument
lets['a'] = 1;
lets['B'] = 2;
lets['c'] = 3;
lets['A'] = 4; // überschreibt Position 'a'
cout <<= lets; // Ausgabe: a:4 B:2 c:3
struct Comp {  // Funktor
    bool operator()(char a, char b) const { return toupper(a) < toupper(b); }
};
map<char,int,Comp> lets2; // hier reicht der Templateparameter

Godbolt Listing lst-0776-godb.cpp, https://godbolt.org/z/nfs15n1Mn:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nfs15n1Mn 
#include <cstdio> // toupper, tolower
// …
auto comp = [](char a, char b) { return toupper(a) < toupper(b); };
map<char,int,decltype(comp)> lets(comp); // als Templateparameter und Argument
lets['a'] = 1;
lets['B'] = 2;
lets['c'] = 3;
lets['A'] = 4; // überschreibt Position 'a'
cout <<= lets; // Ausgabe: a:4 B:2 c:3
struct Comp {  // Funktor
    bool operator()(char a, char b) const { return toupper(a) < toupper(b); }
};
map<char,int,Comp> lets2; // hier reicht der Templateparameter

Listing 24.62: Die Initialisierungsliste muss »pair«-Elemente enthalten.

Book listing lst-0778-book.cpp:

// https://godbolt.org/z/79xx8ddoY 
using std::pair; using std::make_pair;
namespace literal_p { // benutzerdefinierte Literale besser in Namespace packen
constexpr pair<char,char> operator "" _p(const char* s, size_t len) {
    return len>=2 ?make_pair(s[0], s[1]) : make_pair( '-', '-' );
} }
struct Q {
    char a_; int n_;
    Q(char a, int n) : a_{a}, n_{n} {}
    operator pair<const char,int>() { return make_pair(a_, n_); }
};
// …
// explizite Paare:
map<int,int> nums { pair<int,int>(3,4), make_pair(7,8), make_pair(11,23) };
map nums2 { pair<int,int>(6,1), make_pair(5,2) };
// implizite Paare aus Initialisierungslisten:
map<int,char> numch{{1,'a'},{2,'b'},{3,'c'}};
map<int,int> nums3 { {7,2}, {9,4} };
using namespace literal_p;
map<char,char> pmap { "ab"_p, "cd"_p, "ef"_p }; // Umweg über eigenes Literal
cout <<= pmap;                                  // Ausgabe: a:b c:d e:f
map<char,int> qmap{Q('a',1),Q('b',2),Q('c',3)}; // implizite Umwandlungen
cout <<= qmap;                                  // Ausgabe: a:1 b:2 c:3

Godbolt Listing lst-0778-godb.cpp, https://godbolt.org/z/79xx8ddoY:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/79xx8ddoY 
using std::pair; using std::make_pair;
namespace literal_p { // benutzerdefinierte Literale besser in Namespace packen
constexpr pair<char,char> operator "" _p(const char* s, size_t len) {
    return len>=2 ?make_pair(s[0], s[1]) : make_pair( '-', '-' );
} }
struct Q {
    char a_; int n_;
    Q(char a, int n) : a_{a}, n_{n} {}
    operator pair<const char,int>() { return make_pair(a_, n_); }
};
// …
// explizite Paare:
map<int,int> nums { pair<int,int>(3,4), make_pair(7,8), make_pair(11,23) };
map nums2 { pair<int,int>(6,1), make_pair(5,2) };
// implizite Paare aus Initialisierungslisten:
map<int,char> numch{{1,'a'},{2,'b'},{3,'c'}};
map<int,int> nums3 { {7,2}, {9,4} };
using namespace literal_p;
map<char,char> pmap { "ab"_p, "cd"_p, "ef"_p }; // Umweg über eigenes Literal
cout <<= pmap;                                  // Ausgabe: a:b c:d e:f
map<char,int> qmap{Q('a',1),Q('b',2),Q('c',3)}; // implizite Umwandlungen
cout <<= qmap;                                  // Ausgabe: a:1 b:2 c:3

Listing 24.63: Ein einzelnes neues Element geben Sie als Paar an.

Book listing lst-0779-book.cpp:

// https://godbolt.org/z/bzvrPefvY 
map<int,string> plz2ort;
plz2ort.insert(std::make_pair(53227, "Bonn"));
plz2ort.emplace(50667, "Koeln");
cout <<= plz2ort;                    // Ausgabe: 50667:Koeln 53227:Bonn
map<string,int> ort2plz;
ort2plz.emplace("Koeln", 50667);
ort2plz.emplace("Koeln", 51063);     // überschreibt nicht
cout <<= ort2plz;                    // Ausgabe: Koeln:50667

Godbolt Listing lst-0779-godb.cpp, https://godbolt.org/z/bzvrPefvY:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bzvrPefvY 
map<int,string> plz2ort;
plz2ort.insert(std::make_pair(53227, "Bonn"));
plz2ort.emplace(50667, "Koeln");
cout <<= plz2ort;                    // Ausgabe: 50667:Koeln 53227:Bonn
map<string,int> ort2plz;
ort2plz.emplace("Koeln", 50667);
ort2plz.emplace("Koeln", 51063);     // überschreibt nicht
cout <<= ort2plz;                    // Ausgabe: Koeln:50667

Listing 24.64: Mit »operator[]« automatisch erzeugen und gleich überschreiben

Book listing lst-0780-book.cpp:

// https://godbolt.org/z/7h3vsWvYG 
map<string,int> zwerge;
zwerge.emplace("Fili",  2859);
cout << zwerge["Fili"] << '\n'; // Ausgabe: 2859
cout << zwerge["Dori"] << '\n'; // neu erzeugt. Ausgabe: 0
zwerge["Kili"] = 2846;          // neu erzeugt und gleich überschrieben
cout << zwerge["Kili"] << '\n'; // Ausgabe: 2846
cout <<= zwerge;                // Ausgabe: Dori:0 Fili:2859 Kili:2846

Godbolt Listing lst-0780-godb.cpp, https://godbolt.org/z/7h3vsWvYG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7h3vsWvYG 
map<string,int> zwerge;
zwerge.emplace("Fili",  2859);
cout << zwerge["Fili"] << '\n'; // Ausgabe: 2859
cout << zwerge["Dori"] << '\n'; // neu erzeugt. Ausgabe: 0
zwerge["Kili"] = 2846;          // neu erzeugt und gleich überschrieben
cout << zwerge["Kili"] << '\n'; // Ausgabe: 2846
cout <<= zwerge;                // Ausgabe: Dori:0 Fili:2859 Kili:2846

Listing 24.65: Sie können den Wert eines Ziels ändern.

Book listing lst-0781-book.cpp:

// https://godbolt.org/z/7E6cr8GE9 
map<string,string> data { {"Hans","Albers"}, {"Heinz","Ruehmann" }, };
cout <<= data;                         // Hans:Albers Heinz:Ruehmann
data.rbegin()->second = "Erhardt";     // Ziel überschreiben
cout <<= data;                         // Hans:Albers Heinz:Erhardt

Godbolt Listing lst-0781-godb.cpp, https://godbolt.org/z/7E6cr8GE9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7E6cr8GE9 
map<string,string> data { {"Hans","Albers"}, {"Heinz","Ruehmann" }, };
cout <<= data;                         // Hans:Albers Heinz:Ruehmann
data.rbegin()->second = "Erhardt";     // Ziel überschreiben
cout <<= data;                         // Hans:Albers Heinz:Erhardt

Listing 24.66: Iteratoren von »map« sind vom Typ »pair«.

Book listing lst-0782-book.cpp:

// https://godbolt.org/z/16T5dob75 
map<char,int> data { { 'a',1}, {'b',2}, {'c',3} };
for(auto it=data.rbegin(); it!=data.rend(); ++it) {  // rückwärts
    cout << it->first << ':' << it->second << ' ';   // mit -> dereferenzieren
}
cout << '\n'; // Ausgabe: c:3 b:2 a:1
for(auto &e : data) {                          // vorwärts, nimmt begin() und end()
    cout << e.first << ':' << e.second << ' '; // Paar, Elementzugriff mit .
}
cout << '\n'; // Ausgabe: a:1 b:2 c:3

Godbolt Listing lst-0782-godb.cpp, https://godbolt.org/z/16T5dob75:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/16T5dob75 
map<char,int> data { { 'a',1}, {'b',2}, {'c',3} };
for(auto it=data.rbegin(); it!=data.rend(); ++it) {  // rückwärts
    cout << it->first << ':' << it->second << ' ';   // mit -> dereferenzieren
}
cout << '\n'; // Ausgabe: c:3 b:2 a:1
for(auto &e : data) {                          // vorwärts, nimmt begin() und end()
    cout << e.first << ':' << e.second << ' '; // Paar, Elementzugriff mit .
}
cout << '\n'; // Ausgabe: a:1 b:2 c:3

Listing 24.67: Sie können »operator[]« nicht auf einer »const map« verwenden.

Book listing lst-0783-book.cpp:

// https://godbolt.org/z/54zqqhzh6 
string such7(const map<int,string> &data) {
    return data[7];            //                                                  (ERR)  non-const-Methode auf const-Parameter
}
string such5(const map<int,string> &data) {
    auto it = data.find(5);    // nicht automatisch einfügend
    return it==data.end() ? string{} : it->second;
}
// …
map<int,string> zwerge{ {1,"eins"}, {3,"drei"}, {5,"fuenf"}, {7,"sieben"} };
cout << such7(zwerge) << '\n';
cout << such5(zwerge) << '\n';  // Ausgabe: fuenf

Godbolt Listing lst-0783-godb.cpp, https://godbolt.org/z/54zqqhzh6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/54zqqhzh6 
string such7(const map<int,string> &data) {
    return data[7];            //                                                  (ERR)  non-const-Methode auf const-Parameter
}
string such5(const map<int,string> &data) {
    auto it = data.find(5);    // nicht automatisch einfügend
    return it==data.end() ? string{} : it->second;
}
// …
map<int,string> zwerge{ {1,"eins"}, {3,"drei"}, {5,"fuenf"}, {7,"sieben"} };
cout << such7(zwerge) << '\n';
cout << such5(zwerge) << '\n';  // Ausgabe: fuenf

Listing 24.68: Dies ist die Schablone für die Beispiellistings dieses Abschnitts zu »multiset«.

Book listing lst-0784-book.cpp:

// https://godbolt.org/z/PYbexWex3 
#include <set>     // multiset
#include <iostream>
using std::multiset; using std::cout;
template<typename Elem, typename Comp>
std::ostream& operator<<=(std::ostream&os, const multiset<Elem,Comp>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Godbolt Listing lst-0784-godb.cpp, https://godbolt.org/z/PYbexWex3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PYbexWex3 
#include <set>     // multiset
#include <iostream>
using std::multiset; using std::cout;
template<typename Elem, typename Comp>
std::ostream& operator<<=(std::ostream&os, const multiset<Elem,Comp>&data) {
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Listing 24.69: Einträge werden sortiert, doppelte bleiben erhalten.

Book listing lst-0785-book.cpp:

// https://godbolt.org/z/Mej9GjT1j 
#include <vector>
// …
multiset msinit{1,2,2,3,1};                   // sortiert bei Initialisierung
cout <<= msinit; // Ausgabe: 1 1 2 2 3
std::vector in{ 7,7,7,7,7,7,7 };
std::set srange( in.begin(), in.end() );      // set entfernt doppelte
cout << srange.size() << ": " << *srange.begin() << '\n'; // Ausgabe: 1: 7
multiset msrange( in.begin(), in.end() );      // multiset erhält doppelte
cout <<= msrange; // Ausgabe: 7 7 7 7 7 7 7

Godbolt Listing lst-0785-godb.cpp, https://godbolt.org/z/Mej9GjT1j:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mej9GjT1j 
#include <vector>
// …
multiset msinit{1,2,2,3,1};                   // sortiert bei Initialisierung
cout <<= msinit; // Ausgabe: 1 1 2 2 3
std::vector in{ 7,7,7,7,7,7,7 };
std::set srange( in.begin(), in.end() );      // set entfernt doppelte
cout << srange.size() << ": " << *srange.begin() << '\n'; // Ausgabe: 1: 7
multiset msrange( in.begin(), in.end() );      // multiset erhält doppelte
cout <<= msrange; // Ausgabe: 7 7 7 7 7 7 7

Listing 24.70: Die »multiset«-Suchfunktionen finden den Bereich der passenden Elemente.

Book listing lst-0786-book.cpp:

// https://godbolt.org/z/9hPqa5MfY 
#include <string>
#include <iterator> // distance
#include <ranges>   // subrange
struct Person {
  std::string name;
  friend bool operator<(const Person &a, const Person &b) {  
    // nur erster Buchstabe
    return a.name.size()==0 ? true
      : (b.name.size()==0 ? false : a.name[0] < b.name[0]);
  }
};
// …
multiset data{ 1, 4,4, 2,2,2, 7, 9 };
auto [von1, bis1] = data.equal_range(2);
cout << "Anzahl 2en: "
  << std::distance(von1, bis1) << '\n'; // Ausgabe: Anzahl 2en: 3
auto [von2, bis2] = data.equal_range(5);
cout << "Anzahl 5en: "
  << std::distance(von2, bis2) << '\n'; // Ausgabe: Anzahl 5en: 0
multiset<Person> raum{
  {"Karl"}, {"Kurt"}, {"Peter"}, {"Karl"}, {"Ken"}};
auto [p, q] = raum.equal_range(Person{"K"});
for(auto& p : std::ranges::subrange(p,q)) { // C++20-Range oder einfache Schleife
  cout << p.name << ' ';
}
cout << '\n'; // Ausgabe: Karl Kurt Karl Ken

Godbolt Listing lst-0786-godb.cpp, https://godbolt.org/z/9hPqa5MfY:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9hPqa5MfY 
#include <string>
#include <iterator> // distance
#include <ranges>   // subrange
struct Person {
  std::string name;
  friend bool operator<(const Person &a, const Person &b) {  
    // nur erster Buchstabe
    return a.name.size()==0 ? true
      : (b.name.size()==0 ? false : a.name[0] < b.name[0]);
  }
};
// …
multiset data{ 1, 4,4, 2,2,2, 7, 9 };
auto [von1, bis1] = data.equal_range(2);
cout << "Anzahl 2en: "
  << std::distance(von1, bis1) << '\n'; // Ausgabe: Anzahl 2en: 3
auto [von2, bis2] = data.equal_range(5);
cout << "Anzahl 5en: "
  << std::distance(von2, bis2) << '\n'; // Ausgabe: Anzahl 5en: 0
multiset<Person> raum{
  {"Karl"}, {"Kurt"}, {"Peter"}, {"Karl"}, {"Ken"}};
auto [p, q] = raum.equal_range(Person{"K"});
for(auto& p : std::ranges::subrange(p,q)) { // C++20-Range oder einfache Schleife
  cout << p.name << ' ';
}
cout << '\n'; // Ausgabe: Karl Kurt Karl Ken

Listing 24.71: Dies ist die Schablone für die Listings dieses Abschnitts zur »multimap«.

Book listing lst-0787-book.cpp:

// https://godbolt.org/z/sfaEozjzq 
#include <map>        // die Hauptsache
#include <iostream>   // zur Ausgabe
#include <string>     // gerne mal Schlüssel oder Ziel
using std::multimap; using std::cout; using std::string;
template<typename Key, typename Trg, typename Cmp>
std::ostream& operator<<=(std::ostream&os, const multimap<Key,Trg,Cmp>&data){
    for(auto &e : data) {
        os << e.first << ":" << e.second << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Godbolt Listing lst-0787-godb.cpp, https://godbolt.org/z/sfaEozjzq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sfaEozjzq 
#include <map>        // die Hauptsache
#include <iostream>   // zur Ausgabe
#include <string>     // gerne mal Schlüssel oder Ziel
using std::multimap; using std::cout; using std::string;
template<typename Key, typename Trg, typename Cmp>
std::ostream& operator<<=(std::ostream&os, const multimap<Key,Trg,Cmp>&data){
    for(auto &e : data) {
        os << e.first << ":" << e.second << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Listing 24.72: Es landen alle Einträge in der »multimap«.

Book listing lst-0788-book.cpp:

// https://godbolt.org/z/6no9dW64d 
multimap int2int{ std::make_pair(3,4) };  // multimap<int,int>
using namespace std::literals; // für ""s
multimap<int,string> numlang{
    {7,"sieben"s}, {6,"six"s},
    {7,"siete"s}, {6,"sechs"s},
    {7,"seven"s}, {7,"yedi"s},
    {8,"eight"s} };
cout <<= numlang; // Ausgabe: 6:six 6:sechs 7:sieben 7:siete 7:seven 7:yedi 8:eight

Godbolt Listing lst-0788-godb.cpp, https://godbolt.org/z/6no9dW64d:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6no9dW64d 
multimap int2int{ std::make_pair(3,4) };  // multimap<int,int>
using namespace std::literals; // für ""s
multimap<int,string> numlang{
    {7,"sieben"s}, {6,"six"s},
    {7,"siete"s}, {6,"sechs"s},
    {7,"seven"s}, {7,"yedi"s},
    {8,"eight"s} };
cout <<= numlang; // Ausgabe: 6:six 6:sechs 7:sieben 7:siete 7:seven 7:yedi 8:eight

Listing 24.73: »insert« und »emplace« bei der »multimap«

Book listing lst-0789-book.cpp:

// https://godbolt.org/z/dj68ej97r 
using namespace std::literals; // für ""s

multimap<int,string> numlang{};
numlang.insert( std::make_pair(7, "seven"s) );
numlang.insert( std::pair<int,string>(7, "sieben"s) );
numlang.emplace( 7, "yedi"s );
cout <<= numlang; // Ausgabe: 7:seven 7:sieben 7:yedi

Godbolt Listing lst-0789-godb.cpp, https://godbolt.org/z/dj68ej97r:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dj68ej97r 
using namespace std::literals; // für ""s

multimap<int,string> numlang{};
numlang.insert( std::make_pair(7, "seven"s) );
numlang.insert( std::pair<int,string>(7, "sieben"s) );
numlang.emplace( 7, "yedi"s );
cout <<= numlang; // Ausgabe: 7:seven 7:sieben 7:yedi

Listing 24.74: »erase«mit einem Schlüssel kann mehrere Elemente löschen.

Book listing lst-0790-book.cpp:

// https://godbolt.org/z/TbvKTn4Px 
multimap<char,int> vals{ {'c',1}, {'c',8}, {'g',1},
    {'c',1}, {'a',7}, {'a',1}, {'c',2}, };
cout <<= vals;            // Ausgabe: a:7 a:1 c:1 c:8 c:1 c:2 g:1
vals.erase( 'c' );        // löscht alle 'c's
cout <<= vals;            // Ausgabe: a:7 a:1 g:1
vals.erase(vals.begin()); // löscht nur eines der 'a's
cout <<= vals;            // Ausgabe: a:1 g:1

Godbolt Listing lst-0790-godb.cpp, https://godbolt.org/z/TbvKTn4Px:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TbvKTn4Px 
multimap<char,int> vals{ {'c',1}, {'c',8}, {'g',1},
    {'c',1}, {'a',7}, {'a',1}, {'c',2}, };
cout <<= vals;            // Ausgabe: a:7 a:1 c:1 c:8 c:1 c:2 g:1
vals.erase( 'c' );        // löscht alle 'c's
cout <<= vals;            // Ausgabe: a:7 a:1 g:1
vals.erase(vals.begin()); // löscht nur eines der 'a's
cout <<= vals;            // Ausgabe: a:1 g:1

Listing 24.75: Betreiben Sie ungeordnete assoziative Container niemals mit einer schlechten Hashfunktion.

Book listing lst-0791-book.cpp:

// https://godbolt.org/z/ejMv4ohse 
#include <set>               // set, multiset
#include <unordered_set>     // unordered_set, unordered_multiset
#include <iostream>
#include <string>
#include <chrono>            // Zeitmessung
using std::cout;
using namespace std::chrono;

long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start).count();
}
constexpr size_t ITERATIONS = 100'000;
template<typename Cont, typename Gen>
    requires std::invocable<Gen, size_t> &&  // C++20-Concept
    requires(Gen gen, size_t n) {{gen(n)} -> std::same_as<int>;} &&
    std::same_as<typename Cont::value_type,int>
void timeStuff(std::string name, Cont data, Gen genNum) {
    cout << name << "...";
    auto start = steady_clock::now();
    for(size_t idx=0; idx<ITERATIONS; ++idx) {
        data.insert( genNum(idx) );
    }
    cout << " " << millisSeit(start) << " ms" << std::endl;
}
int alleGleich(size_t) { return 7; }      // erzeugt immer die gleiche Zahl
int gestreut(size_t n) { return int(n); } // erzeugt unterschiedliche Zahlen
struct BadHash {  // die schlechtestmögliche Hashfunktion als Funktor
       size_t   operator()(int) const { return 1uz; }
};

int main() {
   std::multiset<int> m{};
   timeStuff("multiset           alleGleich        ", m, &alleGleich);
   timeStuff("multiset           gestreut          ", m, &gestreut);
   std::set<int> s{};
   timeStuff("set                alleGleich        ", s, &alleGleich);
   timeStuff("set                gestreut          ", s, &gestreut);
   std::unordered_multiset<int> um{};
   timeStuff("unordered_multiset alleGleich        ", um, &alleGleich);
   timeStuff("unordered_multiset gestreut          ", um, &gestreut);
   std::unordered_multiset<int,BadHash> umb{};
   timeStuff("unordered_multiset alleGleich badHash", umb, &alleGleich);
   timeStuff("unordered_multiset gestreut   badHash", umb, &gestreut);
}

Godbolt Listing lst-0791-godb.cpp, https://godbolt.org/z/ejMv4ohse:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ejMv4ohse 
#include <set>               // set, multiset
#include <unordered_set>     // unordered_set, unordered_multiset
#include <iostream>
#include <string>
#include <chrono>            // Zeitmessung
using std::cout;
using namespace std::chrono;

long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start).count();
}
constexpr size_t ITERATIONS = 100'000;
template<typename Cont, typename Gen>
    requires std::invocable<Gen, size_t> &&  // C++20-Concept
    requires(Gen gen, size_t n) {{gen(n)} -> std::same_as<int>;} &&
    std::same_as<typename Cont::value_type,int>
void timeStuff(std::string name, Cont data, Gen genNum) {
    cout << name << "...";
    auto start = steady_clock::now();
    for(size_t idx=0; idx<ITERATIONS; ++idx) {
        data.insert( genNum(idx) );
    }
    cout << " " << millisSeit(start) << " ms" << std::endl;
}
int alleGleich(size_t) { return 7; }      // erzeugt immer die gleiche Zahl
int gestreut(size_t n) { return int(n); } // erzeugt unterschiedliche Zahlen
struct BadHash {  // die schlechtestmögliche Hashfunktion als Funktor
       size_t   operator()(int) const { return 1uz; }
};

int main() {
   std::multiset<int> m{};
   timeStuff("multiset           alleGleich        ", m, &alleGleich);
   timeStuff("multiset           gestreut          ", m, &gestreut);
   std::set<int> s{};
   timeStuff("set                alleGleich        ", s, &alleGleich);
   timeStuff("set                gestreut          ", s, &gestreut);
   std::unordered_multiset<int> um{};
   timeStuff("unordered_multiset alleGleich        ", um, &alleGleich);
   timeStuff("unordered_multiset gestreut          ", um, &gestreut);
   std::unordered_multiset<int,BadHash> umb{};
   timeStuff("unordered_multiset alleGleich badHash", umb, &alleGleich);
   timeStuff("unordered_multiset gestreut   badHash", umb, &gestreut);
}

Listing 24.76: Doppelt so viele Elemente bei schlechter Hashfunktion heißt viermal länger.

Book listing lst-0792-book.cpp:

// https://godbolt.org/z/osdTM7vbx 
#include <unordered_set>     // unordered_set, unordered_multiset
#include <iostream>
#include <string>
#include <chrono>            // Zeitmessung
using std::cout;
using namespace std::chrono;
long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start)
        .count();
}
struct BadHash {  // die schlechtestmögliche Hashfunktion als Funktor
    size_t   operator()(int) const { return 1uz; }
};
void timeStuff(size_t iters) {
    std::unordered_multiset<int,BadHash> data{};
    cout << iters << "...";
    auto start = steady_clock::now();
    for(size_t idx=0; idx<iters; ++idx) {
        data.insert( (int)idx );
    }
    cout << " " << millisSeit(start) << " ms" << std::endl;
}
constexpr size_t LIMIT = 20'000;
int main() {
    size_t iters = 100;
    while(iters < LIMIT) {
        timeStuff(iters);
        iters *= 2; // verdoppeln
    }
}

Godbolt Listing lst-0792-godb.cpp, https://godbolt.org/z/osdTM7vbx:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/osdTM7vbx 
#include <unordered_set>     // unordered_set, unordered_multiset
#include <iostream>
#include <string>
#include <chrono>            // Zeitmessung
using std::cout;
using namespace std::chrono;
long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start)
        .count();
}
struct BadHash {  // die schlechtestmögliche Hashfunktion als Funktor
    size_t   operator()(int) const { return 1uz; }
};
void timeStuff(size_t iters) {
    std::unordered_multiset<int,BadHash> data{};
    cout << iters << "...";
    auto start = steady_clock::now();
    for(size_t idx=0; idx<iters; ++idx) {
        data.insert( (int)idx );
    }
    cout << " " << millisSeit(start) << " ms" << std::endl;
}
constexpr size_t LIMIT = 20'000;
int main() {
    size_t iters = 100;
    while(iters < LIMIT) {
        timeStuff(iters);
        iters *= 2; // verdoppeln
    }
}

Listing 24.77: Dies ist die Schablone für die Beispiellistings zu »unordered_set«.

Book listing lst-0793-book.cpp:

// https://godbolt.org/z/xv6vrcsY6 
#include <unordered_set>
#include <iostream>
using std::unordered_set; using std::cout; using std::ostream;
template<typename Elem, typename Cmp>
ostream& operator<<=(ostream&os, const unordered_set<Elem,Cmp>&data){
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Godbolt Listing lst-0793-godb.cpp, https://godbolt.org/z/xv6vrcsY6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xv6vrcsY6 
#include <unordered_set>
#include <iostream>
using std::unordered_set; using std::cout; using std::ostream;
template<typename Elem, typename Cmp>
ostream& operator<<=(ostream&os, const unordered_set<Elem,Cmp>&data){
    for(auto &e : data) {
        os << e << ' ';
    }
    return os << '\n'; // '<<=' statt '<<' für Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Listing 24.78: Ein »unordered_set« mit eigenem Vergleich und Hashfunktion

Book listing lst-0794-book.cpp:

// https://godbolt.org/z/MWrY1cznd 
#include <unordered_set>
#include <iostream>
#include <vector>
#include <string>
using std::string; using std::unordered_set; using std::cout;
struct Word {
    string word_;
    size_t row_;
    Word(const string &word, size_t row)
        : word_{word}, row_{row} {}
    friend bool operator==(const Word& a, const Word &b)
        { return a.word_ == b.word_; } // ignoriert row
 };
 namespace std {
 template<> struct hash<Word> { // ignoriert row
        std::hash<string> stringHash;
        std::size_t operator()(const Word &w) const {
            return stringHash(w.word_);
        }
 }; }
 struct ExactWordHash { // bezieht row mit ein
     std::hash<string> sHash;
     std::hash<size_t> iHash;
     bool operator()(const Word& a) const {
         return sHash(a.word_) ^ iHash(a.row_);
     }
 };
 struct ExactWordEqual { // bezieht row mit ein
     bool operator()(const Word& a, const Word &b) const {
         return std::tie(a.word_, a.row_) == std::tie(b.word_, b.row_);
     }
 };
 int main() {
     std::vector input {
       Word{"eine",0}, Word{"Rose",0},
       Word{"ist",1}, Word{"eine",1}, Word{"Rose",1},
       Word{"ist",2}, Word{"eine",2}, Word{"Rose",2},  };
     // Überladungen nutzen
     unordered_set<Word> words( input.begin(), input.end() );
     cout << words.size() << '\n'; // Ausgabe: 3
     // Eigene Funktoren nutzen
     unordered_set<Word,ExactWordHash,ExactWordEqual> poem(
          input.begin(), input.end() );
     cout << poem.size() << '\n';  // Ausgabe: 8
     // Hash als Lambda
     auto h = [](const auto &a) { return std::hash<string>{}(a.word_); };
     unordered_set<Word,decltype(h)> rose(input.begin(), input.end(), 10, h);
     cout << rose.size() << '\n';  // Ausgabe: 3
 }

Godbolt Listing lst-0794-godb.cpp, https://godbolt.org/z/MWrY1cznd:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MWrY1cznd 
#include <unordered_set>
#include <iostream>
#include <vector>
#include <string>
using std::string; using std::unordered_set; using std::cout;
struct Word {
    string word_;
    size_t row_;
    Word(const string &word, size_t row)
        : word_{word}, row_{row} {}
    friend bool operator==(const Word& a, const Word &b)
        { return a.word_ == b.word_; } // ignoriert row
 };
 namespace std {
 template<> struct hash<Word> { // ignoriert row
        std::hash<string> stringHash;
        std::size_t operator()(const Word &w) const {
            return stringHash(w.word_);
        }
 }; }
 struct ExactWordHash { // bezieht row mit ein
     std::hash<string> sHash;
     std::hash<size_t> iHash;
     bool operator()(const Word& a) const {
         return sHash(a.word_) ^ iHash(a.row_);
     }
 };
 struct ExactWordEqual { // bezieht row mit ein
     bool operator()(const Word& a, const Word &b) const {
         return std::tie(a.word_, a.row_) == std::tie(b.word_, b.row_);
     }
 };
 int main() {
     std::vector input {
       Word{"eine",0}, Word{"Rose",0},
       Word{"ist",1}, Word{"eine",1}, Word{"Rose",1},
       Word{"ist",2}, Word{"eine",2}, Word{"Rose",2},  };
     // Überladungen nutzen
     unordered_set<Word> words( input.begin(), input.end() );
     cout << words.size() << '\n'; // Ausgabe: 3
     // Eigene Funktoren nutzen
     unordered_set<Word,ExactWordHash,ExactWordEqual> poem(
          input.begin(), input.end() );
     cout << poem.size() << '\n';  // Ausgabe: 8
     // Hash als Lambda
     auto h = [](const auto &a) { return std::hash<string>{}(a.word_); };
     unordered_set<Word,decltype(h)> rose(input.begin(), input.end(), 10, h);
     cout << rose.size() << '\n';  // Ausgabe: 3
 }

Listing 24.79: Dies sind die Möglichkeiten, ein »unordered_set« zu initialisieren.

Book listing lst-0796-book.cpp:

// https://godbolt.org/z/WeMr9ePdh 
#include <set>
template<typename Key>
std::set<Key> sorted(const unordered_set<Key> &data)
  { return std::set<Key>(data.begin(), data.end()); }
// …
// ohne Argumente
unordered_set<int> leer{};
cout <<= leer;      // Ausgabe:
// Initialisierungsliste
unordered_set daten{1,1,2,2,3,3,4,4,5,5};// doppelte werden nicht übernommen
cout <<= daten;     // Ausgabe in etwa: 5 4 3 2 1
// Kopie
unordered_set kopie(daten);
cout <<= kopie;     // Ausgabe in etwa: 5 4 3 2 1
// Bereich
auto so1 = sorted(daten);
unordered_set bereich(std::next(so1.begin()), std::prev(so1.end()));
cout <<= bereich;   // Ausgabe in etwa: 2 3 4

Godbolt Listing lst-0796-godb.cpp, https://godbolt.org/z/WeMr9ePdh:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WeMr9ePdh 
#include <set>
template<typename Key>
std::set<Key> sorted(const unordered_set<Key> &data)
  { return std::set<Key>(data.begin(), data.end()); }
// …
// ohne Argumente
unordered_set<int> leer{};
cout <<= leer;      // Ausgabe:
// Initialisierungsliste
unordered_set daten{1,1,2,2,3,3,4,4,5,5};// doppelte werden nicht übernommen
cout <<= daten;     // Ausgabe in etwa: 5 4 3 2 1
// Kopie
unordered_set kopie(daten);
cout <<= kopie;     // Ausgabe in etwa: 5 4 3 2 1
// Bereich
auto so1 = sorted(daten);
unordered_set bereich(std::next(so1.begin()), std::prev(so1.end()));
cout <<= bereich;   // Ausgabe in etwa: 2 3 4

Listing 24.80: Einfügen in ein »unordered_set«

Book listing lst-0797-book.cpp:

// https://godbolt.org/z/KEb55ds4z 
unordered_set<int> data;
auto res1 = data.insert( 5 );                  // Einfügen per Kopie
if(res1.second) cout << "ja, 5 nun drin\n";    // das klappt
auto res2 = data.emplace( 5 );                 // Einfügen vor Ort
if(res2.second) cout << "zweite 5 nun drin\n"; // das klappt nicht
auto res3 = data.insert(res1.first, 6 );       // mit Positionshinweis
// res3 ist nur ein iterator ohne bool
cout << *res3 << '\n';                         // auf jeden Fall eine 6

Godbolt Listing lst-0797-godb.cpp, https://godbolt.org/z/KEb55ds4z:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KEb55ds4z 
unordered_set<int> data;
auto res1 = data.insert( 5 );                  // Einfügen per Kopie
if(res1.second) cout << "ja, 5 nun drin\n";    // das klappt
auto res2 = data.emplace( 5 );                 // Einfügen vor Ort
if(res2.second) cout << "zweite 5 nun drin\n"; // das klappt nicht
auto res3 = data.insert(res1.first, 6 );       // mit Positionshinweis
// res3 ist nur ein iterator ohne bool
cout << *res3 << '\n';                         // auf jeden Fall eine 6

Listing 24.81: Löschen erhält die Reihenfolge der restlichen Elemente.

Book listing lst-0798-book.cpp:

// https://godbolt.org/z/1s41eaWjx 
unordered_set nums{ 1,2,3,4,5,6,7,8,9,10 };
cout <<= nums;               // Ausgabe ähnlich: 9 1 2 3 4 5 6 7 8 10
auto it = nums.begin();
while(it != nums.end()) {
    if(*it % 2 == 0) {       // gerade Zahl?
        it = nums.erase(it); // Restelemente verändern nicht Reihenfolge
    } else {
        ++it;
    }
}
cout <<= nums;               // Ausgabe ähnlich: 9 1 3 5 7

Godbolt Listing lst-0798-godb.cpp, https://godbolt.org/z/1s41eaWjx:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1s41eaWjx 
unordered_set nums{ 1,2,3,4,5,6,7,8,9,10 };
cout <<= nums;               // Ausgabe ähnlich: 9 1 2 3 4 5 6 7 8 10
auto it = nums.begin();
while(it != nums.end()) {
    if(*it % 2 == 0) {       // gerade Zahl?
        it = nums.erase(it); // Restelemente verändern nicht Reihenfolge
    } else {
        ++it;
    }
}
cout <<= nums;               // Ausgabe ähnlich: 9 1 3 5 7

Listing 24.82: Sie können eimerweise auf »unordered_set« zugreifen.

Book listing lst-0799-book.cpp:

// https://godbolt.org/z/TTbY8YbG9 
// Befüllen mit 100 Werten
unordered_set<int> d{};
d.rehash(10);             // versuche, 10 Eimer zu haben
d.max_load_factor(100.0); // 100 Elemente pro Eimer sind okay
cout << "Eimer Anzahl: " << d.bucket_count() << '\n';
for(int x : std::ranges::iota_view{0,100}) { // C++20 iota(): 0,1,2,…,99
    d.insert(x);
}
// ausgeben
for(int b = d.bucket_count()-1; b>=0; --b) {
    cout << "Eimer "<<b<<":";
    for(auto it=d.begin(b); it!=d.end(b); ++it)
        cout << *it << ' ';
    cout << '\n';
}

Godbolt Listing lst-0799-godb.cpp, https://godbolt.org/z/TTbY8YbG9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TTbY8YbG9 
// Befüllen mit 100 Werten
unordered_set<int> d{};
d.rehash(10);             // versuche, 10 Eimer zu haben
d.max_load_factor(100.0); // 100 Elemente pro Eimer sind okay
cout << "Eimer Anzahl: " << d.bucket_count() << '\n';
for(int x : std::ranges::iota_view{0,100}) { // C++20 iota(): 0,1,2,…,99
    d.insert(x);
}
// ausgeben
for(int b = d.bucket_count()-1; b>=0; --b) {
    cout << "Eimer "<<b<<":";
    for(auto it=d.begin(b); it!=d.end(b); ++it)
        cout << *it << ' ';
    cout << '\n';
}

Listing 24.83: Dies ist die Schablone für die Beispiellistings zu »unordered_map«.

Book listing lst-0800-book.cpp:

// https://godbolt.org/z/ffashhsK1 
#include <unordered_map>
#include <iostream>
using std::unordered_map; using std::cout;
template<typename K, typename T>
std::ostream& operator<<=(std::ostream&os, const unordered_map<K,T>&data) {
    for(auto &e : data) {
        os << e.first << ":" << e.second << ' ';
    }
    return os << '\n'; // bei operator<<= mit Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Godbolt Listing lst-0800-godb.cpp, https://godbolt.org/z/ffashhsK1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ffashhsK1 
#include <unordered_map>
#include <iostream>
using std::unordered_map; using std::cout;
template<typename K, typename T>
std::ostream& operator<<=(std::ostream&os, const unordered_map<K,T>&data) {
    for(auto &e : data) {
        os << e.first << ":" << e.second << ' ';
    }
    return os << '\n'; // bei operator<<= mit Zeilenumbruch
}
int main() {
   // Beispielcode hier
}

Listing 24.84: Ein eigener Datentyp als Schlüssel in einer »unordered_map«

Book listing lst-0801-book.cpp:

// https://godbolt.org/z/Ka3czrn54 
#include <unordered_map>
#include <iostream>
#include <string>
using std::string; using std::unordered_map; using std::cout;
struct Stadt {
    string name_;
    explicit Stadt(const string &name) : name_{name} {}
    auto operator<=>(const Stadt &b) const = default;
 };
 struct StadtHash {
     std::hash<string> sHash;
     size_t operator()(const Stadt& a) const {
         return sHash(a.name_);
     }
 };
 int main() {
     unordered_map<Stadt,string,StadtHash> abk{
         {Stadt{"Bielefeld"}, "BI"},
         {Stadt{"Jetzendorf"}, "JE"},
         {Stadt{"Tharandt"}, "TH"},
         };
     cout << abk[Stadt{"Bielefeld"}] << '\n'; // Ausgabe: BI
 }

Godbolt Listing lst-0801-godb.cpp, https://godbolt.org/z/Ka3czrn54:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ka3czrn54 
#include <unordered_map>
#include <iostream>
#include <string>
using std::string; using std::unordered_map; using std::cout;
struct Stadt {
    string name_;
    explicit Stadt(const string &name) : name_{name} {}
    auto operator<=>(const Stadt &b) const = default;
 };
 struct StadtHash {
     std::hash<string> sHash;
     size_t operator()(const Stadt& a) const {
         return sHash(a.name_);
     }
 };
 int main() {
     unordered_map<Stadt,string,StadtHash> abk{
         {Stadt{"Bielefeld"}, "BI"},
         {Stadt{"Jetzendorf"}, "JE"},
         {Stadt{"Tharandt"}, "TH"},
         };
     cout << abk[Stadt{"Bielefeld"}] << '\n'; // Ausgabe: BI
 }

Listing 24.85: Sie können auch nur einen Teil Ihres Objekts als Schlüssel verwenden.

Book listing lst-0802-book.cpp:

// https://godbolt.org/z/eTYqbedqK 
#include <unordered_set> // unordered_multiset
#include <iostream>
#include <string>
using std::string; using std::unordered_multiset; using std::cout;
struct Stadt {
    string name_;
    explicit Stadt(const string &name) : name_{name} {}
    auto operator<=>(const Stadt &b) const = default;
 };
 struct Eintrag { string stadt_; int plz_; };
 struct EqEintrag {
     bool operator()(const Eintrag&a, const Eintrag&b) const {
         return a.stadt_==b.stadt_;
     }
 };
 struct HashEintrag {
     std::hash<string> sHash;
     size_t operator()(const Eintrag& a) const {
         return sHash(a.stadt_);
     }
 };
 int main() {
     unordered_multiset<Eintrag,HashEintrag,EqEintrag> verzeichnis{
         {Eintrag{"Bielefeld", 33615}},
         {Eintrag{"Bielefeld", 33617}},
         {Eintrag{"Bielefeld", 33621}},
         {Eintrag{"Berlin", 10032}},
         {Eintrag{"Berlin", 10027}},
         };
     const Eintrag such{"Bielefeld", 0}; // plz spielt bei Suche keine Rolle
     cout<<"Bielefeld hat "<<verzeichnis.count(such)<<" Postleitzahlen.\n";
     cout<<"Die Postleitzahlen von Bielefeld sind:\n";
     auto [wo, bis] = verzeichnis.equal_range(such);
     while(wo != bis) {
         cout << "  " << wo->plz_ << '\n';
         ++wo;
     }
 }

Godbolt Listing lst-0802-godb.cpp, https://godbolt.org/z/eTYqbedqK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eTYqbedqK 
#include <unordered_set> // unordered_multiset
#include <iostream>
#include <string>
using std::string; using std::unordered_multiset; using std::cout;
struct Stadt {
    string name_;
    explicit Stadt(const string &name) : name_{name} {}
    auto operator<=>(const Stadt &b) const = default;
 };
 struct Eintrag { string stadt_; int plz_; };
 struct EqEintrag {
     bool operator()(const Eintrag&a, const Eintrag&b) const {
         return a.stadt_==b.stadt_;
     }
 };
 struct HashEintrag {
     std::hash<string> sHash;
     size_t operator()(const Eintrag& a) const {
         return sHash(a.stadt_);
     }
 };
 int main() {
     unordered_multiset<Eintrag,HashEintrag,EqEintrag> verzeichnis{
         {Eintrag{"Bielefeld", 33615}},
         {Eintrag{"Bielefeld", 33617}},
         {Eintrag{"Bielefeld", 33621}},
         {Eintrag{"Berlin", 10032}},
         {Eintrag{"Berlin", 10027}},
         };
     const Eintrag such{"Bielefeld", 0}; // plz spielt bei Suche keine Rolle
     cout<<"Bielefeld hat "<<verzeichnis.count(such)<<" Postleitzahlen.\n";
     cout<<"Die Postleitzahlen von Bielefeld sind:\n";
     auto [wo, bis] = verzeichnis.equal_range(such);
     while(wo != bis) {
         cout << "  " << wo->plz_ << '\n';
         ++wo;
     }
 }

GodboltId:9szMGYK9v

Book listing lst-0804-book.cpp:

// https://godbolt.org/z/9szMGYK9v 
struct EqEintrag {
    bool operator()(const Eintrag&a, const Eintrag&b) const {
        return a.stadt_==b.stadt_;
    }
};

struct HashEintrag {
    std::hash<string> sHash;
    std::hash<int> iHash;
    size_t operator()(const Eintrag& a) const {
        return sHash(a.stadt_) ^ iHash(a.plz_); //                                          (ERR)  zu viele Elemente
    }
};

Godbolt Listing lst-0804-godb.cpp, https://godbolt.org/z/9szMGYK9v:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9szMGYK9v 
struct EqEintrag {
    bool operator()(const Eintrag&a, const Eintrag&b) const {
        return a.stadt_==b.stadt_;
    }
};

struct HashEintrag {
    std::hash<string> sHash;
    std::hash<int> iHash;
    size_t operator()(const Eintrag& a) const {
        return sHash(a.stadt_) ^ iHash(a.plz_); //                                          (ERR)  zu viele Elemente
    }
};

Listing 24.86: Dies sind die Möglichkeiten, ein »unordered_multiset« zu initialisieren.

Book listing lst-0805-book.cpp:

// https://godbolt.org/z/qnove9h8o 
#include <unordered_set> // unordered_multiset
#include <vector>
#include <iostream>
using std::unordered_multiset; using std::cout; using std::ostream;
template<typename Elem>
ostream& operator<<=(ostream&os, const unordered_multiset<Elem>&data) {
    for(auto &e : data) { os << e << ' '; } return os << '\n'; }
int main() {
    // ohne Argumente
    unordered_multiset<int> leer(1000); // anfängliche Größe der Hashtabelle
    cout <<= leer;      // Ausgabe:
    // Initialisierungsliste; doppelte werden übernommen:
    unordered_multiset daten{ 1,1,2,2,3,3,4,4,5,5 };
    cout <<= daten;     // Ausgabe in etwa: 5 5 4 4 3 3 2 2 1 1
    // Kopie
    unordered_multiset kopie(daten);
    cout <<= kopie;     // Ausgabe in etwa: 5 5 4 4 3 3 2 2 1 1
    // Bereich
    std::vector in{1,2,3,10,20,30,10,20,30,1,2,3};
    unordered_multiset bereich(in.begin()+3, in.end()-3);
    cout <<= bereich;   // Ausgabe in etwa: 30 30 20 20 10 10
}

Godbolt Listing lst-0805-godb.cpp, https://godbolt.org/z/qnove9h8o:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qnove9h8o 
#include <unordered_set> // unordered_multiset
#include <vector>
#include <iostream>
using std::unordered_multiset; using std::cout; using std::ostream;
template<typename Elem>
ostream& operator<<=(ostream&os, const unordered_multiset<Elem>&data) {
    for(auto &e : data) { os << e << ' '; } return os << '\n'; }
int main() {
    // ohne Argumente
    unordered_multiset<int> leer(1000); // anfängliche Größe der Hashtabelle
    cout <<= leer;      // Ausgabe:
    // Initialisierungsliste; doppelte werden übernommen:
    unordered_multiset daten{ 1,1,2,2,3,3,4,4,5,5 };
    cout <<= daten;     // Ausgabe in etwa: 5 5 4 4 3 3 2 2 1 1
    // Kopie
    unordered_multiset kopie(daten);
    cout <<= kopie;     // Ausgabe in etwa: 5 5 4 4 3 3 2 2 1 1
    // Bereich
    std::vector in{1,2,3,10,20,30,10,20,30,1,2,3};
    unordered_multiset bereich(in.begin()+3, in.end()-3);
    cout <<= bereich;   // Ausgabe in etwa: 30 30 20 20 10 10
}

Listing 24.87: Bei den »multi«-Varianten ergibt »count« richtig Sinn.

Book listing lst-0806-book.cpp:

// https://godbolt.org/z/a8cGxr9s9 
#include <unordered_set> // unordered_multiset
#include <iostream>
#include <string>
using std::unordered_multiset; using std::cout; using std::string;
int main() {
    const string in = "Keines meiner beiden Beine zeigt einen Schein.";
    unordered_multiset<int> cs(in.begin(), in.end()); // string als Container
    cout << cs.count( 'e' ) << " Mal e\n"; // Ausgabe: 10 Mal e
}

Godbolt Listing lst-0806-godb.cpp, https://godbolt.org/z/a8cGxr9s9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a8cGxr9s9 
#include <unordered_set> // unordered_multiset
#include <iostream>
#include <string>
using std::unordered_multiset; using std::cout; using std::string;
int main() {
    const string in = "Keines meiner beiden Beine zeigt einen Schein.";
    unordered_multiset<int> cs(in.begin(), in.end()); // string als Container
    cout << cs.count( 'e' ) << " Mal e\n"; // Ausgabe: 10 Mal e
}

Listing 24.88: Adapter funktionieren mit wechselbaren Implementierungen.

Book listing lst-0807-book.cpp:

// https://godbolt.org/z/qaKv6Tebf 
#include <stack>
void run(auto data) { /* ... */ }  // C++20, abgekürztes Funktionstemplate
run(stack<int>{});              // Default: nutzt vector<int>
run(stack<int,vector<int>>{});  // wie der Default
run(stack<int,list<int>>{});    // nutzt list<int>

Godbolt Listing lst-0807-godb.cpp, https://godbolt.org/z/qaKv6Tebf:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qaKv6Tebf 
#include <stack>
void run(auto data) { /* ... */ }  // C++20, abgekürztes Funktionstemplate
run(stack<int>{});              // Default: nutzt vector<int>
run(stack<int,vector<int>>{});  // wie der Default
run(stack<int,list<int>>{});    // nutzt list<int>

Listing 24.89: »string« eignet sich besser für Texte als »vector«.

Book listing lst-0808-book.cpp:

// https://godbolt.org/z/6sYGnqnTj 
#include <vector>
#include <string>
#include <iostream>
#include <string_view>
using std::string; using std::string_view; using std::vector; using std::cout;
int get_len(string_view str) { return str.size(); } // string_view als Parameter
int main() {
    string s1 = "Hallo";                  // einfach mit Stringliteral
    string s2{'H','a','l','l','o'};       // oder mit Liste von char
    using namespace std::literals;        // für ""s-Suffix und ""sv-Suffix
    auto s3 = "Hallo"s;  // noch einfacher mit echtem Stringliteral
    vector<char> v1{"Hallo"};             //                          (ERR)  kein vector mit Stringliteral
    vector<char> v2{'H','a','l','l','o'}; // Liste von char ist okay
    cout << s1 << s2 << s3 << '\n';       // Ausgabe von string geht
    cout << v1 << v2 << '\n';             //                          (ERR)  vector hat keine Ausgabe
    const auto str = "String"s;           // Stringliteral
    const auto strv = "String-View"sv;    // String-View-Literal
    cout << "Laenge von 'str' ist " << get_len(str) << '\n';   // Ausgabe: … 6
    cout << "Laenge von 'strv' ist " << get_len(strv) << '\n'; // Ausgabe: … 11
}

Godbolt Listing lst-0808-godb.cpp, https://godbolt.org/z/6sYGnqnTj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6sYGnqnTj 
#include <vector>
#include <string>
#include <iostream>
#include <string_view>
using std::string; using std::string_view; using std::vector; using std::cout;
int get_len(string_view str) { return str.size(); } // string_view als Parameter
int main() {
    string s1 = "Hallo";                  // einfach mit Stringliteral
    string s2{'H','a','l','l','o'};       // oder mit Liste von char
    using namespace std::literals;        // für ""s-Suffix und ""sv-Suffix
    auto s3 = "Hallo"s;  // noch einfacher mit echtem Stringliteral
    vector<char> v1{"Hallo"};             //                          (ERR)  kein vector mit Stringliteral
    vector<char> v2{'H','a','l','l','o'}; // Liste von char ist okay
    cout << s1 << s2 << s3 << '\n';       // Ausgabe von string geht
    cout << v1 << v2 << '\n';             //                          (ERR)  vector hat keine Ausgabe
    const auto str = "String"s;           // Stringliteral
    const auto strv = "String-View"sv;    // String-View-Literal
    cout << "Laenge von 'str' ist " << get_len(str) << '\n';   // Ausgabe: … 6
    cout << "Laenge von 'strv' ist " << get_len(strv) << '\n'; // Ausgabe: … 11
}

Listing 24.90: »bitset« im Beispiel

Book listing lst-0809-book.cpp:

// https://godbolt.org/z/jrGdT6665 
#include <bitset>
#include <iostream>
using std::cout;
int main() {
    std::bitset<8> bits{};         // 8 Bit dicht gepackt
    bits.set(4);                   // 5. Bit auf 1
    cout << bits << '\n';          // 00010000
    bits.flip();                   // alle Bits invertieren
    cout << bits << '\n';          // 11101111
    bits.set();                    // alle Bits auf 1
    bits.flip(1);                  // 2. Bit invertieren
    std::cout << bits << '\n';     // 11111101
    bits.reset();                  // alle Bits auf 0
    bits.set(4);                   // 5. Bit auf 1
    cout << bits << '\n';          // 00010000
    bits.flip();                   // alle Bits invertieren
    cout << bits << '\n';          // 11101111
    bits.set();                    // alle Bits auf 1
    bits.flip(1);                  // 2. Bit invertieren
    bits.flip(6);                  // 7. Bit invertieren
    cout << bits << '\n';          // 10111101
    // Verknüpfungen
    std::bitset<8> zack("....####", 8, '.', '#');
    cout << zack << '\n';          // 00001111
    cout << (bits & zack) << '\n'; // 00001101
    cout << (bits | zack) << '\n'; // 10111111
    cout << (bits ^ zack) << '\n'; // 10110010
    // andere Integertypen
    std::bitset<64> b(0x123456789abcdef0LL);
    cout << b << '\n';
    // 0001001000110100010101100111100010011010101111001101111011110000
    cout << std::hex << b.to_ullong() << '\n'; // umwandeln
    // 123456789abcdef0
}

Godbolt Listing lst-0809-godb.cpp, https://godbolt.org/z/jrGdT6665:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jrGdT6665 
#include <bitset>
#include <iostream>
using std::cout;
int main() {
    std::bitset<8> bits{};         // 8 Bit dicht gepackt
    bits.set(4);                   // 5. Bit auf 1
    cout << bits << '\n';          // 00010000
    bits.flip();                   // alle Bits invertieren
    cout << bits << '\n';          // 11101111
    bits.set();                    // alle Bits auf 1
    bits.flip(1);                  // 2. Bit invertieren
    std::cout << bits << '\n';     // 11111101
    bits.reset();                  // alle Bits auf 0
    bits.set(4);                   // 5. Bit auf 1
    cout << bits << '\n';          // 00010000
    bits.flip();                   // alle Bits invertieren
    cout << bits << '\n';          // 11101111
    bits.set();                    // alle Bits auf 1
    bits.flip(1);                  // 2. Bit invertieren
    bits.flip(6);                  // 7. Bit invertieren
    cout << bits << '\n';          // 10111101
    // Verknüpfungen
    std::bitset<8> zack("....####", 8, '.', '#');
    cout << zack << '\n';          // 00001111
    cout << (bits & zack) << '\n'; // 00001101
    cout << (bits | zack) << '\n'; // 10111111
    cout << (bits ^ zack) << '\n'; // 10110010
    // andere Integertypen
    std::bitset<64> b(0x123456789abcdef0LL);
    cout << b << '\n';
    // 0001001000110100010101100111100010011010101111001101111011110000
    cout << std::hex << b.to_ullong() << '\n'; // umwandeln
    // 123456789abcdef0
}

GodboltId:KPP16bdK9

Book listing lst-0810-book.cpp:

// https://godbolt.org/z/KPP16bdK9 
#include <iostream>
#include <valarray>
using std::ostream; using std::valarray;
ostream& operator<<(ostream&os, const valarray<double>&vs) {
    os << "[";
    for(auto&v : vs) os << v << " ";
    return os << "]";
}
int main() {
    valarray a{ 1.0, 2.0, 3.0, 4.0 }; // valarray<double>
    valarray b{ 2.0, 4.0, 6.0, 8.0 };
    valarray c{ 2.5, 1.75, 0.5, 0.125 };
    valarray<double> x = ( a + b ) * c;
    std::cout << "x: " << x << "\n";  // Ausgabe: [7.5 10.5 4.5 1.5 ]
    auto y = ( a + b ) / 2;           // y ist nicht unbedingt ein valarray!
    std::cout << "y: " << y << "\n";  // Ausgabe: [1.5 3 4.5 6 ]
}

Godbolt Listing lst-0810-godb.cpp, https://godbolt.org/z/KPP16bdK9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KPP16bdK9 
#include <iostream>
#include <valarray>
using std::ostream; using std::valarray;
ostream& operator<<(ostream&os, const valarray<double>&vs) {
    os << "[";
    for(auto&v : vs) os << v << " ";
    return os << "]";
}
int main() {
    valarray a{ 1.0, 2.0, 3.0, 4.0 }; // valarray<double>
    valarray b{ 2.0, 4.0, 6.0, 8.0 };
    valarray c{ 2.5, 1.75, 0.5, 0.125 };
    valarray<double> x = ( a + b ) * c;
    std::cout << "x: " << x << "\n";  // Ausgabe: [7.5 10.5 4.5 1.5 ]
    auto y = ( a + b ) / 2;           // y ist nicht unbedingt ein valarray!
    std::cout << "y: " << y << "\n";  // Ausgabe: [1.5 3 4.5 6 ]
}

GodboltId:r11584Wef

Book listing lst-0811-book.cpp:

// https://godbolt.org/z/r11584Wef 
#include <valarray>
#include <iostream>
using namespace std;
template<typename T>
ostream& operator<<=(ostream &os, const valarray<T>& a) { // '<<=' mit Newline
    for(const auto &v : a) os << v << ' ';
    return os << '\n';
}
int main() {
    // … Beispielcode hier …
}

Godbolt Listing lst-0811-godb.cpp, https://godbolt.org/z/r11584Wef:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r11584Wef 
#include <valarray>
#include <iostream>
using namespace std;
template<typename T>
ostream& operator<<=(ostream &os, const valarray<T>& a) { // '<<=' mit Newline
    for(const auto &v : a) os << v << ' ';
    return os << '\n';
}
int main() {
    // … Beispielcode hier …
}

GodboltId:WGazqoGc1

Book listing lst-0812-book.cpp:

// https://godbolt.org/z/WGazqoGc1 
valarray<int> data;              // zunächst Größe 0
cout << data.size() << "\n";     // Ausgabe: 0
data.resize(100);                // vergrößert
cout << data.size() << "\n";     // Ausgabe: 100
valarray<int> data2(200);        // Platz für 200 Werte
cout << data2.size() << "\n";    // Ausgabe: 200
valarray<int> dataC(5, 20);      // zwanzig 5en, andersherum als bei vector
cout << dataC.size() <<": dataC[6]="<< dataC[6]<< "\n"; // Ausgabe: 20: dataC[6]=5
valarray dataD{ 2, 3, 5, 7, 11 };      // valarray<int>, Initialisierungsliste
cout << dataD.size() <<": dataD[3]=" <<dataD[3]<< "\n"; // Ausgabe: 5: dataD[3]=7

Godbolt Listing lst-0812-godb.cpp, https://godbolt.org/z/WGazqoGc1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WGazqoGc1 
valarray<int> data;              // zunächst Größe 0
cout << data.size() << "\n";     // Ausgabe: 0
data.resize(100);                // vergrößert
cout << data.size() << "\n";     // Ausgabe: 100
valarray<int> data2(200);        // Platz für 200 Werte
cout << data2.size() << "\n";    // Ausgabe: 200
valarray<int> dataC(5, 20);      // zwanzig 5en, andersherum als bei vector
cout << dataC.size() <<": dataC[6]="<< dataC[6]<< "\n"; // Ausgabe: 20: dataC[6]=5
valarray dataD{ 2, 3, 5, 7, 11 };      // valarray<int>, Initialisierungsliste
cout << dataD.size() <<": dataD[3]=" <<dataD[3]<< "\n"; // Ausgabe: 5: dataD[3]=7

GodboltId:dd1q6GdYq

Book listing lst-0813-book.cpp:

// https://godbolt.org/z/dd1q6GdYq 
valarray v { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
valarray<int> r1(v[slice(0, 4, 3)]); // Start bei 0, 4 Elemente, Schrittweite 3
cout <<= r1;                         // Ausgabe: 1 4 7 10
valarray<int> r2(v[v > 6]);          // adressiert per valarray<bool>
cout <<= r2;                         // Ausgabe: 7 8 9 10 11 12
const valarray<size_t> indirekt{ 2, 2, 3, 6 };  // doppelte erlaubt
valarray<int> r5(v[indirekt]);       // adressiert per valarray<size_t>
cout <<= r5;                         // Ausgabe: 3 3 4 7

Godbolt Listing lst-0813-godb.cpp, https://godbolt.org/z/dd1q6GdYq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dd1q6GdYq 
valarray v { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
valarray<int> r1(v[slice(0, 4, 3)]); // Start bei 0, 4 Elemente, Schrittweite 3
cout <<= r1;                         // Ausgabe: 1 4 7 10
valarray<int> r2(v[v > 6]);          // adressiert per valarray<bool>
cout <<= r2;                         // Ausgabe: 7 8 9 10 11 12
const valarray<size_t> indirekt{ 2, 2, 3, 6 };  // doppelte erlaubt
valarray<int> r5(v[indirekt]);       // adressiert per valarray<size_t>
cout <<= r5;                         // Ausgabe: 3 3 4 7

GodboltId:6z6d71Ka4

Book listing lst-0814-book.cpp:

// https://godbolt.org/z/6z6d71Ka4 
valarray<int> v {
  1,  2,  3,
  4,  5,  6,
  7,  8,  9,
 10, 11, 12 };
v[slice(0, 4, 3)] *= valarray<int>(v[slice(0, 4, 3)]); // erste Spalte quadrieren
cout <<= v;  // Ausgabe: 1 2 3 16 5 6 49 8 9 100 11 12
v[slice(0, 4, 3)] = valarray<int>{1, 4, 7, 10}; // wiederherstellen
valarray<int> r3(v[gslice(0, {2, 3}, {6,2})]);  // 2-D-Schnitt vom 3-D-Würfel
cout <<= r3;                                    // Ausgabe: 1 3 5 7 9 11
valarray<char> text("jetzt gehts erst los", 20);
valarray<char> caps("JGEL", 4);
valarray<size_t> idx{ 0, 6, 12, 17 };           // Indexe in text
text[idx] = caps;                               // indirekt zuweisen
cout <<= text;                                  // Ausgabe: Jetzt Gehts Erst Los

Godbolt Listing lst-0814-godb.cpp, https://godbolt.org/z/6z6d71Ka4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6z6d71Ka4 
valarray<int> v {
  1,  2,  3,
  4,  5,  6,
  7,  8,  9,
 10, 11, 12 };
v[slice(0, 4, 3)] *= valarray<int>(v[slice(0, 4, 3)]); // erste Spalte quadrieren
cout <<= v;  // Ausgabe: 1 2 3 16 5 6 49 8 9 100 11 12
v[slice(0, 4, 3)] = valarray<int>{1, 4, 7, 10}; // wiederherstellen
valarray<int> r3(v[gslice(0, {2, 3}, {6,2})]);  // 2-D-Schnitt vom 3-D-Würfel
cout <<= r3;                                    // Ausgabe: 1 3 5 7 9 11
valarray<char> text("jetzt gehts erst los", 20);
valarray<char> caps("JGEL", 4);
valarray<size_t> idx{ 0, 6, 12, 17 };           // Indexe in text
text[idx] = caps;                               // indirekt zuweisen
cout <<= text;                                  // Ausgabe: Jetzt Gehts Erst Los

GodboltId:jr1chqbze

Book listing lst-0815-book.cpp:

// https://godbolt.org/z/jr1chqbze 
#include <iostream>
#include <iomanip> // setw
#include <valarray>
using namespace std;

/* Matrix drucken */
template<class T>
void printMatrix(ostream&os, const valarray<T>& a, size_t n) {
    for(size_t i = 0; i < (n*n); ++i) {
        os << setw(3) << a[i];        // Wert drucken
        os << ((i+1)%n ? ' ' : '\n'); // nächste Zeile?
    }
}

/* Matrix-Kreuzprodukt */
template<class T>

valarray<T> matmult(
        const valarray<T>& a, size_t arows, size_t acols,
        const valarray<T>& b, size_t brows, size_t bcols)
{
    /* Bedingung: acols==brows */
    valarray<T> result(arows * bcols);
    for(size_t i = 0; i < arows; ++i) {
      for(size_t j = 0; j < bcols; ++j) {
        auto row = a[slice(acols*i, acols, 1)]; // Zeile
        auto col = b[slice(j, brows, bcols)];   // Spalte
        result[i*bcols+j] = (row*col).sum();    // Kreuzprodukt Zeile a[i] und 
                                                // Spalte b[j]
      }
    }
    return result;
}

int main() {
    constexpr int n = 3;
    valarray ma{1,0,-1,  2,2,-3,  3,4,0};         // 3 x 3-Matrix
    valarray mb{3,4,-1,  1,-3,0,  -1,1,2};        // 3 x 3-Matrix
    printMatrix(cout, ma, n);
    cout << "  -mal-\n ";
    printMatrix(cout, mb, n);
    cout << "  -ergibt-:\n ";
    valarray<int> mc = matmult(ma, n,n, mb, n,n);
    printMatrix(cout, mc, n);
}

Godbolt Listing lst-0815-godb.cpp, https://godbolt.org/z/jr1chqbze:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jr1chqbze 
#include <iostream>
#include <iomanip> // setw
#include <valarray>
using namespace std;

/* Matrix drucken */
template<class T>
void printMatrix(ostream&os, const valarray<T>& a, size_t n) {
    for(size_t i = 0; i < (n*n); ++i) {
        os << setw(3) << a[i];        // Wert drucken
        os << ((i+1)%n ? ' ' : '\n'); // nächste Zeile?
    }
}

/* Matrix-Kreuzprodukt */
template<class T>

valarray<T> matmult(
        const valarray<T>& a, size_t arows, size_t acols,
        const valarray<T>& b, size_t brows, size_t bcols)
{
    /* Bedingung: acols==brows */
    valarray<T> result(arows * bcols);
    for(size_t i = 0; i < arows; ++i) {
      for(size_t j = 0; j < bcols; ++j) {
        auto row = a[slice(acols*i, acols, 1)]; // Zeile
        auto col = b[slice(j, brows, bcols)];   // Spalte
        result[i*bcols+j] = (row*col).sum();    // Kreuzprodukt Zeile a[i] und 
                                                // Spalte b[j]
      }
    }
    return result;
}

int main() {
    constexpr int n = 3;
    valarray ma{1,0,-1,  2,2,-3,  3,4,0};         // 3 x 3-Matrix
    valarray mb{3,4,-1,  1,-3,0,  -1,1,2};        // 3 x 3-Matrix
    printMatrix(cout, ma, n);
    cout << "  -mal-\n ";
    printMatrix(cout, mb, n);
    cout << "  -ergibt-:\n ";
    valarray<int> mc = matmult(ma, n,n, mb, n,n);
    printMatrix(cout, mc, n);
}

Listing 25.1: Mit dem Eingabevektor wird etwas gemacht, aber was?

Book listing lst-0816-book.cpp:

// https://godbolt.org/z/5czT3xoxc 
std::vector v{0,1,3,5,7,9,2,4,6,8};
bool flag = true;
for(size_t i=1; (i <= v.size()) && flag; ++i) {
    flag = false;
    for(size_t j=0; (j < v.size()-1); ++j) {
        if(v[j+1] < v[j]) {
            std::swap(v[j+1], v[j]);
            flag = true;
        }
    }
}
for(int i:v) std::cout << i << ' ';

Godbolt Listing lst-0816-godb.cpp, https://godbolt.org/z/5czT3xoxc:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5czT3xoxc 
std::vector v{0,1,3,5,7,9,2,4,6,8};
bool flag = true;
for(size_t i=1; (i <= v.size()) && flag; ++i) {
    flag = false;
    for(size_t j=0; (j < v.size()-1); ++j) {
        if(v[j+1] < v[j]) {
            std::swap(v[j+1], v[j]);
            flag = true;
        }
    }
}
for(int i:v) std::cout << i << ' ';

Listing 25.2: Dieser Eingabevektor wird sortiert!

Book listing lst-0817-book.cpp:

// https://godbolt.org/z/EjT7nPPv7 
std::vector v{0,1,3,5,7,9,2,4,6,8};
std::sort(v.begin(), v.end());
for(int i:v) std::cout << i << ' ';
std::cout << '\n';
// oder mit einer Range:
std::ranges::sort(v);
for(int i:v) std::cout << i << ' ';
std::cout << '\n';

Godbolt Listing lst-0817-godb.cpp, https://godbolt.org/z/EjT7nPPv7:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EjT7nPPv7 
std::vector v{0,1,3,5,7,9,2,4,6,8};
std::sort(v.begin(), v.end());
for(int i:v) std::cout << i << ' ';
std::cout << '\n';
// oder mit einer Range:
std::ranges::sort(v);
for(int i:v) std::cout << i << ' ';
std::cout << '\n';

Listing 25.3: Zusammenstecken von Funktionen

Book listing lst-0818-book.cpp:

// https://godbolt.org/z/9xrP8Ehvd 
#include <algorithm>
#include <vector>
#include <iostream>
void sort_uniq(std::vector<int> &data) {
    std::ranges::sort(data);                        // sortieren
    auto to_delete = std::ranges::unique(data);     // nach hinten verschieben
    data.erase(to_delete.begin(), to_delete.end()); // tatsächlich löschen
}
int main() {
    std::vector ns{1,5,2,3,9,2,2,2,2,1,5,2,2,3,1,1,2,2,1};
    sort_uniq(ns);
    std::ranges::for_each(ns, [](auto x) {
        std::cout << x << ' '; });
    std::cout << '\n'; // Ausgabe: 1 2 3 5 9
}

Godbolt Listing lst-0818-godb.cpp, https://godbolt.org/z/9xrP8Ehvd:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9xrP8Ehvd 
#include <algorithm>
#include <vector>
#include <iostream>
void sort_uniq(std::vector<int> &data) {
    std::ranges::sort(data);                        // sortieren
    auto to_delete = std::ranges::unique(data);     // nach hinten verschieben
    data.erase(to_delete.begin(), to_delete.end()); // tatsächlich löschen
}
int main() {
    std::vector ns{1,5,2,3,9,2,2,2,2,1,5,2,2,3,1,1,2,2,1};
    sort_uniq(ns);
    std::ranges::for_each(ns, [](auto x) {
        std::cout << x << ' '; });
    std::cout << '\n'; // Ausgabe: 1 2 3 5 9
}

Listing 25.4: Algorithmen laufen parallel

Book listing lst-0819-book.cpp:

// https://godbolt.org/z/qcT9o7YfG 
#include <algorithm>  // find
#include <numeric>    // reduce, accumulate
#include <execution>  // std::execution
#include <iostream>
#include <chrono>     // Zeitmessung
using namespace std::chrono;
long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start).count();
}
template <typename FUNC> void timeit(const char* title, FUNC func) {
    auto start = steady_clock::now();
    auto ret = func(); // ausführen
    std::cout << title << ": " << millisSeit(start) << " ms" << std::endl;
}
int main() {
    using namespace std::execution;          // seq, par, par_unseq
    using std::reduce; using std::accumulate; using std::find;
    std::vector<double> v(600'000'000, 0.0); // 600 Millionen Elemente
    for(auto&x:v) x = ::rand();              // mit Zufallswerten füllen
    timeit("warmlaufen       ", [&v] {
        return reduce(seq, v.begin(), v.end(), 0.0);
    });
    timeit("accumulate       ", [&v] {
        return accumulate(v.begin(), v.end(), 0.0);
    });
    timeit("reduce, seq      ", [&v] {
        return reduce(seq, v.begin(), v.end(), 0.0);
    });
    timeit("reduce, par      ", [&v] {
        return reduce(par, v.begin(), v.end(), 0.0);
    });

    timeit("reduce, par_unseq", [&v] {
        return reduce(par_unseq, v.begin(), v.end(), 0.0);
    });
    timeit("find, seq        ", [&v] {
        return find(seq, v.begin(), v.end(), 1.1) == v.end() ? 0.0 : 1.0;
    });
    timeit("find, par        ", [&v] {
        return find(par, v.begin(), v.end(), 1.1) == v.end() ? 0.0 : 1.0;
    });
    return 0;
}

Godbolt Listing lst-0819-godb.cpp, https://godbolt.org/z/qcT9o7YfG:

//#(compile) c++; compiler:g112; options:-O3 -std=c++23 -ltbb; libs:tbb@trunk
// https://godbolt.org/z/qcT9o7YfG 
#include <algorithm>  // find
#include <numeric>    // reduce, accumulate
#include <execution>  // std::execution
#include <iostream>
#include <chrono>     // Zeitmessung
using namespace std::chrono;
long long millisSeit(steady_clock::time_point start) {
    return duration_cast<milliseconds>(steady_clock::now()-start).count();
}
template <typename FUNC> void timeit(const char* title, FUNC func) {
    auto start = steady_clock::now();
    auto ret = func(); // ausführen
    std::cout << title << ": " << millisSeit(start) << " ms" << std::endl;
}
int main() {
    using namespace std::execution;          // seq, par, par_unseq
    using std::reduce; using std::accumulate; using std::find;
    std::vector<double> v(600'000'000, 0.0); // 600 Millionen Elemente
    for(auto&x:v) x = ::rand();              // mit Zufallswerten füllen
    timeit("warmlaufen       ", [&v] {
        return reduce(seq, v.begin(), v.end(), 0.0);
    });
    timeit("accumulate       ", [&v] {
        return accumulate(v.begin(), v.end(), 0.0);
    });
    timeit("reduce, seq      ", [&v] {
        return reduce(seq, v.begin(), v.end(), 0.0);
    });
    timeit("reduce, par      ", [&v] {
        return reduce(par, v.begin(), v.end(), 0.0);
    });

    timeit("reduce, par_unseq", [&v] {
        return reduce(par_unseq, v.begin(), v.end(), 0.0);
    });
    timeit("find, seq        ", [&v] {
        return find(seq, v.begin(), v.end(), 1.1) == v.end() ? 0.0 : 1.0;
    });
    timeit("find, par        ", [&v] {
        return find(par, v.begin(), v.end(), 1.1) == v.end() ? 0.0 : 1.0;
    });
    return 0;
}

Listing 25.5: View-Typen und ihre Adapter

Book listing lst-0820-book.cpp:

// https://godbolt.org/z/rrq1v5qPs 
std::list lst{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto take5 = rs::take_view{lst, 5};     // View via Typ
auto take6 = lst | vs::take(6);         // View via Adapter

Godbolt Listing lst-0820-godb.cpp, https://godbolt.org/z/rrq1v5qPs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rrq1v5qPs 
std::list lst{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto take5 = rs::take_view{lst, 5};     // View via Typ
auto take6 = lst | vs::take(6);         // View via Adapter

Listing 25.6: Besonders die C++23-Views lassen sich gut kombinieren.

Book listing lst-0821-book.cpp:

// https://godbolt.org/z/hYTv6f9eo 
#include <ranges>
#include <array>
#include <string>
#include <iostream>
#include <string_view>
using namespace std::literals; using namespace std;

// Funktion für die Ausgabe von allem Möglichen
template <typename OBJ>
void print(OBJ&& obj, int level = 0) {
  if constexpr(std::ranges::input_range<OBJ>) {                 // range
    cout << '[';
    for (const auto& elem : obj) print(elem, level+1);
    cout << ']';
  } else if constexpr(requires (OBJ tpl){ std::get<0>(tpl);}) { // tuple/pair
    cout << "(";
    print(get<0>(obj), level+1); print(get<1>(obj), level+1);
    cout << ")";
  } else cout << obj;                                           // element
  if (level == 0) cout << '\n';
}
int main() {
  using namespace std::views; // ausnahmsweise für die Kürze
  auto const nums = array{0, 0, 1, 1, 2, 2};
  auto const animals = array{"cat"s, "dog"s};
  print(iota(0, 5) | chunk(2));                      // Ausgabe: [[01][23][4]]
  print(nums | chunk_by(equal_to{}));                // Ausgabe: [[00][11][22]]
  print(iota(0, 5) | slide(3));                      // Ausgabe: [[012][123][234]]
  print(iota(0, 10) | stride(3));                    // Ausgabe: [0369]
  print(repeat(8) |take(5));                         // Ausgabe: [88888]
  print(zip_transform(plus{}, nums, nums));          // Ausgabe: [002244]
  print(zip(iota(0, 3), iota(1, 4)));                // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | adjacent<2>);                   // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | pairwise);                      // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | adjacent_transform<2>(plus{})); // Ausgabe: [135]
  print(iota(0, 4) | pairwise_transform(plus{}));    // Ausgabe: [135]
  print(animals | join_with( '+' ));                 // Ausgabe: [cat+dog]
  print(cartesian_product(iota(0, 2), "AZ"s));       // Ausgabe: [(0A)(0Z)(1A)(1Z)]
  print(enumerate("APL"s));                          // Ausgabe: [(0A)(1P)(2L)]
  return 0;
}

Godbolt Listing lst-0821-godb.cpp, https://godbolt.org/z/hYTv6f9eo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hYTv6f9eo 
#include <ranges>
#include <array>
#include <string>
#include <iostream>
#include <string_view>
using namespace std::literals; using namespace std;

// Funktion für die Ausgabe von allem Möglichen
template <typename OBJ>
void print(OBJ&& obj, int level = 0) {
  if constexpr(std::ranges::input_range<OBJ>) {                 // range
    cout << '[';
    for (const auto& elem : obj) print(elem, level+1);
    cout << ']';
  } else if constexpr(requires (OBJ tpl){ std::get<0>(tpl);}) { // tuple/pair
    cout << "(";
    print(get<0>(obj), level+1); print(get<1>(obj), level+1);
    cout << ")";
  } else cout << obj;                                           // element
  if (level == 0) cout << '\n';
}
int main() {
  using namespace std::views; // ausnahmsweise für die Kürze
  auto const nums = array{0, 0, 1, 1, 2, 2};
  auto const animals = array{"cat"s, "dog"s};
  print(iota(0, 5) | chunk(2));                      // Ausgabe: [[01][23][4]]
  print(nums | chunk_by(equal_to{}));                // Ausgabe: [[00][11][22]]
  print(iota(0, 5) | slide(3));                      // Ausgabe: [[012][123][234]]
  print(iota(0, 10) | stride(3));                    // Ausgabe: [0369]
  print(repeat(8) |take(5));                         // Ausgabe: [88888]
  print(zip_transform(plus{}, nums, nums));          // Ausgabe: [002244]
  print(zip(iota(0, 3), iota(1, 4)));                // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | adjacent<2>);                   // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | pairwise);                      // Ausgabe: [(01)(12)(23)]
  print(iota(0, 4) | adjacent_transform<2>(plus{})); // Ausgabe: [135]
  print(iota(0, 4) | pairwise_transform(plus{}));    // Ausgabe: [135]
  print(animals | join_with( '+' ));                 // Ausgabe: [cat+dog]
  print(cartesian_product(iota(0, 2), "AZ"s));       // Ausgabe: [(0A)(0Z)(1A)(1Z)]
  print(enumerate("APL"s));                          // Ausgabe: [(0A)(1P)(2L)]
  return 0;
}

Listing 25.7: Funktionen müssen einen Range-Parameter als universelle Referenz bekommen.

Book listing lst-0824-book.cpp:

// https://godbolt.org/z/64zdMEe4r 
void print(const auto& range) { //             (ERR)  kritisch: konstante Referenz
  for (auto const& e : range) { cout << e; } cout << '\n';
}
vector vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
list   lst{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(vec);                  // funktioniert auf direkten Containern
print(lst);                  // funktioniert auf direkten Containern
print(vec | vs::take(3));    // take mit vector klappt
print(lst | vs::take(3));    // take mit list klappt
print(vec | vs::drop(5));    // drop mit vector klappt
print(lst | vs::drop(5));    //             (ERR)  drop mit list klappt nicht!

Godbolt Listing lst-0824-godb.cpp, https://godbolt.org/z/64zdMEe4r:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/64zdMEe4r 
void print(const auto& range) { //             (ERR)  kritisch: konstante Referenz
  for (auto const& e : range) { cout << e; } cout << '\n';
}
vector vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
list   lst{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(vec);                  // funktioniert auf direkten Containern
print(lst);                  // funktioniert auf direkten Containern
print(vec | vs::take(3));    // take mit vector klappt
print(lst | vs::take(3));    // take mit list klappt
print(vec | vs::drop(5));    // drop mit vector klappt
print(lst | vs::drop(5));    //             (ERR)  drop mit list klappt nicht!

Listing 25.8: Eine Funktion nur für Views und nicht für Container

Book listing lst-0825-book.cpp:

// https://godbolt.org/z/s1GjfWxv6 
void print(ranges::view auto range) { // Wertparameter, eingeschränkt auf Views
  for (auto const& e : range) { cout << e; } cout << '\n';
}
vector vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
list   lst{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(vec);                      //             (ERR)  Verboten für Container, sehr gut!
print(vs::all(vec));             // Container in View umwandeln
print(vs::all(lst));             // Container in View umwandeln
print(vec | vs::take(3));        // take mit vector klappt
print(lst | vs::take(3));        // take mit list klappt
print(vec | vs::drop(5));        // drop mit vector klappt
print(lst | vs::drop(5));        // als Wertparameter klappt drop mit list

Godbolt Listing lst-0825-godb.cpp, https://godbolt.org/z/s1GjfWxv6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s1GjfWxv6 
void print(ranges::view auto range) { // Wertparameter, eingeschränkt auf Views
  for (auto const& e : range) { cout << e; } cout << '\n';
}
vector vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
list   lst{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(vec);                      //             (ERR)  Verboten für Container, sehr gut!
print(vs::all(vec));             // Container in View umwandeln
print(vs::all(lst));             // Container in View umwandeln
print(vec | vs::take(3));        // take mit vector klappt
print(lst | vs::take(3));        // take mit list klappt
print(vec | vs::drop(5));        // drop mit vector klappt
print(lst | vs::drop(5));        // als Wertparameter klappt drop mit list

Listing 25.9: Suchen mit Prädikat

Book listing lst-0826-book.cpp:

// https://godbolt.org/z/3r5E1f9YP 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
#include <ranges>
using std::vector; using std::string; using std::string_view;
using namespace std::literals; using std::find_if;
vector<string> demo_split(string_view s) {
  vector<string> result{};
  auto it = s.begin();
  while(it != s.end()) {
    // bis normales Zeichen:
    it = find_if(it, s.end(), [](char c) { return c!=' '; });
     // bis Leerzeichen:
     auto jt = find_if(it, s.end(), [](char c) { return c==' '; });
    if(it!=s.end())
      result.push_back(string(it, jt)); // Kopie ins Ergebnis
    it = jt;
  }
  return result;
}
int main() {
  auto text = "Der Text ist kurz"sv;
  auto res = demo_split(text);
  std::ranges::for_each(res, [](const string &e) {
      std::cout << "[" << e << "] "; });
  std::cout << '\n'; // Ausgabe: [Der] [Text] [ist] [kurz]
  // oder gleich mit views::split:
  for(auto word : text | std::views::split(" "sv)) {
    std::cout << "[";
    for(auto c : word) std::cout << c;
    std::cout << "] ";
  } // Ausgabe: [Der] [Text] [ist] [kurz]
}

Godbolt Listing lst-0826-godb.cpp, https://godbolt.org/z/3r5E1f9YP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3r5E1f9YP 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
#include <ranges>
using std::vector; using std::string; using std::string_view;
using namespace std::literals; using std::find_if;
vector<string> demo_split(string_view s) {
  vector<string> result{};
  auto it = s.begin();
  while(it != s.end()) {
    // bis normales Zeichen:
    it = find_if(it, s.end(), [](char c) { return c!=' '; });
     // bis Leerzeichen:
     auto jt = find_if(it, s.end(), [](char c) { return c==' '; });
    if(it!=s.end())
      result.push_back(string(it, jt)); // Kopie ins Ergebnis
    it = jt;
  }
  return result;
}
int main() {
  auto text = "Der Text ist kurz"sv;
  auto res = demo_split(text);
  std::ranges::for_each(res, [](const string &e) {
      std::cout << "[" << e << "] "; });
  std::cout << '\n'; // Ausgabe: [Der] [Text] [ist] [kurz]
  // oder gleich mit views::split:
  for(auto word : text | std::views::split(" "sv)) {
    std::cout << "[";
    for(auto c : word) std::cout << c;
    std::cout << "] ";
  } // Ausgabe: [Der] [Text] [ist] [kurz]
}

Listing 25.10: Ein Palindrom mit einer Codezeile erkennen

Book listing lst-0827-book.cpp:

// https://godbolt.org/z/WqvM6KEEM 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
using std::string_view; using namespace std::literals; using std::cout;
auto istPalindrom(string_view sv) {
  return std::ranges::equal(sv.begin(), sv.end(), sv.rbegin(), sv.rend()); };
int main() {
  for(auto s : {"regallager"sv, "rentner"sv, "blutwurst"sv }) {
    cout << s << " ist " << (istPalindrom(s)?"ein":"kein") << " Palindrom\n";
  }
}

Godbolt Listing lst-0827-godb.cpp, https://godbolt.org/z/WqvM6KEEM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WqvM6KEEM 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
using std::string_view; using namespace std::literals; using std::cout;
auto istPalindrom(string_view sv) {
  return std::ranges::equal(sv.begin(), sv.end(), sv.rbegin(), sv.rend()); };
int main() {
  for(auto s : {"regallager"sv, "rentner"sv, "blutwurst"sv }) {
    cout << s << " ist " << (istPalindrom(s)?"ein":"kein") << " Palindrom\n";
  }
}

Listing 25.11: Auch »nur lesende« Algorithmen wie »for_each« können die Elemente verändern.

Book listing lst-0828-book.cpp:

// https://godbolt.org/z/jz1Gqo7d9 
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
    std::vector<int> c{ 1,2,3,4 };
    std::ranges::for_each(c, [](auto &n) { n*=n; }); //             (ERR)  modifizierend
    std::cout << c[3] << '\n'; // Ausgabe: 16
}

Godbolt Listing lst-0828-godb.cpp, https://godbolt.org/z/jz1Gqo7d9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jz1Gqo7d9 
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
    std::vector<int> c{ 1,2,3,4 };
    std::ranges::for_each(c, [](auto &n) { n*=n; }); //             (ERR)  modifizierend
    std::cout << c[3] << '\n'; // Ausgabe: 16
}

Listing 25.12: »transform« kann mit unterschiedlichen Typen jonglieren.

Book listing lst-0830-book.cpp:

// https://godbolt.org/z/7r4b8jdGr 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using std::to_string; using std::string; using std::vector;
struct Squares {
    mutable int n = 1;
    int operator()() const { return n*n++; }
};
int main() {
    vector<int> sq(10);
    std::ranges::generate(sq, Squares{});
    std::ranges::for_each(sq, [](auto n) {
        std::cout << n << " "; });
    std::cout << '\n';        // Ausgabe: 1 4 9 16 25 36 49 64 81 100
    string a = "NCC-";
    vector<int> b {1,7,0,1};
    vector<string> c(4);
    auto f = [](char c, int i) -> string { return c+to_string(i); };
    std::ranges::transform(
        a,           // Eingabe 1
        b,           // Eingabe 2
        c.begin(),   // Ausgabe
        f);          // string f(char,int)
    std::ranges::for_each(c, [](auto s) {
        std::cout << s << " "; });
    std::cout << '\n';        // Ausgabe: N1 C7 C0 -1
}

Godbolt Listing lst-0830-godb.cpp, https://godbolt.org/z/7r4b8jdGr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7r4b8jdGr 
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using std::to_string; using std::string; using std::vector;
struct Squares {
    mutable int n = 1;
    int operator()() const { return n*n++; }
};
int main() {
    vector<int> sq(10);
    std::ranges::generate(sq, Squares{});
    std::ranges::for_each(sq, [](auto n) {
        std::cout << n << " "; });
    std::cout << '\n';        // Ausgabe: 1 4 9 16 25 36 49 64 81 100
    string a = "NCC-";
    vector<int> b {1,7,0,1};
    vector<string> c(4);
    auto f = [](char c, int i) -> string { return c+to_string(i); };
    std::ranges::transform(
        a,           // Eingabe 1
        b,           // Eingabe 2
        c.begin(),   // Ausgabe
        f);          // string f(char,int)
    std::ranges::for_each(c, [](auto s) {
        std::cout << s << " "; });
    std::cout << '\n';        // Ausgabe: N1 C7 C0 -1
}

Listing 25.13: Mit Range-Adaptern transformieren

Book listing lst-0831-book.cpp:

// https://godbolt.org/z/j9ozax8qE 
#include <ranges> // zip_transform
// …
auto res = std::views::zip_transform(f, a, b);  // Range-Adapter
for(auto s: res) { std::cout << s << " "; };
std::cout << '\n';        // Ausgabe: N1 C7 C0 -1

Godbolt Listing lst-0831-godb.cpp, https://godbolt.org/z/j9ozax8qE:

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/j9ozax8qE 
#include <ranges> // zip_transform
// …
auto res = std::views::zip_transform(f, a, b);  // Range-Adapter
for(auto s: res) { std::cout << s << " "; };
std::cout << '\n';        // Ausgabe: N1 C7 C0 -1

GodboltId:s53qx664K

Book listing lst-0832-book.cpp:

// https://godbolt.org/z/s53qx664K 
#include <iostream>
#include <random>       // default_random_engine
#include <string>
#include <iterator>     // back_inserter
#include <algorithm>    // sample

int main() {
   std::default_random_engine zufall{};
   const std::string in = "abcdefgh";
   for(auto idx : {0,1,2,3}) {
     std::string out;
     std::ranges::sample(in, std::back_inserter(out), 5, zufall);
     std::cout << out << '\n';
   }
}

Godbolt Listing lst-0832-godb.cpp, https://godbolt.org/z/s53qx664K:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s53qx664K 
#include <iostream>
#include <random>       // default_random_engine
#include <string>
#include <iterator>     // back_inserter
#include <algorithm>    // sample

int main() {
   std::default_random_engine zufall{};
   const std::string in = "abcdefgh";
   for(auto idx : {0,1,2,3}) {
     std::string out;
     std::ranges::sample(in, std::back_inserter(out), 5, zufall);
     std::cout << out << '\n';
   }
}

Listing 25.14: Wirkungsweise der Mischmengenalgorithmen

Book listing lst-0833-book.cpp:

// https://godbolt.org/z/qW4hvE9s3 
#include <algorithm>
#include <iostream>
#include <list>
#include <string>
#include <iterator> // ostream_iterator
#include <cctype>   // toupper
using std::toupper;
int main() {
    std::list a{ 1,2,4,4,4,7,7,9 };
    std::list b{ 2,2,3,4,4,8 };
    using Os = std::ostream_iterator<int>; // Typ des Ausgabeiterators
    Os os{std::cout, " "};                 // Streamausgabeiterator für int
    auto run = [&a,&b,&os](auto algo) {    // nutze a, b und os
        algo(a.begin(), a.end(), b.begin(), b.end(), os); // Algorithmus aufrufen
        std::cout << '\n';
    };

    // Ergebnisse der Algorithmen
    using It = decltype(a.begin());       // Typ der Eingabeiteratoren

    run(std::merge<It,It,Os>);            // Ausgabe: 1 2 2 2 3 4 4 4 4 4 7 7 8 9
    run(std::set_union<It,It,Os>);        // Ausgabe: 1 2 2 3 4 4 4 7 7 8 9
    run(std::set_intersection<It,It,Os>); // Ausgabe: 2 4 4
    run(std::set_difference<It,It,Os>);   // Ausgabe: 1 4 7 7 9
    run(std::set_symmetric_difference<It,It,Os>); // Ausgabe: 1 2 3 4 7 7 8 9

    // Mit Buchstaben wird es noch klarer
    std::string x = "abdddggi";
    std::string y = "BBCDDH";
    using Us = std::ostream_iterator<char>;   // Typ des Ausgabeiterators
    Us us{std::cout, ""};                     // Streamausgabeiterator für char
    auto compare = [](auto c, auto d) { return toupper(c) < toupper(d); };
    auto run2 = [&x,&y,&us,&compare](auto algo) {    // nutze x, y und us
        algo(x.begin(), x.end(), y.begin(), y.end(), us, compare);
        std::cout << '\n';
    };
    // Ergebnisse der Algorithmen
    using Jt = decltype(x.begin());           // Typ der Eingabeiteratoren
    using Cm = decltype(compare);             // Typ der Vergleichsfunktion

    run2(std::merge<Jt,Jt,Us,Cm>);            // Ausgabe: abBBCdddDDggHi
    run2(std::set_union<Jt,Jt,Us,Cm>);        // Ausgabe: abBCdddggHi
    run2(std::set_intersection<Jt,Jt,Us,Cm>); // Ausgabe: bdd
    run2(std::set_difference<Jt,Jt,Us,Cm>);   // Ausgabe: adggi
    run2(std::set_symmetric_difference<Jt,Jt,Us,Cm>); // Ausgabe: aBCdggHi
}

Godbolt Listing lst-0833-godb.cpp, https://godbolt.org/z/qW4hvE9s3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qW4hvE9s3 
#include <algorithm>
#include <iostream>
#include <list>
#include <string>
#include <iterator> // ostream_iterator
#include <cctype>   // toupper
using std::toupper;
int main() {
    std::list a{ 1,2,4,4,4,7,7,9 };
    std::list b{ 2,2,3,4,4,8 };
    using Os = std::ostream_iterator<int>; // Typ des Ausgabeiterators
    Os os{std::cout, " "};                 // Streamausgabeiterator für int
    auto run = [&a,&b,&os](auto algo) {    // nutze a, b und os
        algo(a.begin(), a.end(), b.begin(), b.end(), os); // Algorithmus aufrufen
        std::cout << '\n';
    };

    // Ergebnisse der Algorithmen
    using It = decltype(a.begin());       // Typ der Eingabeiteratoren

    run(std::merge<It,It,Os>);            // Ausgabe: 1 2 2 2 3 4 4 4 4 4 7 7 8 9
    run(std::set_union<It,It,Os>);        // Ausgabe: 1 2 2 3 4 4 4 7 7 8 9
    run(std::set_intersection<It,It,Os>); // Ausgabe: 2 4 4
    run(std::set_difference<It,It,Os>);   // Ausgabe: 1 4 7 7 9
    run(std::set_symmetric_difference<It,It,Os>); // Ausgabe: 1 2 3 4 7 7 8 9

    // Mit Buchstaben wird es noch klarer
    std::string x = "abdddggi";
    std::string y = "BBCDDH";
    using Us = std::ostream_iterator<char>;   // Typ des Ausgabeiterators
    Us us{std::cout, ""};                     // Streamausgabeiterator für char
    auto compare = [](auto c, auto d) { return toupper(c) < toupper(d); };
    auto run2 = [&x,&y,&us,&compare](auto algo) {    // nutze x, y und us
        algo(x.begin(), x.end(), y.begin(), y.end(), us, compare);
        std::cout << '\n';
    };
    // Ergebnisse der Algorithmen
    using Jt = decltype(x.begin());           // Typ der Eingabeiteratoren
    using Cm = decltype(compare);             // Typ der Vergleichsfunktion

    run2(std::merge<Jt,Jt,Us,Cm>);            // Ausgabe: abBBCdddDDggHi
    run2(std::set_union<Jt,Jt,Us,Cm>);        // Ausgabe: abBCdddggHi
    run2(std::set_intersection<Jt,Jt,Us,Cm>); // Ausgabe: bdd
    run2(std::set_difference<Jt,Jt,Us,Cm>);   // Ausgabe: adggi
    run2(std::set_symmetric_difference<Jt,Jt,Us,Cm>); // Ausgabe: aBCdggHi
}

GodboltId:73hTTM7s6

Book listing lst-0834-book.cpp:

// https://godbolt.org/z/73hTTM7s6 
#include <iostream>
#include <algorithm>
#include <string>
void one(std::string &seq) {
    std::ranges::next_permutation(seq);
    std::cout << seq << '\n';
}
int main() {
    std::string seq = "BDK";
    std::cout << seq << '\n'; // Ausgabe: BDK
    auto limit = 3*2*1;       // n!
    for(int i=0; i<limit; ++i)
        one(seq);
    // Hier ist die Sequenz wieder in ihrem Ursprungszustand.
}

Godbolt Listing lst-0834-godb.cpp, https://godbolt.org/z/73hTTM7s6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/73hTTM7s6 
#include <iostream>
#include <algorithm>
#include <string>
void one(std::string &seq) {
    std::ranges::next_permutation(seq);
    std::cout << seq << '\n';
}
int main() {
    std::string seq = "BDK";
    std::cout << seq << '\n'; // Ausgabe: BDK
    auto limit = 3*2*1;       // n!
    for(int i=0; i<limit; ++i)
        one(seq);
    // Hier ist die Sequenz wieder in ihrem Ursprungszustand.
}

Listing 25.15: »accumulate«

Book listing lst-0835-book.cpp:

// https://godbolt.org/z/8sEdxd5jP 
#include <numeric>    // accumulate
#include <functional> // multiplies
#include <algorithm>  // transform, fold_left
#include <iostream>
#include <vector>
using std::accumulate; using std::cout; using std::vector; using std::multiplies;
namespace rs = std::ranges;
int main() {
  vector data{ 2, 3, 5, 10, 20 };
  cout << accumulate(data.begin(),data.end(),0)<<'\n';     // +, Ausgabe: 40
  cout << rs::fold_left(data, 1, multiplies<int>{})<<'\n'; // *, 6000
  vector<bool> gerade( data.size() );
  std::transform( data.begin(), data.end(), gerade.begin(),
      [](auto n) { return n%2==0; });
  for(auto b : gerade) {
      cout << ( b ? "gerade " : "ungerade ");
  }
  cout << "\n";       // Ausgabe: gerade ungerade ungerade gerade gerade
  auto sindAlleGerade = accumulate(gerade.begin(), gerade.end(), true,
          [](auto b, auto c) { return b&&c; });
  if(sindAlleGerade) {
      cout << "alles gerade Zahlen\n";
  } else {
      cout << "ungerade Zahlen dabei\n"; // das ist die Ausgabe
  }
}

Godbolt Listing lst-0835-godb.cpp, https://godbolt.org/z/8sEdxd5jP:

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/8sEdxd5jP 
#include <numeric>    // accumulate
#include <functional> // multiplies
#include <algorithm>  // transform, fold_left
#include <iostream>
#include <vector>
using std::accumulate; using std::cout; using std::vector; using std::multiplies;
namespace rs = std::ranges;
int main() {
  vector data{ 2, 3, 5, 10, 20 };
  cout << accumulate(data.begin(),data.end(),0)<<'\n';     // +, Ausgabe: 40
  cout << rs::fold_left(data, 1, multiplies<int>{})<<'\n'; // *, 6000
  vector<bool> gerade( data.size() );
  std::transform( data.begin(), data.end(), gerade.begin(),
      [](auto n) { return n%2==0; });
  for(auto b : gerade) {
      cout << ( b ? "gerade " : "ungerade ");
  }
  cout << "\n";       // Ausgabe: gerade ungerade ungerade gerade gerade
  auto sindAlleGerade = accumulate(gerade.begin(), gerade.end(), true,
          [](auto b, auto c) { return b&&c; });
  if(sindAlleGerade) {
      cout << "alles gerade Zahlen\n";
  } else {
      cout << "ungerade Zahlen dabei\n"; // das ist die Ausgabe
  }
}

Listing 25.16: »adjacent_difference« und »pairwise_transform«

Book listing lst-0836-book.cpp:

// https://godbolt.org/z/z4ajz5E5P 
#include <numeric>    // adjacent_difference
#include <functional> // plus
#include <algorithm>  // copy
#include <iostream>
#include <iterator>   // ostream_iterator
#include <vector>
#include <ranges>     // pairwise_transform
using std::cout; using std::vector; namespace vs = std::views;
int main() {
    // Streamausgabeiterator für int;
    std::ostream_iterator<int> os{std::cout, " "};
    vector data{ 1, -1, 2, -2, -4, 4, -6, 6 };
    std::copy(data.begin(), data.end (), os);
    cout << '\n'; // Ausgabe: 1 –1 2 –2 –4 4 –6 6
    vector<int> res( data.size()-1 ); // Platz für Ergebnis
    // Ergebnisse nach res schreiben:
    adjacent_difference(data.begin(), data.end(), res.begin());
    std::copy (res.begin(), res.end (), os);
    cout << '\n'; // Ausgabe: 1 –2 3 –4 –2 8 –10
    // gleich nach os schreiben:
    adjacent_difference(data.begin(), data.end(), os, std::plus<int>{});
    cout << '\n'; // Ausgabe: 1 0 1 0 –6 0 –2 0
    // oder via Range-Adapter:
    for(auto e: vs::pairwise_transform(data, std::plus<int>{}))
        cout << e << ' ';
    cout << '\n'; // Ausgabe: 0 1 0 –6 0 –2 0
}

Godbolt Listing lst-0836-godb.cpp, https://godbolt.org/z/z4ajz5E5P:

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/z4ajz5E5P 
#include <numeric>    // adjacent_difference
#include <functional> // plus
#include <algorithm>  // copy
#include <iostream>
#include <iterator>   // ostream_iterator
#include <vector>
#include <ranges>     // pairwise_transform
using std::cout; using std::vector; namespace vs = std::views;
int main() {
    // Streamausgabeiterator für int;
    std::ostream_iterator<int> os{std::cout, " "};
    vector data{ 1, -1, 2, -2, -4, 4, -6, 6 };
    std::copy(data.begin(), data.end (), os);
    cout << '\n'; // Ausgabe: 1 –1 2 –2 –4 4 –6 6
    vector<int> res( data.size()-1 ); // Platz für Ergebnis
    // Ergebnisse nach res schreiben:
    adjacent_difference(data.begin(), data.end(), res.begin());
    std::copy (res.begin(), res.end (), os);
    cout << '\n'; // Ausgabe: 1 –2 3 –4 –2 8 –10
    // gleich nach os schreiben:
    adjacent_difference(data.begin(), data.end(), os, std::plus<int>{});
    cout << '\n'; // Ausgabe: 1 0 1 0 –6 0 –2 0
    // oder via Range-Adapter:
    for(auto e: vs::pairwise_transform(data, std::plus<int>{}))
        cout << e << ' ';
    cout << '\n'; // Ausgabe: 0 1 0 –6 0 –2 0
}

Listing 25.17: »iota«, »stride« und »take«

Book listing lst-0837-book.cpp:

// https://godbolt.org/z/aPoe3d873 
#include <numeric>   // accumulate, iota
#include <algorithm> // copy
#include <iostream>
#include <iterator>  // ostream_iterator
#include <vector>
#include <ranges>    // iota, take, stride
using std::accumulate; using std::cout; using std::vector; 
namespace vs = std::views;
struct Generator {
    int state_;
    void operator++() { state_ += state_; }
    operator int() { return state_; }
};
int main() {
    std::ostream_iterator<int> os{std::cout, " "}; // Streamausgabeiterator für int
    vector<int> data(7);
    std::iota(data.begin(), data.end(), 10);
    std::copy(data.begin(), data.end (), os);
    cout << '\n';          // Ausgabe: 10 11 12 13 14 15 16
    vector<int> seq(7);
    std::iota(seq.begin(), seq.end(), Generator{2});
    std::copy(seq.begin(), seq.end(), os);
    cout << '\n';          // Ausgabe: 2 4 8 16 32 64 128
    for(auto i: vs::iota(0) | vs::stride(3) | vs::take(6))
        cout << i << ' ';
    cout << '\n';          // Ausgabe: 0 3 6 9 12 15
}

Godbolt Listing lst-0837-godb.cpp, https://godbolt.org/z/aPoe3d873:

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/aPoe3d873 
#include <numeric>   // accumulate, iota
#include <algorithm> // copy
#include <iostream>
#include <iterator>  // ostream_iterator
#include <vector>
#include <ranges>    // iota, take, stride
using std::accumulate; using std::cout; using std::vector; 
namespace vs = std::views;
struct Generator {
    int state_;
    void operator++() { state_ += state_; }
    operator int() { return state_; }
};
int main() {
    std::ostream_iterator<int> os{std::cout, " "}; // Streamausgabeiterator für int
    vector<int> data(7);
    std::iota(data.begin(), data.end(), 10);
    std::copy(data.begin(), data.end (), os);
    cout << '\n';          // Ausgabe: 10 11 12 13 14 15 16
    vector<int> seq(7);
    std::iota(seq.begin(), seq.end(), Generator{2});
    std::copy(seq.begin(), seq.end(), os);
    cout << '\n';          // Ausgabe: 2 4 8 16 32 64 128
    for(auto i: vs::iota(0) | vs::stride(3) | vs::take(6))
        cout << i << ' ';
    cout << '\n';          // Ausgabe: 0 3 6 9 12 15
}

Listing 25.18: »inclusive_scan« und »exclusive_scan«

Book listing lst-0838-book.cpp:

// https://godbolt.org/z/qcWsdedMz 
#include <numeric> // *_scan
#include <iostream>
#include <vector>
using std::inclusive_scan; using std::exclusive_scan;
std::ostream& operator<<=(std::ostream&os, const std::vector<int>&data) {
    for(auto &e : data) os << e << ' '; return os << '\n';
}
int main() {
  std::vector data{ 1, 3, 10, 18, 30, 50 };
  std::vector<int> result(6);    // 6 Elemente
  auto plus = [](auto a, auto b) { return a+b; };
  inclusive_scan(data.begin(),data.end(), result.begin(), plus, 100);
  std::cout <<= result;
  // Ausgabe: 101 104 114 132 162 212
  exclusive_scan(data.begin(),data.end(), result.begin(), 100);
  std::cout <<= result;
  // Ausgabe: 100 101 104 114 132 162
}

Godbolt Listing lst-0838-godb.cpp, https://godbolt.org/z/qcWsdedMz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qcWsdedMz 
#include <numeric> // *_scan
#include <iostream>
#include <vector>
using std::inclusive_scan; using std::exclusive_scan;
std::ostream& operator<<=(std::ostream&os, const std::vector<int>&data) {
    for(auto &e : data) os << e << ' '; return os << '\n';
}
int main() {
  std::vector data{ 1, 3, 10, 18, 30, 50 };
  std::vector<int> result(6);    // 6 Elemente
  auto plus = [](auto a, auto b) { return a+b; };
  inclusive_scan(data.begin(),data.end(), result.begin(), plus, 100);
  std::cout <<= result;
  // Ausgabe: 101 104 114 132 162 212
  exclusive_scan(data.begin(),data.end(), result.begin(), 100);
  std::cout <<= result;
  // Ausgabe: 100 101 104 114 132 162
}

GodboltId:dKPbjj1f8

Book listing lst-0839-book.cpp:

// https://godbolt.org/z/dKPbjj1f8 
#include <iostream>
#include <memory>    // uninitialized_copy
#include <alloca.h>  // alloca (Linux)
#include <list>
int main () {
  const std::list input{1,9,2,6,6,6,8};
  const auto SZ = input.size();
  // uninitialisierter Speicherbereich:
  int* ziel = (int*)alloca(sizeof(int) * SZ); // Platz für 7 ints
  std::uninitialized_copy(input.begin(), input.end(), ziel);
  // Testausgabe
  for(int idx=0; idx<SZ; ++idx) {
    std::cout << ziel[idx] << ' ';
  }
  std::cout << '\n'; // Ausgabe: 1 9 2 6 6 6 8
}

Godbolt Listing lst-0839-godb.cpp, https://godbolt.org/z/dKPbjj1f8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dKPbjj1f8 
#include <iostream>
#include <memory>    // uninitialized_copy
#include <alloca.h>  // alloca (Linux)
#include <list>
int main () {
  const std::list input{1,9,2,6,6,6,8};
  const auto SZ = input.size();
  // uninitialisierter Speicherbereich:
  int* ziel = (int*)alloca(sizeof(int) * SZ); // Platz für 7 ints
  std::uninitialized_copy(input.begin(), input.end(), ziel);
  // Testausgabe
  for(int idx=0; idx<SZ; ++idx) {
    std::cout << ziel[idx] << ' ';
  }
  std::cout << '\n'; // Ausgabe: 1 9 2 6 6 6 8
}

Listing 25.19: Ein eigener Algorithmus

Book listing lst-0841-book.cpp:

// https://godbolt.org/z/n8ErWj7j6 
template<typename It, typename Func>
void adjacent_pair(It begin, It end, Func func) {
    if(begin != end) {
        It prev = begin;    // erstes Argument
        ++begin;            // zweites Argument
        for(; begin != end; ++begin, ++prev) {
            func(*prev, *begin);
        }
    }
}

Godbolt Listing lst-0841-godb.cpp, https://godbolt.org/z/n8ErWj7j6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n8ErWj7j6 
template<typename It, typename Func>
void adjacent_pair(It begin, It end, Func func) {
    if(begin != end) {
        It prev = begin;    // erstes Argument
        ++begin;            // zweites Argument
        for(; begin != end; ++begin, ++prev) {
            func(*prev, *begin);
        }
    }
}

Listing 25.20: Der Einsatz von adjacent_pair

Book listing lst-0842-book.cpp:

// https://godbolt.org/z/91jj8Toqs 
#include <vector>
#include <iostream>
// … adjacent_pair von oben hier …
int main() {
    std::vector v{1,2,3,4};
    auto f = [](auto a, auto b) { std::cout << (a+b) << ' '; };
    adjacent_pair(v.begin(), v.end(), f); // 3 5 7
    std::cout << '\n';

    std::vector x{4,8};
    adjacent_pair(x.begin(), x.end(), f); // 12
    std::cout << '\n';

    std::vector w{4};
    adjacent_pair(w.begin(), w.end(), f); // nichts
    std::cout << '\n';

    std::vector<int> y{};
    adjacent_pair(y.begin(), y.end(), f); // nichts
    std::cout << '\n';
}

Godbolt Listing lst-0842-godb.cpp, https://godbolt.org/z/91jj8Toqs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/91jj8Toqs 
#include <vector>
#include <iostream>
// … adjacent_pair von oben hier …
int main() {
    std::vector v{1,2,3,4};
    auto f = [](auto a, auto b) { std::cout << (a+b) << ' '; };
    adjacent_pair(v.begin(), v.end(), f); // 3 5 7
    std::cout << '\n';

    std::vector x{4,8};
    adjacent_pair(x.begin(), x.end(), f); // 12
    std::cout << '\n';

    std::vector w{4};
    adjacent_pair(w.begin(), w.end(), f); // nichts
    std::cout << '\n';

    std::vector<int> y{};
    adjacent_pair(y.begin(), y.end(), f); // nichts
    std::cout << '\n';
}

Listing 25.21: Eigene Range-Adapter für Views

Book listing lst-0843-book.cpp:

// https://godbolt.org/z/dfoorEdYT 
#include <ranges>
#include <iostream>
#include <string_view>
#include <vector>
using namespace std::literals;
using namespace std; namespace vs = std::views; namespace rs = std::ranges;

// Beispiel 1
class Add_1: public rs::range_adaptor_closure<Add_1> { 
  // von Hilfsklasse ableiten
public:
  template<rs::input_range R>
  constexpr auto operator()(R&& r) const {         // universelle Referenz
    return forward<R>(r)                           // universelle Referenz erhalten
      | vs::transform([](auto i) {return i+1;});   // Ihre Implementierung
  }
};
Add_1 add_1{};                                     // Range-Adapter erzeugen

// Beispiel 2
class Dna_to_rna: public rs::range_adaptor_closure<Dna_to_rna> { // ableiten
public:
  template<rs::input_range R>
  constexpr auto operator()(R&& r) const {         // universelle Referenz
    return forward<R>(r)                           // universelle Referenz erhalten
      | vs::transform([](char c)                   // Ihre Implementierung
      {
        switch(c) {
          case 'T': return 'U';
          case 't': return 'u';
          default: return c;
        }
    });
  }
};
Dna_to_rna dna_to_rna{};                           // Range-Adapter erzeugen
// Beispiele benutzen
int main() {
  vector vec{1, 2, 3, 4, 5};
  for(auto i: vec | add_1)                         // benutzen
    cout << i << ' ';
  cout << '\n';         // Ausgabe: 2 3 4 5 6
  auto telo_rep = "TTAGGGTTAGGGTTAGGGTTAGGGT"sv;
  for(auto c: telo_rep | dna_to_rna)  // benutzen
        cout << c;
  cout << '\n';         // Ausgabe: UUAGGGUUAGGGUUAGGGUUAGGGU
}

Godbolt Listing lst-0843-godb.cpp, https://godbolt.org/z/dfoorEdYT:

//#(compile) c++; compiler:g132; options:"-std=c++23"; libs:-
// https://godbolt.org/z/dfoorEdYT 
#include <ranges>
#include <iostream>
#include <string_view>
#include <vector>
using namespace std::literals;
using namespace std; namespace vs = std::views; namespace rs = std::ranges;

// Beispiel 1
class Add_1: public rs::range_adaptor_closure<Add_1> { 
  // von Hilfsklasse ableiten
public:
  template<rs::input_range R>
  constexpr auto operator()(R&& r) const {         // universelle Referenz
    return forward<R>(r)                           // universelle Referenz erhalten
      | vs::transform([](auto i) {return i+1;});   // Ihre Implementierung
  }
};
Add_1 add_1{};                                     // Range-Adapter erzeugen

// Beispiel 2
class Dna_to_rna: public rs::range_adaptor_closure<Dna_to_rna> { // ableiten
public:
  template<rs::input_range R>
  constexpr auto operator()(R&& r) const {         // universelle Referenz
    return forward<R>(r)                           // universelle Referenz erhalten
      | vs::transform([](char c)                   // Ihre Implementierung
      {
        switch(c) {
          case 'T': return 'U';
          case 't': return 'u';
          default: return c;
        }
    });
  }
};
Dna_to_rna dna_to_rna{};                           // Range-Adapter erzeugen
// Beispiele benutzen
int main() {
  vector vec{1, 2, 3, 4, 5};
  for(auto i: vec | add_1)                         // benutzen
    cout << i << ' ';
  cout << '\n';         // Ausgabe: 2 3 4 5 6
  auto telo_rep = "TTAGGGTTAGGGTTAGGGTTAGGGT"sv;
  for(auto c: telo_rep | dna_to_rna)  // benutzen
        cout << c;
  cout << '\n';         // Ausgabe: UUAGGGUUAGGGUUAGGGUUAGGGU
}

Listing 26.1: Mit einem »vector« können Sie ein »set« simulieren.

Book listing lst-0844-book.cpp:

// https://godbolt.org/z/8d8qPWPcG 
#include <vector>
#include <iostream>
#include <algorithm>
using std::vector; using std::ostream; using std::cout;
int main() {
    vector<int> data{};
    data.reserve(400);                    // Platz für 400 Elemente
    // Phase 1: befüllen
    for(int idx = 1; idx <= 20; ++idx) {
        for(int val = 0; val < 20; ++val) {
            data.push_back(val % idx);    // irgendwas zwischen 0 und 19
        }
    }
    cout << data.size() << '\n';          // 400 Elemente zwischen 0 und 19
    // Nachbereitung Phase 1: set-Äquivalent erstellen
    std::sort(data.begin(), data.end());  // Vorbereitung für unique
    auto wo = std::unique(data.begin(), data.end()); // doppelte ans Ende
    data.erase(wo, data.end());           // doppelte wegräumen
    data.shrink_to_fit();
    cout << data.size() << '\n';          // nur noch 20 Elemente
    // Phase 2: benutzen
    for(auto &e:data)
        cout << e << ' ';                 // Ausgabe: 0 1 2 .. 18 19
    cout << '\n';
    auto it = std::lower_bound(data.begin(), data.end(), 16); // suche Wert
    if(it!=data.end() && *it == 16)
        cout << "gefunden!\n";
    if(std::binary_search(data.begin(), data.end(), 7))       // ja oder nein
        cout << "auch gefunden!\n";
}

Godbolt Listing lst-0844-godb.cpp, https://godbolt.org/z/8d8qPWPcG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8d8qPWPcG 
#include <vector>
#include <iostream>
#include <algorithm>
using std::vector; using std::ostream; using std::cout;
int main() {
    vector<int> data{};
    data.reserve(400);                    // Platz für 400 Elemente
    // Phase 1: befüllen
    for(int idx = 1; idx <= 20; ++idx) {
        for(int val = 0; val < 20; ++val) {
            data.push_back(val % idx);    // irgendwas zwischen 0 und 19
        }
    }
    cout << data.size() << '\n';          // 400 Elemente zwischen 0 und 19
    // Nachbereitung Phase 1: set-Äquivalent erstellen
    std::sort(data.begin(), data.end());  // Vorbereitung für unique
    auto wo = std::unique(data.begin(), data.end()); // doppelte ans Ende
    data.erase(wo, data.end());           // doppelte wegräumen
    data.shrink_to_fit();
    cout << data.size() << '\n';          // nur noch 20 Elemente
    // Phase 2: benutzen
    for(auto &e:data)
        cout << e << ' ';                 // Ausgabe: 0 1 2 .. 18 19
    cout << '\n';
    auto it = std::lower_bound(data.begin(), data.end(), 16); // suche Wert
    if(it!=data.end() && *it == 16)
        cout << "gefunden!\n";
    if(std::binary_search(data.begin(), data.end(), 7))       // ja oder nein
        cout << "auch gefunden!\n";
}

GodboltId:fv3963reh

Book listing lst-0845-book.cpp:

// https://godbolt.org/z/fv3963reh 
#include <iostream>  // cout
#include <algorithm> // copy
#include <iterator>  // ostream_iterator
#include <vector>
int main() {
  std::vector<char> pfad{};
  for (char ch = 'a'; ch <= 'z'; ++ch) {
    pfad.push_back(ch);
  }
  std::ranges::copy(pfad, // hier alles, geht aber auch mit anderen Ranges
    std::ostream_iterator<char>(std::cout, " ") // kopiere nach cout, Separator " "
  );
}

Godbolt Listing lst-0845-godb.cpp, https://godbolt.org/z/fv3963reh:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fv3963reh 
#include <iostream>  // cout
#include <algorithm> // copy
#include <iterator>  // ostream_iterator
#include <vector>
int main() {
  std::vector<char> pfad{};
  for (char ch = 'a'; ch <= 'z'; ++ch) {
    pfad.push_back(ch);
  }
  std::ranges::copy(pfad, // hier alles, geht aber auch mit anderen Ranges
    std::ostream_iterator<char>(std::cout, " ") // kopiere nach cout, Separator " "
  );
}

Listing 26.2: Sie erhalten ein um ein Element vergrößertes Array zurück.

Book listing lst-0846-book.cpp:

// https://godbolt.org/z/jT7raEfKa 
#include <iostream>
#include <array>
#include <vector>
#include <string>
using std::array; using std::move; using std::forward;

// == array vergrößern ==
template<typename T, size_t S, std::size_t... Idx>
constexpr array<T, S+1>
help_append(array<T, S>&& data, T&& elem, std::index_sequence<Idx...>) {
  return { std::get<Idx>(forward<array<T, S>>(data))..., forward<T>(elem) };
}
template<typename T, size_t S>
constexpr auto
append(array<T, S> data, T elem) {
  return help_append(move(data), move(elem),
                  std::make_index_sequence<S>{});
}

// == Beispiel ==
class Picture {            // Nullerregel; verschiebbar
  std::vector<char> data_; // viele Daten
  std::string name_;
public:
  explicit Picture(const std::string& name) : data_(1000,0), name_{name}
    { /* ... hier Bild laden ... */ }
  auto name() const { return name_; }
};
int main() {
  // vorher
  array pics{Picture{"Mona"}, Picture{"Schrei"}, Picture{"Vincent"}};
  std::cout << pics[0].name() << '\n'; // Ausgabe: Mona
  // vergrößern
  Picture neu { "Uhren" };
  auto mehr = append(move(pics), move(neu));
  // nachher
  std::cout << pics[0].name() << '\n'; // Ausgabe:
  std::cout << mehr[0].name() << '\n'; // Ausgabe: Mona
  std::cout << mehr[3].name() << '\n'; // Ausgabe: Uhren
}

Godbolt Listing lst-0846-godb.cpp, https://godbolt.org/z/jT7raEfKa:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jT7raEfKa 
#include <iostream>
#include <array>
#include <vector>
#include <string>
using std::array; using std::move; using std::forward;

// == array vergrößern ==
template<typename T, size_t S, std::size_t... Idx>
constexpr array<T, S+1>
help_append(array<T, S>&& data, T&& elem, std::index_sequence<Idx...>) {
  return { std::get<Idx>(forward<array<T, S>>(data))..., forward<T>(elem) };
}
template<typename T, size_t S>
constexpr auto
append(array<T, S> data, T elem) {
  return help_append(move(data), move(elem),
                  std::make_index_sequence<S>{});
}

// == Beispiel ==
class Picture {            // Nullerregel; verschiebbar
  std::vector<char> data_; // viele Daten
  std::string name_;
public:
  explicit Picture(const std::string& name) : data_(1000,0), name_{name}
    { /* ... hier Bild laden ... */ }
  auto name() const { return name_; }
};
int main() {
  // vorher
  array pics{Picture{"Mona"}, Picture{"Schrei"}, Picture{"Vincent"}};
  std::cout << pics[0].name() << '\n'; // Ausgabe: Mona
  // vergrößern
  Picture neu { "Uhren" };
  auto mehr = append(move(pics), move(neu));
  // nachher
  std::cout << pics[0].name() << '\n'; // Ausgabe:
  std::cout << mehr[0].name() << '\n'; // Ausgabe: Mona
  std::cout << mehr[3].name() << '\n'; // Ausgabe: Uhren
}

Listing 26.3: »append« zur Laufzeit

Book listing lst-0850-book.cpp:

// https://godbolt.org/z/MMP16Mj3W 
#include <iostream>
#include <array>
#include <string>
using std::array;
template<typename T, size_t S>
auto append(const array<T, S>& data, T elem) {
    array<T, S+1> result {};
    for(auto i=0u; i < data.size(); ++i)
        result[i] = data[i];
    result[S] =elem;
    return result;
}
int main() {
    // vorher
    array pics { 3, 4, 5 };
    std::cout << pics[0] << '\n'; // Ausgabe: 3
    // vergrößern
    auto mehr = append(pics, 77);
    // nachher
    std::cout << mehr[3] << '\n'; // Ausgabe: 77
}

Godbolt Listing lst-0850-godb.cpp, https://godbolt.org/z/MMP16Mj3W:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MMP16Mj3W 
#include <iostream>
#include <array>
#include <string>
using std::array;
template<typename T, size_t S>
auto append(const array<T, S>& data, T elem) {
    array<T, S+1> result {};
    for(auto i=0u; i < data.size(); ++i)
        result[i] = data[i];
    result[S] =elem;
    return result;
}
int main() {
    // vorher
    array pics { 3, 4, 5 };
    std::cout << pics[0] << '\n'; // Ausgabe: 3
    // vergrößern
    auto mehr = append(pics, 77);
    // nachher
    std::cout << mehr[3] << '\n'; // Ausgabe: 77
}

Listing 26.4: Verschiedene Implementierungen eines Algorithmus, unterschieden anhand von Concepts

Book listing lst-0851-book.cpp:

// https://godbolt.org/z/scE81KfEa 
#include <iostream>
#include <vector>
#include <list>
#include <ranges>
namespace rs = std::ranges;

template<rs::range R>
void alg(R&& range) {
  if constexpr(rs::random_access_range<R>)
    std::cout << "wahlfrei.\n";
  else if constexpr(rs::bidirectional_range<R>)
    std::cout << "bidirektional, aber nicht wahlfrei\n";
  else static_assert(false, "nicht unterstützter Range-Typ");
}
int main() {
    std::vector<int> vec {};       // vector ist wahlfrei
    alg(vec);
    std::list<int> lst;            // list ist nur bidirektional
    alg(lst);
    std::istreambuf_iterator<char> i1{std::cin}, i2{}; // nicht einmal bidirektional
    auto fwd = rs::subrange{i1, i2};
    alg(fwd); //             (ERR)  Fehler: keine passende Implementierung
}

Godbolt Listing lst-0851-godb.cpp, https://godbolt.org/z/scE81KfEa:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/scE81KfEa 
#include <iostream>
#include <vector>
#include <list>
#include <ranges>
namespace rs = std::ranges;

template<rs::range R>
void alg(R&& range) {
  if constexpr(rs::random_access_range<R>)
    std::cout << "wahlfrei.\n";
  else if constexpr(rs::bidirectional_range<R>)
    std::cout << "bidirektional, aber nicht wahlfrei\n";
  else static_assert(false, "nicht unterstützter Range-Typ");
}
int main() {
    std::vector<int> vec {};       // vector ist wahlfrei
    alg(vec);
    std::list<int> lst;            // list ist nur bidirektional
    alg(lst);
    std::istreambuf_iterator<char> i1{std::cin}, i2{}; // nicht einmal bidirektional
    auto fwd = rs::subrange{i1, i2};
    alg(fwd); //             (ERR)  Fehler: keine passende Implementierung
}

Listing 27.1: Den Stream als Referenz zurückzugeben, ermöglicht das Aneinanderhängen.

Book listing lst-0854-book.cpp:

// https://godbolt.org/z/Th66Y9WvE 
#include <iostream> // cin, cout
int main() {
    int val1, val2;
    std::cout << "Bitte 2 int-Werte: ";
    std::cin >> val1 >> val2;
    std::cout << val1 << " : " << val2 << std::endl;
}

Godbolt Listing lst-0854-godb.cpp, https://godbolt.org/z/Th66Y9WvE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Th66Y9WvE 
#include <iostream> // cin, cout
int main() {
    int val1, val2;
    std::cout << "Bitte 2 int-Werte: ";
    std::cin >> val1 >> val2;
    std::cout << val1 << " : " << val2 << std::endl;
}

Listing 27.2: Unformatierte Eingabe aus Streams

Book listing lst-0856-book.cpp:

// https://godbolt.org/z/rP6vMM1Gr 
#include <iostream>
using std::cout; using std::cin; using std::endl;
int main() {
    const unsigned int MAX = 10;
    char buffer[MAX] = {0};
    cout << "Eingabe getline : ";
    cin.getline(buffer, MAX);
    cout << std::cin.gcount()
        << " Zeichen wurden eingelesen\n";
    for(auto c : buffer) {
        if(c && c!='\0') cout.put(c);
    }
    cin.ignore(MAX, '\n');
    cout << "\nEingabe machen (mit . beenden) : ";
    char ch=0;
    while(cin.get(ch)) {
        if(ch == '.') break;
        cout.put(ch);
    }
    cout << "Eingabe beendet" << endl;
}

Godbolt Listing lst-0856-godb.cpp, https://godbolt.org/z/rP6vMM1Gr:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rP6vMM1Gr 
#include <iostream>
using std::cout; using std::cin; using std::endl;
int main() {
    const unsigned int MAX = 10;
    char buffer[MAX] = {0};
    cout << "Eingabe getline : ";
    cin.getline(buffer, MAX);
    cout << std::cin.gcount()
        << " Zeichen wurden eingelesen\n";
    for(auto c : buffer) {
        if(c && c!='\0') cout.put(c);
    }
    cin.ignore(MAX, '\n');
    cout << "\nEingabe machen (mit . beenden) : ";
    char ch=0;
    while(cin.get(ch)) {
        if(ch == '.') break;
        cout.put(ch);
    }
    cout << "Eingabe beendet" << endl;
}

Listing 27.3: Zustandsprüfungen bei Streams

Book listing lst-0858-book.cpp:

// https://godbolt.org/z/rq3eGP3cv 
#include <fstream>
#include <iostream>
using std::cout; using std::cin; using std::ofstream;
void checkIOstate(std::ios& stream) {
    if( stream.good() ) {
        cout << "Alles in Ordnung\n";
    } else if( stream.bad() ) {
        cout << "Fataler Fehler\n";
    } else if( stream.fail()) {
        cout << "Fehler bei der Ein-/Ausgabe\n";
        if( stream.eof()) {
            cout << "Ende des Datenstroms erreicht\n";
        }
    }
    stream.clear();
}
int main() {
    int val=0;
    cout << "Wert eingeben: ";
    cin >> val;
    checkIOstate( cin );
    std::ifstream file;
    file.open("nichtvorhanden.text");
    checkIOstate(file);
    std::fstream fstr;
    fstr.open("neueDatei.txt",
        ofstream::out | ofstream::in
        | ofstream::binary | ofstream::trunc);
    fstr << "Text in der Datei\n";
    fstr.seekp(std::ios_base::beg);
    char ch;
    while( fstr.good()) {
        fstr.get(ch);
        if(fstr.good()) cout.put(ch);
    }
    checkIOstate(fstr);
}

Godbolt Listing lst-0858-godb.cpp, https://godbolt.org/z/rq3eGP3cv:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rq3eGP3cv 
#include <fstream>
#include <iostream>
using std::cout; using std::cin; using std::ofstream;
void checkIOstate(std::ios& stream) {
    if( stream.good() ) {
        cout << "Alles in Ordnung\n";
    } else if( stream.bad() ) {
        cout << "Fataler Fehler\n";
    } else if( stream.fail()) {
        cout << "Fehler bei der Ein-/Ausgabe\n";
        if( stream.eof()) {
            cout << "Ende des Datenstroms erreicht\n";
        }
    }
    stream.clear();
}
int main() {
    int val=0;
    cout << "Wert eingeben: ";
    cin >> val;
    checkIOstate( cin );
    std::ifstream file;
    file.open("nichtvorhanden.text");
    checkIOstate(file);
    std::fstream fstr;
    fstr.open("neueDatei.txt",
        ofstream::out | ofstream::in
        | ofstream::binary | ofstream::trunc);
    fstr << "Text in der Datei\n";
    fstr.seekp(std::ios_base::beg);
    char ch;
    while( fstr.good()) {
        fstr.get(ch);
        if(fstr.good()) cout.put(ch);
    }
    checkIOstate(fstr);
}

Listing 27.4: Operator »bool« von Streams

Book listing lst-0859-book.cpp:

// https://godbolt.org/z/Mr6E3Ez48 
#include <iostream>
int main() {
    unsigned int val;
    std::cout << "Wert eingeben: ";
    std::cin >> val;
    if( std::cin ) { // operator bool()
        /* ... */                                   // Eingabe korrekt
    } else {
        std::cout << "Fehler bei std::cin\n";   // Fehler bei der Eingabe
    }
}

Godbolt Listing lst-0859-godb.cpp, https://godbolt.org/z/Mr6E3Ez48:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mr6E3Ez48 
#include <iostream>
int main() {
    unsigned int val;
    std::cout << "Wert eingeben: ";
    std::cin >> val;
    if( std::cin ) { // operator bool()
        /* ... */                                   // Eingabe korrekt
    } else {
        std::cout << "Fehler bei std::cin\n";   // Fehler bei der Eingabe
    }
}

Listing 27.5: Einen Boolean als Text oder Zahl ausgeben

Book listing lst-0860-book.cpp:

// https://godbolt.org/z/s1csa51z9 
#include <iostream>
#include <iomanip>
using std::cin; using std::cout; using std::endl;

void f(bool b) {
     cout << b << endl;                    // Ausgabe:  true
}

int main () {
    bool b=true;
    cout << std::boolalpha << b << endl;   // Ausgabe: true
    b=false;
    cout << b << endl;                     // Ausgabe: false
    f(true);
    cout << std::noboolalpha << b << endl; // Ausgabe: 0
    b=true;
    cout << b << endl;                     // Ausgabe: 1
}

Godbolt Listing lst-0860-godb.cpp, https://godbolt.org/z/s1csa51z9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/s1csa51z9 
#include <iostream>
#include <iomanip>
using std::cin; using std::cout; using std::endl;

void f(bool b) {
     cout << b << endl;                    // Ausgabe:  true
}

int main () {
    bool b=true;
    cout << std::boolalpha << b << endl;   // Ausgabe: true
    b=false;
    cout << b << endl;                     // Ausgabe: false
    f(true);
    cout << std::noboolalpha << b << endl; // Ausgabe: 0
    b=true;
    cout << b << endl;                     // Ausgabe: 1
}

Listing 27.6: Zahlenformate bei der Ausgabe

Book listing lst-0862-book.cpp:

// https://godbolt.org/z/bEKaYdssE 
#include <iostream>
#include <ios>
using std::cout; using std::endl;
void f() {
    int val = 100;
    cout << val << endl;               // Ausgabe: 0x64
}
int main() {
    int val = 255;
    cout << std::showbase;
    cout << std::dec << val << endl;   // Ausgabe: 255
    cout << std::hex << val << endl;   // Ausgabe: 0xff
    f();
    cout << std::oct << val << endl;   // Ausgabe: 0377
    cout << val << std::endl;          // Ausgabe: 0377
}

Godbolt Listing lst-0862-godb.cpp, https://godbolt.org/z/bEKaYdssE:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bEKaYdssE 
#include <iostream>
#include <ios>
using std::cout; using std::endl;
void f() {
    int val = 100;
    cout << val << endl;               // Ausgabe: 0x64
}
int main() {
    int val = 255;
    cout << std::showbase;
    cout << std::dec << val << endl;   // Ausgabe: 255
    cout << std::hex << val << endl;   // Ausgabe: 0xff
    f();
    cout << std::oct << val << endl;   // Ausgabe: 0377
    cout << val << std::endl;          // Ausgabe: 0377
}

Listing 27.7: Unterschiedliche Möglichkeiten zum Auffüllen bei der Ausgabe

Book listing lst-0863-book.cpp:

// https://godbolt.org/z/TMdzrjvhd 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw
using std::cout; using std::endl;
int main() {
    int val = -1000;
    cout << std::setw(10) << std::internal
         << val << endl;
    cout << std::setw(10) << std::left << val << endl;
    cout << std::setw(10) << std::right
         << val << endl;
}

Godbolt Listing lst-0863-godb.cpp, https://godbolt.org/z/TMdzrjvhd:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TMdzrjvhd 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw
using std::cout; using std::endl;
int main() {
    int val = -1000;
    cout << std::setw(10) << std::internal
         << val << endl;
    cout << std::setw(10) << std::left << val << endl;
    cout << std::setw(10) << std::right
         << val << endl;
}

Listing 27.8: Zahlenformate bei der Ausgabe

Book listing lst-0864-book.cpp:

// https://godbolt.org/z/sYK8oT33x 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw

using std::cout; using std::endl;
int main() {
    double dval = 3.14159;
    std::ios_base::fmtflags ff(std::ios::scientific|std::ios::uppercase);
    cout << std::setiosflags(ff);
    cout << dval << endl;                           // Ausgabe: 3.141590E+00
    cout << std::resetiosflags(ff) << dval << endl; // Ausgabe: 3.14159
    cout << std::setprecision(3) << dval << endl;   // Ausgabe: 3.14
    cout << std::setw(10);
    cout << std::setfill( '*' ) << 1246 << endl;    // Ausgabe: ******1246
}

Godbolt Listing lst-0864-godb.cpp, https://godbolt.org/z/sYK8oT33x:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/sYK8oT33x 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw

using std::cout; using std::endl;
int main() {
    double dval = 3.14159;
    std::ios_base::fmtflags ff(std::ios::scientific|std::ios::uppercase);
    cout << std::setiosflags(ff);
    cout << dval << endl;                           // Ausgabe: 3.141590E+00
    cout << std::resetiosflags(ff) << dval << endl; // Ausgabe: 3.14159
    cout << std::setprecision(3) << dval << endl;   // Ausgabe: 3.14
    cout << std::setw(10);
    cout << std::setfill( '*' ) << 1246 << endl;    // Ausgabe: ******1246
}

Listing 27.9: Eigene Manipulatoren

Book listing lst-0865-book.cpp:

// https://godbolt.org/z/TY9df9sb6 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw
using std::cout; using std::cin; using std::endl;
std::ostream& tabl(std::ostream& os) {
    os << '\t';
    return os;
}
std::istream& firstNum(std::istream& is) {
    char ch;
    is.get(ch);
    if( (ch >= '0') && (ch <= '9') ) {
        std::cin.putback(ch);
    }
    return is;
}
int main() {
    int val=0;
    cout << "Text1" << tabl << "Text2" << endl; // Ausgabe: Text1 (tab) Text2
    cout << "Eingabe machen: ";
    cin >> firstNum >> val;
    cout << val << std::endl; // Ausgabe: 12345
}

Godbolt Listing lst-0865-godb.cpp, https://godbolt.org/z/TY9df9sb6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TY9df9sb6 
#include <iostream>
#include <ios>        // left, right, internal
#include <iomanip>    // setw
using std::cout; using std::cin; using std::endl;
std::ostream& tabl(std::ostream& os) {
    os << '\t';
    return os;
}
std::istream& firstNum(std::istream& is) {
    char ch;
    is.get(ch);
    if( (ch >= '0') && (ch <= '9') ) {
        std::cin.putback(ch);
    }
    return is;
}
int main() {
    int val=0;
    cout << "Text1" << tabl << "Text2" << endl; // Ausgabe: Text1 (tab) Text2
    cout << "Eingabe machen: ";
    cin >> firstNum >> val;
    cout << val << std::endl; // Ausgabe: 12345
}

Listing 27.10: Manipulator als Lambda

Book listing lst-0867-book.cpp:

#include <iostream>
using std::cout; using std::endl;
int main() {
    auto ddash = [](auto &os) -> std::ostream& { return os << "-"; };
    cout << "Text1" << ddash << "Text2" << endl; // Ausgabe: Text1-Text2
}

Listing 27.11: Manipulator mit Parameter

Book listing lst-0868-book.cpp:

// https://godbolt.org/z/KKE6nWT49 
#include <iostream>
using std::cout; using std::endl;
class dendl { // Punkte gefolgt von Newline
    int dendl_;
public:
    dendl(int n=1)
      : dendl_{n} {}
    std::ostream& operator()(std::ostream& os) const { // Funktor
        for(int i=0; i<dendl_; ++i) os << '.';
        return os << '\n';
    }
};
std::ostream& operator<<( std::ostream& os, const dendl& elem) {
    return elem(os);
}
int main() {
    cout << "Text1" << dendl(4); // Ausgabe: Text1....
    cout << "Text2" << dendl(2); // Ausgabe: Text2..
    cout << "Text3" << dendl();  // Ausgabe: Text3.
}

Godbolt Listing lst-0868-godb.cpp, https://godbolt.org/z/KKE6nWT49:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KKE6nWT49 
#include <iostream>
using std::cout; using std::endl;
class dendl { // Punkte gefolgt von Newline
    int dendl_;
public:
    dendl(int n=1)
      : dendl_{n} {}
    std::ostream& operator()(std::ostream& os) const { // Funktor
        for(int i=0; i<dendl_; ++i) os << '.';
        return os << '\n';
    }
};
std::ostream& operator<<( std::ostream& os, const dendl& elem) {
    return elem(os);
}
int main() {
    cout << "Text1" << dendl(4); // Ausgabe: Text1....
    cout << "Text2" << dendl(2); // Ausgabe: Text2..
    cout << "Text3" << dendl();  // Ausgabe: Text3.
}

Listing 27.12: Format direkt beeinflussen

Book listing lst-0870-book.cpp:

// https://godbolt.org/z/csbPMYM19 
#include <iostream>
#include <ios> // hex, dec
using std::cout; using std::endl;
int main() {
    int val = 255;
    cout << std::showbase << std::hex << val << endl;   // Ausgabe: 0xff
    cout << std::noshowbase << std::dec << val << endl; // Ausgabe: 255
}

Godbolt Listing lst-0870-godb.cpp, https://godbolt.org/z/csbPMYM19:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/csbPMYM19 
#include <iostream>
#include <ios> // hex, dec
using std::cout; using std::endl;
int main() {
    int val = 255;
    cout << std::showbase << std::hex << val << endl;   // Ausgabe: 0xff
    cout << std::noshowbase << std::dec << val << endl; // Ausgabe: 255
}

Listing 27.13: Format mit »setf« und »unsetf« beeinflussen

Book listing lst-0871-book.cpp:

// https://godbolt.org/z/1xzzMdjdM 
#include <iostream>
using std::cout; using std::endl;
int main() {
    int val = 255;
    cout.setf(std::ios_base::hex, std::ios_base::basefield);
    cout.setf(std::ios_base::showbase);
    cout << val << std::endl; // Ausgabe: 0xff
    cout.unsetf(std::ios_base::showbase);
    cout.setf(std::ios_base::dec, std::ios_base::basefield);
    cout << val << std::endl; // Ausgabe: 255
}

Godbolt Listing lst-0871-godb.cpp, https://godbolt.org/z/1xzzMdjdM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xzzMdjdM 
#include <iostream>
using std::cout; using std::endl;
int main() {
    int val = 255;
    cout.setf(std::ios_base::hex, std::ios_base::basefield);
    cout.setf(std::ios_base::showbase);
    cout << val << std::endl; // Ausgabe: 0xff
    cout.unsetf(std::ios_base::showbase);
    cout.setf(std::ios_base::dec, std::ios_base::basefield);
    cout << val << std::endl; // Ausgabe: 255
}

Listing 27.14: Flags sichern und wiederherstellen

Book listing lst-0872-book.cpp:

// https://godbolt.org/z/4MY1Yznv9 
#include <iostream>
using std::cout; using std::endl;
int main() {
    int val = 255;
    std::ios::fmtflags ff = std::cout.flags();
    cout.flags(std::ios::hex | std::ios::showbase);
    cout << val << endl;  // Ausgabe: 0xff
    cout.flags(ff);
    cout << val << endl;  // Ausgabe: 255
}

Godbolt Listing lst-0872-godb.cpp, https://godbolt.org/z/4MY1Yznv9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4MY1Yznv9 
#include <iostream>
using std::cout; using std::endl;
int main() {
    int val = 255;
    std::ios::fmtflags ff = std::cout.flags();
    cout.flags(std::ios::hex | std::ios::showbase);
    cout << val << endl;  // Ausgabe: 0xff
    cout.flags(ff);
    cout << val << endl;  // Ausgabe: 255
}

Listing 27.15: Öffnen und Anlegen von Dateien

Book listing lst-0873-book.cpp:

// https://godbolt.org/z/EfEx8fdGo 
#include <fstream>
#include <iostream>
#include <string>
int main() {
    std::string name = "textfile.txt";
    std::ifstream file01;
    file01.open(name);
    if( file01.fail() ) {
        std::cout << "Konnte " << name << " nicht oeffnen\n";
    }
    std::ofstream file02("data.dat");
    if( file02.good() ) {
        std::cout << "data.dat geoeffnet bzw. erzeugt\n";
    }
    std::fstream file03;
    file03.open("database.db");
    if( !file03 ) {
        std::cout << "Konnte database.db nicht oeffnen\n";
    }
}

Godbolt Listing lst-0873-godb.cpp, https://godbolt.org/z/EfEx8fdGo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/EfEx8fdGo 
#include <fstream>
#include <iostream>
#include <string>
int main() {
    std::string name = "textfile.txt";
    std::ifstream file01;
    file01.open(name);
    if( file01.fail() ) {
        std::cout << "Konnte " << name << " nicht oeffnen\n";
    }
    std::ofstream file02("data.dat");
    if( file02.good() ) {
        std::cout << "data.dat geoeffnet bzw. erzeugt\n";
    }
    std::fstream file03;
    file03.open("database.db");
    if( !file03 ) {
        std::cout << "Konnte database.db nicht oeffnen\n";
    }
}

Listing 27.16: Weitere Flags beim Öffnen von Dateien

Book listing lst-0874-book.cpp:

// https://godbolt.org/z/3ocr4v745 
#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ofstream file01("testfile.txt", std::ios::out|std::ios::app);
    if(file01.fail()) {
        cout << "Konnte testfile.txt nicht öffnen\n";
    } else {
        cout << "ok.\n";
    }
    std::fstream file02;
    file02.open("database.db", std::ios::out|std::ios::trunc);
    if( !file02 ) {
        cout << "Konnte database.db nicht öffnen\n";
    } else {
        cout << "ok.\n";
    }
}

Godbolt Listing lst-0874-godb.cpp, https://godbolt.org/z/3ocr4v745:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3ocr4v745 
#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ofstream file01("testfile.txt", std::ios::out|std::ios::app);
    if(file01.fail()) {
        cout << "Konnte testfile.txt nicht öffnen\n";
    } else {
        cout << "ok.\n";
    }
    std::fstream file02;
    file02.open("database.db", std::ios::out|std::ios::trunc);
    if( !file02 ) {
        cout << "Konnte database.db nicht öffnen\n";
    } else {
        cout << "ok.\n";
    }
}

Listing 27.17: Explizites Schließen eines Dateistreams

Book listing lst-0875-book.cpp:

// https://godbolt.org/z/arKsG6vqc 
#include <fstream>
#include <iostream>
int main() {
    std::ofstream file01("data.db");
    if( file01.fail() ) {
        std::cout << "Konnte data.db nicht öffnen\n";
    } else {
        std::cout << "ok.\n";
    }
    file01 << "Text für die Datei\n";
    if( file01.is_open()) {
        file01.close();
    }
    file01.open("data001.db");
    // Automatisch:
    {
        std::ofstream file02("data002.db");
    } // ab hier wird file02 geschlossen
} // ab hier ist auch file01 geschlossen

Godbolt Listing lst-0875-godb.cpp, https://godbolt.org/z/arKsG6vqc:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/arKsG6vqc 
#include <fstream>
#include <iostream>
int main() {
    std::ofstream file01("data.db");
    if( file01.fail() ) {
        std::cout << "Konnte data.db nicht öffnen\n";
    } else {
        std::cout << "ok.\n";
    }
    file01 << "Text für die Datei\n";
    if( file01.is_open()) {
        file01.close();
    }
    file01.open("data001.db");
    // Automatisch:
    {
        std::ofstream file02("data002.db");
    } // ab hier wird file02 geschlossen
} // ab hier ist auch file01 geschlossen

Listing 27.18: Lesen und Schreiben mit Dateien

Book listing lst-0876-book.cpp:

// https://godbolt.org/z/KzsPfMbnq 
#include <fstream>
#include <iomanip> // setw
#include <iostream>
int main() {
    std::ofstream file("data.dat");
    if( !file ) {
        std::cout << "Konnte data.dat nicht öffnen\n";
        return 1;
    }
    file << std::setw(10) << std::setfill( '*' )
         << 1234 << std::endl;
}

Godbolt Listing lst-0876-godb.cpp, https://godbolt.org/z/KzsPfMbnq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/KzsPfMbnq 
#include <fstream>
#include <iomanip> // setw
#include <iostream>
int main() {
    std::ofstream file("data.dat");
    if( !file ) {
        std::cout << "Konnte data.dat nicht öffnen\n";
        return 1;
    }
    file << std::setw(10) << std::setfill( '*' )
         << 1234 << std::endl;
}

Listing 27.19: Byteweises Lesen und Schreiben

Book listing lst-0877-book.cpp:

// https://godbolt.org/z/43E38b6Eq 
#include <fstream>
#include <iomanip> // setw
#include <iostream>
int main() {
    std::ifstream file("data.dat");
    if( !file ) {
        std::cout << "Fehler beim Öffnen\n";
        return 1;
    }
    char ch;
    while(file.get(ch) ) {
        std::cout.put(ch);
    }
    if( file.eof() ) {
        file.clear();
    }
    file.close();
}

Godbolt Listing lst-0877-godb.cpp, https://godbolt.org/z/43E38b6Eq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/43E38b6Eq 
#include <fstream>
#include <iomanip> // setw
#include <iostream>
int main() {
    std::ifstream file("data.dat");
    if( !file ) {
        std::cout << "Fehler beim Öffnen\n";
        return 1;
    }
    char ch;
    while(file.get(ch) ) {
        std::cout.put(ch);
    }
    if( file.eof() ) {
        file.clear();
    }
    file.close();
}

Listing 27.20: Eine Datei byteweise kopieren

Book listing lst-0878-book.cpp:

#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ifstream file("data.dat");
    if( !file ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::ofstream filecopy("backup.dat");
    if( !filecopy ) { /* Fehler */ cout << "ERR\n"; return 1; }
    char ch;
    while(file.get(ch) ) {
        filecopy.put(ch);
    }
}

Listing 27.21: Zeilenweises Lesen und Schreiben

Book listing lst-0879-book.cpp:

// https://godbolt.org/z/7r8r31K3e 
#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ifstream file("44fstream07.cpp");
    if( !file ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::ofstream filecopy("backup.cpp");
    if( !filecopy ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::string puffer;
    while( getline(file, puffer) ) {
        filecopy << puffer << std::endl;
        cout << puffer << std::endl;
    }
    if( file.eof() ) {
        file.clear();
    }
}

Godbolt Listing lst-0879-godb.cpp, https://godbolt.org/z/7r8r31K3e:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7r8r31K3e 
#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ifstream file("44fstream07.cpp");
    if( !file ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::ofstream filecopy("backup.cpp");
    if( !filecopy ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::string puffer;
    while( getline(file, puffer) ) {
        filecopy << puffer << std::endl;
        cout << puffer << std::endl;
    }
    if( file.eof() ) {
        file.clear();
    }
}

Listing 27.22: Blockweises Lesen und Schreiben mit »read« und »write«

Book listing lst-0880-book.cpp:

// https://godbolt.org/z/qP8cT5n7c 
#include <fstream>
#include <iostream>
#include <vector>
using std::cout;
int main() {
    std::ifstream file("testfile.txt", std::ios::binary);
    if( !file ) { /* Fehler */ cout <<"ERR1\n"; return 1; }
    std::ofstream filecopy("backup.dat", std::ios::binary);
    if( !filecopy ) { /* Fehler */ return 1; }
    file.seekg(0, std::ios::end);
    auto size = file.tellg();
    cout << "Dateigroesse : " << size << " Byte\n";
    file.seekg(0, std::ios::beg); // Wichtig!
    std::vector<char> puffer(size);
    file.read(puffer.data(), size);
    if( !file ) { cout << "Fehler bei read...\n"; return 1;}
    cout << "Gelesen: " << file.gcount() << " Byte\n";
    filecopy.write( puffer.data(), size );
    if( !filecopy ) { cout << "Fehler bei write...\n"; return 1;}
}

Godbolt Listing lst-0880-godb.cpp, https://godbolt.org/z/qP8cT5n7c:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qP8cT5n7c 
#include <fstream>
#include <iostream>
#include <vector>
using std::cout;
int main() {
    std::ifstream file("testfile.txt", std::ios::binary);
    if( !file ) { /* Fehler */ cout <<"ERR1\n"; return 1; }
    std::ofstream filecopy("backup.dat", std::ios::binary);
    if( !filecopy ) { /* Fehler */ return 1; }
    file.seekg(0, std::ios::end);
    auto size = file.tellg();
    cout << "Dateigroesse : " << size << " Byte\n";
    file.seekg(0, std::ios::beg); // Wichtig!
    std::vector<char> puffer(size);
    file.read(puffer.data(), size);
    if( !file ) { cout << "Fehler bei read...\n"; return 1;}
    cout << "Gelesen: " << file.gcount() << " Byte\n";
    filecopy.write( puffer.data(), size );
    if( !filecopy ) { cout << "Fehler bei write...\n"; return 1;}
}

Listing 27.23: Blockweises Lesen und Schreiben mit Hilfsklasse

Book listing lst-0881-book.cpp:

// https://godbolt.org/z/b3W48s86z 
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using std::cout; using std::string;
class DataClass {
    std::string text_;
    int data_;
public:
    DataClass(string t="", int i=0)
      : text_{t}, data_{i} {}
    std::ostream& write(std::ostream& os) const {
        os << text_ << std::ends;
        os.write(reinterpret_cast<const char*>(&data_), sizeof(data_));
        return os;
    }
    std::istream& read(std::istream& is) {
        std::getline(is, text_, '\0');
        is.read(reinterpret_cast<char*>(&data_), sizeof(data_));
        return is;
    }
    std::ostream& print(std::ostream& os) {
        return os << text_ << " : " << data_ << std::endl;
    }
};
int main() {
    std::ofstream file_w("data.dat", std::ios::binary);
    if( !file_w) { cout << "Fehler bei Öffnen\n"; return 1; }
    std::vector<DataClass> vec_dat;
    vec_dat.push_back(DataClass("Ein Text", 123));
    vec_dat.push_back(DataClass("Mehr Text", 321));
    vec_dat.emplace_back("Viel mehr Text", 333);
    for(const auto &elem : vec_dat){
        elem.write(file_w);
    }
    file_w.close();
    std::ifstream file_r("data.dat", std::ios::binary);
    if( !file_r) { cout << "Fehler bei Öffnen\n"; return 1; }
    DataClass dat_r;
    while( file_r ) {
        dat_r.read(file_r);
        if( file_r.eof()) break;
        dat_r.print(cout);
    }
}

Godbolt Listing lst-0881-godb.cpp, https://godbolt.org/z/b3W48s86z:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/b3W48s86z 
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using std::cout; using std::string;
class DataClass {
    std::string text_;
    int data_;
public:
    DataClass(string t="", int i=0)
      : text_{t}, data_{i} {}
    std::ostream& write(std::ostream& os) const {
        os << text_ << std::ends;
        os.write(reinterpret_cast<const char*>(&data_), sizeof(data_));
        return os;
    }
    std::istream& read(std::istream& is) {
        std::getline(is, text_, '\0');
        is.read(reinterpret_cast<char*>(&data_), sizeof(data_));
        return is;
    }
    std::ostream& print(std::ostream& os) {
        return os << text_ << " : " << data_ << std::endl;
    }
};
int main() {
    std::ofstream file_w("data.dat", std::ios::binary);
    if( !file_w) { cout << "Fehler bei Öffnen\n"; return 1; }
    std::vector<DataClass> vec_dat;
    vec_dat.push_back(DataClass("Ein Text", 123));
    vec_dat.push_back(DataClass("Mehr Text", 321));
    vec_dat.emplace_back("Viel mehr Text", 333);
    for(const auto &elem : vec_dat){
        elem.write(file_w);
    }
    file_w.close();
    std::ifstream file_r("data.dat", std::ios::binary);
    if( !file_r) { cout << "Fehler bei Öffnen\n"; return 1; }
    DataClass dat_r;
    while( file_r ) {
        dat_r.read(file_r);
        if( file_r.eof()) break;
        dat_r.print(cout);
    }
}

Listing 27.24: Ausgaben zwischen Threads mit »osyncstream« synchronisieren

Book listing lst-0883-book.cpp:

// https://godbolt.org/z/dz75jr1rM 
#include <iostream>
#include <thread>
#include <syncstream>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long von, long schritt, long bis) {
    for (auto n=von; n<=bis; n+=schritt) {
        std::osyncstream osync{ std::cout }; // Sync auf cout, solange osync existiert
        osync << "fib("<<n<<")=" << fib(n) << '\n';
    }
}
int main() {
    std::jthread f40{ runFib, 1, 3, 40 };
    std::jthread f41{ runFib, 2, 3, 41 };
    std::jthread f42{ runFib, 3, 3, 42 };
}

Godbolt Listing lst-0883-godb.cpp, https://godbolt.org/z/dz75jr1rM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dz75jr1rM 
#include <iostream>
#include <thread>
#include <syncstream>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long von, long schritt, long bis) {
    for (auto n=von; n<=bis; n+=schritt) {
        std::osyncstream osync{ std::cout }; // Sync auf cout, solange osync existiert
        osync << "fib("<<n<<")=" << fib(n) << '\n';
    }
}
int main() {
    std::jthread f40{ runFib, 1, 3, 40 };
    std::jthread f41{ runFib, 2, 3, 41 };
    std::jthread f42{ runFib, 3, 3, 42 };
}

Listing 27.25: Schreiben in einen »stringstream«

Book listing lst-0884-book.cpp:

// https://godbolt.org/z/cbGbcT178 
#include <sstream>  // ostringstream
#include <iostream>
int main() {
    std::ostringstream ostr;
    double dval = 3.1415;
    int ival = 4321;
    ostr << dval << " : " << ival;
    const std::string sval = ostr.str();
    std::cout << sval << std::endl;    // Ausgabe: 3.1415 : 4321
}

Godbolt Listing lst-0884-godb.cpp, https://godbolt.org/z/cbGbcT178:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cbGbcT178 
#include <sstream>  // ostringstream
#include <iostream>
int main() {
    std::ostringstream ostr;
    double dval = 3.1415;
    int ival = 4321;
    ostr << dval << " : " << ival;
    const std::string sval = ostr.str();
    std::cout << sval << std::endl;    // Ausgabe: 3.1415 : 4321
}

Listing 27.26: Lesen aus einem »stringstream«

Book listing lst-0885-book.cpp:

// https://godbolt.org/z/1EMox3hW5 
#include <sstream>  // istringstream
#include <iostream>
int main() {
    std::istringstream istr;
    std::string sval("3.1415 : 4321");
    std::string none;
    double dval=0.0;
    int ival=0;
    istr.str(sval);                // initialisieren
    istr >> dval >> none >> ival;  // auslesen
    if( ! istr.eof() ) {
        std::cout << "Fehler beim Konvertieren\n"; return 1;
    }
    std::cout << dval << " == " << none << " == " << ival << "\n";
    // Ausgabe: 3.1415 == : == 4321
}

Godbolt Listing lst-0885-godb.cpp, https://godbolt.org/z/1EMox3hW5:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1EMox3hW5 
#include <sstream>  // istringstream
#include <iostream>
int main() {
    std::istringstream istr;
    std::string sval("3.1415 : 4321");
    std::string none;
    double dval=0.0;
    int ival=0;
    istr.str(sval);                // initialisieren
    istr >> dval >> none >> ival;  // auslesen
    if( ! istr.eof() ) {
        std::cout << "Fehler beim Konvertieren\n"; return 1;
    }
    std::cout << dval << " == " << none << " == " << ival << "\n";
    // Ausgabe: 3.1415 == : == 4321
}

Listing 27.27: Typkonvertierung mittels »stringstream«

Book listing lst-0886-book.cpp:

// https://godbolt.org/z/vs5henTrz 
#include <sstream> // stringstream
#include <iostream>
#include <stdexcept> // invalid_argument
template <class T1, class T2>
void myConvert(const T1& in, T2& out) {
    std::stringstream ss;
    ss << in;
    ss >> out;
    if( ! ss.eof() ) {
        throw std::invalid_argument("Fehler beim Konvertieren");
    }
}
int main() {
    std::string sval;
    float fval=3.1415f;
    std::string sdval("5.321");
    double dsval=0;
    std::string gehtnicht("geht nicht");
    try {
        myConvert(fval, sval);
        std::cout << sval << std::endl;  // Ausgabe: 3.1415
        myConvert(sdval, dsval);
        std::cout << dsval << std::endl; // Ausgabe: 5.321
        myConvert(gehtnicht, dsval);     // löst "Fehler beim Konvertieren" aus
    }
    catch(const std::invalid_argument& e) {
        std::cout << e.what() << std::endl;
    }
}

Godbolt Listing lst-0886-godb.cpp, https://godbolt.org/z/vs5henTrz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vs5henTrz 
#include <sstream> // stringstream
#include <iostream>
#include <stdexcept> // invalid_argument
template <class T1, class T2>
void myConvert(const T1& in, T2& out) {
    std::stringstream ss;
    ss << in;
    ss >> out;
    if( ! ss.eof() ) {
        throw std::invalid_argument("Fehler beim Konvertieren");
    }
}
int main() {
    std::string sval;
    float fval=3.1415f;
    std::string sdval("5.321");
    double dsval=0;
    std::string gehtnicht("geht nicht");
    try {
        myConvert(fval, sval);
        std::cout << sval << std::endl;  // Ausgabe: 3.1415
        myConvert(sdval, dsval);
        std::cout << dsval << std::endl; // Ausgabe: 5.321
        myConvert(gehtnicht, dsval);     // löst "Fehler beim Konvertieren" aus
    }
    catch(const std::invalid_argument& e) {
        std::cout << e.what() << std::endl;
    }
}

Listing 27.28: Die Funktion »to_string«

Book listing lst-0887-book.cpp:

// https://godbolt.org/z/z6sYqM48e 
#include <iostream>
#include <string>
void show(double f) {
    std::cout << "os: " << f
       << "\t to_string: " << std::to_string(f) << "\n";
}
int main() {
    show(23.43);     // Ausgabe: os: 23.43    to_string: 23.430000
    show(1e-9);      // Ausgabe: os: 1e-09    to_string: 0.000000
    show(1e40);      // Ausgabe: os: 1e+40    to_string: 100…0752.000000
    show(1e-40);     // Ausgabe: os: 1e-40    to_string: 0.000000
    show(123456789); // Ausgabe: os: 1.23457e+08  to_string: 123456789.000000
}

Godbolt Listing lst-0887-godb.cpp, https://godbolt.org/z/z6sYqM48e:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/z6sYqM48e 
#include <iostream>
#include <string>
void show(double f) {
    std::cout << "os: " << f
       << "\t to_string: " << std::to_string(f) << "\n";
}
int main() {
    show(23.43);     // Ausgabe: os: 23.43    to_string: 23.430000
    show(1e-9);      // Ausgabe: os: 1e-09    to_string: 0.000000
    show(1e40);      // Ausgabe: os: 1e+40    to_string: 100…0752.000000
    show(1e-40);     // Ausgabe: os: 1e-40    to_string: 0.000000
    show(123456789); // Ausgabe: os: 1.23457e+08  to_string: 123456789.000000
}

Listing 27.29: Daten aus dem »rdbuf« übertragen

Book listing lst-0890-book.cpp:

// https://godbolt.org/z/on6W73nz1 
#include <fstream>
#include <iostream>
#include <memory> // unique_ptr
int main() {
    std::fstream file("27Streams.tex");          // Datei zum Lesen öffnen
    auto bufptr = file.rdbuf();                  // std::streambuf*
    auto size = bufptr->pubseekoff(0, file.end); // std::streamsize
    bufptr->pubseekoff(0, file.beg);             // wieder an den Anfang
    auto buffer = std::unique_ptr<char[]>(new char[size]); // Speicher holen
    auto n = bufptr->sgetn(buffer.get(), size);  // übertrage Anzahl Zeichen
    std::cout << "Zeichen gelesen: " << n << "\n";
    std::cout.write(buffer.get(), size);         // char[] ausgeben
}

Godbolt Listing lst-0890-godb.cpp, https://godbolt.org/z/on6W73nz1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/on6W73nz1 
#include <fstream>
#include <iostream>
#include <memory> // unique_ptr
int main() {
    std::fstream file("27Streams.tex");          // Datei zum Lesen öffnen
    auto bufptr = file.rdbuf();                  // std::streambuf*
    auto size = bufptr->pubseekoff(0, file.end); // std::streamsize
    bufptr->pubseekoff(0, file.beg);             // wieder an den Anfang
    auto buffer = std::unique_ptr<char[]>(new char[size]); // Speicher holen
    auto n = bufptr->sgetn(buffer.get(), size);  // übertrage Anzahl Zeichen
    std::cout << "Zeichen gelesen: " << n << "\n";
    std::cout.write(buffer.get(), size);         // char[] ausgeben
}

Listing 27.30: So fügen Sie Pfade zusammen.

Book listing lst-0892-book.cpp:

// https://godbolt.org/z/1YPT3asMz 
#include <filesystem>   // std::filesystem
#include <iostream>
namespace fs = std::filesystem; using std::cout; using std::endl;
int main() {
    // Pfadkomponenten
    fs::path root {"/"};
    fs::path dir {"var/www/"};
    fs::path index {"index.html"};
    // zusammenfügen
    fs::path p = root / dir / index;     // operator/
    // ausgeben
    cout << "Name: " << p << endl;       // "/var/www/index.html"
    // zerlegen
    cout << "Vater: " << p.parent_path() << endl; // "/var/www"
    cout << "Name: " << p.filename() << endl;     // "index.html"
    cout << "Endung: " << p.extension() << endl;  // ".html"
    // Information
    cout << std::boolalpha;
    cout << "Existiert? " << fs::exists(p) << endl;
    cout << "Echte Datei? " << fs::is_regular_file(p) << endl;
}

Godbolt Listing lst-0892-godb.cpp, https://godbolt.org/z/1YPT3asMz:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1YPT3asMz 
#include <filesystem>   // std::filesystem
#include <iostream>
namespace fs = std::filesystem; using std::cout; using std::endl;
int main() {
    // Pfadkomponenten
    fs::path root {"/"};
    fs::path dir {"var/www/"};
    fs::path index {"index.html"};
    // zusammenfügen
    fs::path p = root / dir / index;     // operator/
    // ausgeben
    cout << "Name: " << p << endl;       // "/var/www/index.html"
    // zerlegen
    cout << "Vater: " << p.parent_path() << endl; // "/var/www"
    cout << "Name: " << p.filename() << endl;     // "index.html"
    cout << "Endung: " << p.extension() << endl;  // ".html"
    // Information
    cout << std::boolalpha;
    cout << "Existiert? " << fs::exists(p) << endl;
    cout << "Echte Datei? " << fs::is_regular_file(p) << endl;
}

GodboltId:M8xjcnKxq

Book listing lst-0893-book.cpp:

// https://godbolt.org/z/M8xjcnKxq 
#include <format>
#include <chrono>
#include <string>
#include <string_view>
#include <iostream>
using namespace std; using namespace std::literals;
void pr(string_view s) { cout << s << endl; }
double pi = 3.14159265359;

int main() {
  pr(format("Hallo, {}!", "Leser"));             // einfacher C-String
  pr(format("Hallo, {}!", "Autor"s));            // einfacher String
  pr(format("Du bist {} Jahre alt.", 30));       // Ganzzahlen
  pr(format("Das macht {:.2f} Euro.", 19.9933)); // Fließkommazahl, 2 Stellen
  pr(format("Wissenschaftlich: {:e}", -44.876)); // ergibt "-4.487600e+01"
  pr(format("Binär von {} ist {:b}.", 42, 42));  // binär ohne Basis
  pr(format("Hex von {} ist {:#x}.", 73, 73));   // hexadezimal mit Basis
  pr(format("Mit Nullen aufgefüllt: {:03}", 7)); // ergibt "007"
  pr(format("|{0:<10}|{1:^10}|{2:>10}|", "li", "mi", "re"));
  // Ausrichtung und Index
  pr(format("{} {:.9}!", "Boa", "Constrictor")); // ohne Index, String abschneiden
  using namespace std::chrono;                   // schicke Zeitangaben:
  pr(format("{}, {}", 2023y/11/5, minutes{20})); // Ausgabe: 2023-11-05, 20min
}

Godbolt Listing lst-0893-godb.cpp, https://godbolt.org/z/M8xjcnKxq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/M8xjcnKxq 
#include <format>
#include <chrono>
#include <string>
#include <string_view>
#include <iostream>
using namespace std; using namespace std::literals;
void pr(string_view s) { cout << s << endl; }
double pi = 3.14159265359;

int main() {
  pr(format("Hallo, {}!", "Leser"));             // einfacher C-String
  pr(format("Hallo, {}!", "Autor"s));            // einfacher String
  pr(format("Du bist {} Jahre alt.", 30));       // Ganzzahlen
  pr(format("Das macht {:.2f} Euro.", 19.9933)); // Fließkommazahl, 2 Stellen
  pr(format("Wissenschaftlich: {:e}", -44.876)); // ergibt "-4.487600e+01"
  pr(format("Binär von {} ist {:b}.", 42, 42));  // binär ohne Basis
  pr(format("Hex von {} ist {:#x}.", 73, 73));   // hexadezimal mit Basis
  pr(format("Mit Nullen aufgefüllt: {:03}", 7)); // ergibt "007"
  pr(format("|{0:<10}|{1:^10}|{2:>10}|", "li", "mi", "re"));
  // Ausrichtung und Index
  pr(format("{} {:.9}!", "Boa", "Constrictor")); // ohne Index, String abschneiden
  using namespace std::chrono;                   // schicke Zeitangaben:
  pr(format("{}, {}", 2023y/11/5, minutes{20})); // Ausgabe: 2023-11-05, 20min
}

Listing 27.31: Ein Formatierer kann parsen und formatieren delegieren.

Book listing lst-0894-book.cpp:

// https://godbolt.org/z/jYsbxqzYW 
#include <format>
#include <string>
#include <vector>
#include <iostream>
struct Elb {
  std::string name;
  int geb;
  std::string epoche;
  std::string volk;
};
template<> struct std::formatter<Elb> {
  std::formatter<std::string> sub_fmt;
  constexpr auto parse(std::format_parse_context& pctx) {
    return sub_fmt.parse(pctx); // liefert iterator auf '}'
  }
  auto format(const Elb& elb, std::format_context& fctx) const {
    std::string s = std::format("{}/{} ({} {})",
        elb.name, elb.volk, elb.geb, elb.epoche);
    return sub_fmt.format(s, fctx); // formatieren delegieren
  }
};
int main() {
  std::vector<Elb> elben{
    {"Feanor", 1169, "EZ", "Nordor"},
    {"Galadriel", 1362, "EZ", "Noldor"},
    {"Legolas", 87, "DZ", "Sindar"},
    {"Elrond", 532, "EZ", "Halbelb"},
    {"Elwe", 1050, "EZ", "Sindar"},
  };
  for (const auto& e : elben) {
    std::cout << std::format("Elb: {:>20}", e) << std::endl;
  }
}

Godbolt Listing lst-0894-godb.cpp, https://godbolt.org/z/jYsbxqzYW:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jYsbxqzYW 
#include <format>
#include <string>
#include <vector>
#include <iostream>
struct Elb {
  std::string name;
  int geb;
  std::string epoche;
  std::string volk;
};
template<> struct std::formatter<Elb> {
  std::formatter<std::string> sub_fmt;
  constexpr auto parse(std::format_parse_context& pctx) {
    return sub_fmt.parse(pctx); // liefert iterator auf '}'
  }
  auto format(const Elb& elb, std::format_context& fctx) const {
    std::string s = std::format("{}/{} ({} {})",
        elb.name, elb.volk, elb.geb, elb.epoche);
    return sub_fmt.format(s, fctx); // formatieren delegieren
  }
};
int main() {
  std::vector<Elb> elben{
    {"Feanor", 1169, "EZ", "Nordor"},
    {"Galadriel", 1362, "EZ", "Noldor"},
    {"Legolas", 87, "DZ", "Sindar"},
    {"Elrond", 532, "EZ", "Halbelb"},
    {"Elwe", 1050, "EZ", "Sindar"},
  };
  for (const auto& e : elben) {
    std::cout << std::format("Elb: {:>20}", e) << std::endl;
  }
}

Listing 27.32: Ein Formatierer kann selbst parsen und ausgeben.

Book listing lst-0895-book.cpp:

// https://godbolt.org/z/WqjK31Gn6 
// 'Elb' wie zuvor…
template<> struct std::formatter<Elb> {
  std::string attribs;                 // Folge von '%n', '%g', '%e', '%v' und anderem
  constexpr auto parse(std::format_parse_context& pctx) {
    auto it = std::ranges::find(pctx.begin(), pctx.end(), '}');// suche '}'
    attribs = std::string(pctx.begin(), it);                   // alles speichern
    return it;                                                 // zeigt auf '}'
  }
  auto format(const Elb& elb, std::format_context& fctx) const {
    auto out = fctx.out();                                      // hier hinein
    for(auto n=0u; n<attribs.size()-1; ++n) {
      if(attribs[n] == '%') {             // Instruktion, ein Mitglied auszugeben
        switch(attribs[++n]) {
          case 'n': out = std::format_to(out, "{}", elb.name); break;
          case 'g': out = std::format_to(out, "{}", elb.geb); break;
          case 'e': out = std::format_to(out, "{}", elb.epoche); break;
          case 'v': out = std::format_to(out, "{}", elb.volk); break;
          case '%': out = std::format_to(out, "%"); break;      // %% wird zu %
        }
      } else {
        out = std::format_to(out, "{}", attribs[n]);           // alles andere
      }
    }
    return out;                                                // zeigt ans Ende
  }
};
int main() {
  Elb e{"Feanor", 1169, "EZ", "Nordor"};
  std::cout << std::format("{:Elb %n}", e) << std::endl;
  // Ausgabe: Elb Feanor
  std::cout << std::format("Elb {:%n, %v, geboren %g im Zeitalter %e}\n", e);
  // Ausgabe: Elb Feanor, Nordor, geboren 1169 im Zeitalter EZ
}

Godbolt Listing lst-0895-godb.cpp, https://godbolt.org/z/WqjK31Gn6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/WqjK31Gn6 
// 'Elb' wie zuvor…
template<> struct std::formatter<Elb> {
  std::string attribs;                 // Folge von '%n', '%g', '%e', '%v' und anderem
  constexpr auto parse(std::format_parse_context& pctx) {
    auto it = std::ranges::find(pctx.begin(), pctx.end(), '}');// suche '}'
    attribs = std::string(pctx.begin(), it);                   // alles speichern
    return it;                                                 // zeigt auf '}'
  }
  auto format(const Elb& elb, std::format_context& fctx) const {
    auto out = fctx.out();                                      // hier hinein
    for(auto n=0u; n<attribs.size()-1; ++n) {
      if(attribs[n] == '%') {             // Instruktion, ein Mitglied auszugeben
        switch(attribs[++n]) {
          case 'n': out = std::format_to(out, "{}", elb.name); break;
          case 'g': out = std::format_to(out, "{}", elb.geb); break;
          case 'e': out = std::format_to(out, "{}", elb.epoche); break;
          case 'v': out = std::format_to(out, "{}", elb.volk); break;
          case '%': out = std::format_to(out, "%"); break;      // %% wird zu %
        }
      } else {
        out = std::format_to(out, "{}", attribs[n]);           // alles andere
      }
    }
    return out;                                                // zeigt ans Ende
  }
};
int main() {
  Elb e{"Feanor", 1169, "EZ", "Nordor"};
  std::cout << std::format("{:Elb %n}", e) << std::endl;
  // Ausgabe: Elb Feanor
  std::cout << std::format("Elb {:%n, %v, geboren %g im Zeitalter %e}\n", e);
  // Ausgabe: Elb Feanor, Nordor, geboren 1169 im Zeitalter EZ
}

Listing 28.1: So geben Sie mit »pair« zwei Werte gleichzeitig zurück.

Book listing lst-0896-book.cpp:

// https://godbolt.org/z/4YM9d99xG 
#include <iostream>
#include <string>
#include <vector>
#include <utility> // pair
using std::pair; using std::cout; using std::cin; using std::string;
std::vector<string> monate { "Jan", "Feb", "Mar" };
std::vector temps { 8, 12, 11 };
std::pair<string, int> monatMitTemp(size_t m) {
    auto monat = monate.at(m);
    auto temperatur = temps.at(m);
    return std::make_pair(monat, temperatur);
}
int main() {
    std::pair daten = monatMitTemp(1);
    cout << "Monat : " << daten.first << std::endl; // Ausgabe: Monat : Feb
    cout << "Temperatur : " << daten.second << std::endl; 
    // Ausgabe: Temperatur : 12
}

Godbolt Listing lst-0896-godb.cpp, https://godbolt.org/z/4YM9d99xG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4YM9d99xG 
#include <iostream>
#include <string>
#include <vector>
#include <utility> // pair
using std::pair; using std::cout; using std::cin; using std::string;
std::vector<string> monate { "Jan", "Feb", "Mar" };
std::vector temps { 8, 12, 11 };
std::pair<string, int> monatMitTemp(size_t m) {
    auto monat = monate.at(m);
    auto temperatur = temps.at(m);
    return std::make_pair(monat, temperatur);
}
int main() {
    std::pair daten = monatMitTemp(1);
    cout << "Monat : " << daten.first << std::endl; // Ausgabe: Monat : Feb
    cout << "Temperatur : " << daten.second << std::endl; 
    // Ausgabe: Temperatur : 12
}

Listing 28.2: Mit »tuple« können Sie beliebig viele Elemente zurückgeben.

Book listing lst-0897-book.cpp:

// https://godbolt.org/z/47jb7nEG4 
#include <iostream>
#include <string>
#include <algorithm> // min, max
#include <tuple>
using std::tuple; using std::make_tuple; using std::get; using std::cout;
using std::string;
tuple<int,int,int> ordne(int a, int b, int c) {
  using std::min; using std::max;
  auto x = min(a,min(b,c));
  auto y = max(min(a,b), min(max(a,b),c));
  auto z = max(a,max(b,c));
  return make_tuple(x, y, z);
}
auto praeser(int jahr) {
  using namespace std::literals;
  if(jahr>=2017)
    return make_tuple("Frank-Walter"s, "Steinmeier"s, "SPD"s, 1956);
  if(jahr>=2012)
    return make_tuple("Joachim"s, "Gauck"s, "-"s, 1940);
  // …
}
int main() {
  tuple<int,int,int> zs = ordne(23, 42, 7);
  cout << get<0>(zs) <<' '<< get<1>(zs) <<' '<< get<2>(zs) <<'\n'; 
  // Ausgabe: 7 23 42
  auto ps = praeser(2015);
  cout << get<1>(ps) << '\n'; // Ausgabe: Gauck
}

Godbolt Listing lst-0897-godb.cpp, https://godbolt.org/z/47jb7nEG4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/47jb7nEG4 
#include <iostream>
#include <string>
#include <algorithm> // min, max
#include <tuple>
using std::tuple; using std::make_tuple; using std::get; using std::cout;
using std::string;
tuple<int,int,int> ordne(int a, int b, int c) {
  using std::min; using std::max;
  auto x = min(a,min(b,c));
  auto y = max(min(a,b), min(max(a,b),c));
  auto z = max(a,max(b,c));
  return make_tuple(x, y, z);
}
auto praeser(int jahr) {
  using namespace std::literals;
  if(jahr>=2017)
    return make_tuple("Frank-Walter"s, "Steinmeier"s, "SPD"s, 1956);
  if(jahr>=2012)
    return make_tuple("Joachim"s, "Gauck"s, "-"s, 1940);
  // …
}
int main() {
  tuple<int,int,int> zs = ordne(23, 42, 7);
  cout << get<0>(zs) <<' '<< get<1>(zs) <<' '<< get<2>(zs) <<'\n'; 
  // Ausgabe: 7 23 42
  auto ps = praeser(2015);
  cout << get<1>(ps) << '\n'; // Ausgabe: Gauck
}

Listing 28.3: »get« funktioniert mit einem Typ als Index.

Book listing lst-0898-book.cpp:

// https://godbolt.org/z/cx8b9seaW 
// … wie zuvor …
int main() {
  tuple ps = praeser(2015);
  cout << get<int>(ps) << '\n';    // Ausgabe: 1940
  cout << get<string>(ps) << '\n'; //                 (ERR)  nicht eindeutig
}

Godbolt Listing lst-0898-godb.cpp, https://godbolt.org/z/cx8b9seaW:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cx8b9seaW 
// … wie zuvor …
int main() {
  tuple ps = praeser(2015);
  cout << get<int>(ps) << '\n';    // Ausgabe: 1940
  cout << get<string>(ps) << '\n'; //                 (ERR)  nicht eindeutig
}

Listing 28.4: Tupel zerlegen mit »tie« und »ignore«

Book listing lst-0899-book.cpp:

// https://godbolt.org/z/YzTvoE3x6 
// … wie zuvor …
int main() {
  using std::tie; using std::ignore;
  string nachname {};
  int gebj {};
  tie(ignore, nachname, ignore, gebj) = praeser(2015);
  cout << nachname << ' ' << gebj << '\n'; // Ausgabe: Gauck 1940
}

Godbolt Listing lst-0899-godb.cpp, https://godbolt.org/z/YzTvoE3x6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YzTvoE3x6 
// … wie zuvor …
int main() {
  using std::tie; using std::ignore;
  string nachname {};
  int gebj {};
  tie(ignore, nachname, ignore, gebj) = praeser(2015);
  cout << nachname << ' ' << gebj << '\n'; // Ausgabe: Gauck 1940
}

Listing 28.5: Tupel implementieren lexikografische Ordnung.

Book listing lst-0900-book.cpp:

// https://godbolt.org/z/jrP4v76aj 
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <algorithm> // ranges::sort
using std::tuple; using std::get; using std::cout; using std::string;
int main() {
    std::vector<tuple<string,string,int>> armstrongs =
      { {"Armstrong", "Louis", 1901}  // Initialisieren per Initialisierungsliste
      , {"Armstrong", "Lance", 1971}
      , {"Armstrong", "Neil", 1930} };
    std::ranges::sort(armstrongs);  // Lance < Louis < Neil
    for(const auto& a : armstrongs) {
      cout << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "\n";
    }
}

Godbolt Listing lst-0900-godb.cpp, https://godbolt.org/z/jrP4v76aj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/jrP4v76aj 
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <algorithm> // ranges::sort
using std::tuple; using std::get; using std::cout; using std::string;
int main() {
    std::vector<tuple<string,string,int>> armstrongs =
      { {"Armstrong", "Louis", 1901}  // Initialisieren per Initialisierungsliste
      , {"Armstrong", "Lance", 1971}
      , {"Armstrong", "Neil", 1930} };
    std::ranges::sort(armstrongs);  // Lance < Louis < Neil
    for(const auto& a : armstrongs) {
      cout << get<0>(a) << ", " << get<1>(a) << ", " << get<2>(a) << "\n";
    }
}

Listing 28.6: Tupel als Schlüssel

Book listing lst-0901-book.cpp:

// https://godbolt.org/z/9qhMo6zbb 
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>

using std::tuple; using std::get; using std::cout; using std::string;

int main() {
    std::map<tuple<int,string>,double> m { {{12,"x"},3.14} };
    cout << m[{12,"x"}] << "\n"; // Ausgabe: 3.14
    std::unordered_set<tuple<int,string>> s { {12,"x"} }; //                 (ERR)  kein std::hash
}

Godbolt Listing lst-0901-godb.cpp, https://godbolt.org/z/9qhMo6zbb:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9qhMo6zbb 
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>

using std::tuple; using std::get; using std::cout; using std::string;

int main() {
    std::map<tuple<int,string>,double> m { {{12,"x"},3.14} };
    cout << m[{12,"x"}] << "\n"; // Ausgabe: 3.14
    std::unordered_set<tuple<int,string>> s { {12,"x"} }; //                 (ERR)  kein std::hash
}

Listing 28.7: Tupel als Schlüssel

Book listing lst-0902-book.cpp:

// https://godbolt.org/z/vdT7TTjWK 
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>
using std::tuple; using std::tie; using std::cout; using std::string;
struct Point {
    int x,y,z;
    bool operator<(const Point &b) {
        return tie(x,y,z) < tie(b.x, b.y, b.z);
    }
};
int main() {
    Point a{ 11, 22, 33 };
    Point b{ 11, 33, 0 };
    cout << std::boolalpha << (a < b) << "\n"; // Ausgabe: true
}

Godbolt Listing lst-0902-godb.cpp, https://godbolt.org/z/vdT7TTjWK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vdT7TTjWK 
#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_set>
using std::tuple; using std::tie; using std::cout; using std::string;
struct Point {
    int x,y,z;
    bool operator<(const Point &b) {
        return tie(x,y,z) < tie(b.x, b.y, b.z);
    }
};
int main() {
    Point a{ 11, 22, 33 };
    Point b{ 11, 33, 0 };
    cout << std::boolalpha << (a < b) << "\n"; // Ausgabe: true
}

Listing 28.8: Mehrere kleine Tupel zu einem großen zusammenfügen

Book listing lst-0903-book.cpp:

// https://godbolt.org/z/eq1dqWbe9 
#include <iostream>
#include <string>
#include <tuple>
using std::tuple; using std::cout; using std::string;
int main() {
    tuple<int,string> a { 12, "gnorf" };
    tuple b { 666 };
    tuple<double,double,string> c { 77.77, 33.33, "frong" };
    tuple<int,string,int,double,double,string> r = std::tuple_cat( a, b, c );
    cout << std::get<2>(r) << "\n"; // Ausgabe: 666
}

Godbolt Listing lst-0903-godb.cpp, https://godbolt.org/z/eq1dqWbe9:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eq1dqWbe9 
#include <iostream>
#include <string>
#include <tuple>
using std::tuple; using std::cout; using std::string;
int main() {
    tuple<int,string> a { 12, "gnorf" };
    tuple b { 666 };
    tuple<double,double,string> c { 77.77, 33.33, "frong" };
    tuple<int,string,int,double,double,string> r = std::tuple_cat( a, b, c );
    cout << std::get<2>(r) << "\n"; // Ausgabe: 666
}

Listing 28.9: Nützliche Tuple-Type-Traits

Book listing lst-0904-book.cpp:

// https://godbolt.org/z/Psdz9s9Gc 
#include <iostream>
#include <string>
#include <tuple>
using namespace std;
template<typename Tuple>
auto back(Tuple &&tuple) {
    using Noref = typename remove_reference<Tuple>::type; // falls Tuple&
    constexpr auto sz = tuple_size<Noref>::value;
    return get<sz-1>(forward<Tuple>(tuple));
}
int main() {
    tuple<string,int,string> enterprise = make_tuple("NCC", 1701, "D");
    cout << back(enterprise) << "\n"; // Ausgabe: D
}

Godbolt Listing lst-0904-godb.cpp, https://godbolt.org/z/Psdz9s9Gc:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Psdz9s9Gc 
#include <iostream>
#include <string>
#include <tuple>
using namespace std;
template<typename Tuple>
auto back(Tuple &&tuple) {
    using Noref = typename remove_reference<Tuple>::type; // falls Tuple&
    constexpr auto sz = tuple_size<Noref>::value;
    return get<sz-1>(forward<Tuple>(tuple));
}
int main() {
    tuple<string,int,string> enterprise = make_tuple("NCC", 1701, "D");
    cout << back(enterprise) << "\n"; // Ausgabe: D
}

Listing 28.10: Übereinstimmung, Suche und Aufzählung mit regulären Ausdrücken

Book listing lst-0905-book.cpp:

// https://godbolt.org/z/zjboebEhc 
#include <string>
#include <iostream>
#include <regex>
using std::regex; using std::sregex_iterator; using std::string;
const regex rgxMobile(R"(01[567]\d{6,10})");        // Handy 0151-0179
bool isMobilephone(const string& text) {
  return std::regex_match(text, rgxMobile);         // Passt text ganz?
}
bool containsMobilephone(const string &text) {
  return std::regex_search(text, rgxMobile);        // irgendwo in text?
}
void listMobilephones(const string &text) {
  sregex_iterator begin{ text.cbegin(), text.cend(), rgxMobile };
  sregex_iterator end;
  for(auto it = begin; it != end; ++it)
    std::cout << it->str() << " ";                  // Treffertext
} // "xyz01709999 abc 0161887766 uvw" -> "01709999 161887766"

Godbolt Listing lst-0905-godb.cpp, https://godbolt.org/z/zjboebEhc:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/zjboebEhc 
#include <string>
#include <iostream>
#include <regex>
using std::regex; using std::sregex_iterator; using std::string;
const regex rgxMobile(R"(01[567]\d{6,10})");        // Handy 0151-0179
bool isMobilephone(const string& text) {
  return std::regex_match(text, rgxMobile);         // Passt text ganz?
}
bool containsMobilephone(const string &text) {
  return std::regex_search(text, rgxMobile);        // irgendwo in text?
}
void listMobilephones(const string &text) {
  sregex_iterator begin{ text.cbegin(), text.cend(), rgxMobile };
  sregex_iterator end;
  for(auto it = begin; it != end; ++it)
    std::cout << it->str() << " ";                  // Treffertext
} // "xyz01709999 abc 0161887766 uvw" -> "01709999 161887766"

Listing 28.11: Suche und Übereinstimmung

Book listing lst-0906-book.cpp:

// https://godbolt.org/z/E9hcWGMW4 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_match; using std::regex_search;
int main() {
    std::cout << std::boolalpha;
    regex muster {"ello"};
    std::string text = "Hello world";
    auto b1 = regex_match (text.cbegin(), text.cend(), muster); // passt nicht
    std::cout << b1 << "\n"; // Ausgabe: false
    auto b2 = regex_search(text.cbegin(), text.cend(), muster); // gefunden
    std::cout << b2 << "\n"; // Ausgabe: true
}

Godbolt Listing lst-0906-godb.cpp, https://godbolt.org/z/E9hcWGMW4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/E9hcWGMW4 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_match; using std::regex_search;
int main() {
    std::cout << std::boolalpha;
    regex muster {"ello"};
    std::string text = "Hello world";
    auto b1 = regex_match (text.cbegin(), text.cend(), muster); // passt nicht
    std::cout << b1 << "\n"; // Ausgabe: false
    auto b2 = regex_search(text.cbegin(), text.cend(), muster); // gefunden
    std::cout << b2 << "\n"; // Ausgabe: true
}

Listing 28.12: Zugriff auf die Trefferdetails

Book listing lst-0907-book.cpp:

// https://godbolt.org/z/Ed8ca4Keq 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
int main() {
    cmatch res;                              // für Detailergebnisse
    std::string text = "<h2>Ergebnis und Teile davon</h2>";
    regex muster{"<h(.)>([^<]+)"};           // Suchmuster mit Gruppen
    regex_search(text.c_str(), res, muster); // Details nach res
    std::cout << res[1] << ". "              // ()-Gruppe 1: H-Ebene
         << res[2] << std::endl;             // ()-Gruppe 2: H-Text
}

Godbolt Listing lst-0907-godb.cpp, https://godbolt.org/z/Ed8ca4Keq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Ed8ca4Keq 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
int main() {
    cmatch res;                              // für Detailergebnisse
    std::string text = "<h2>Ergebnis und Teile davon</h2>";
    regex muster{"<h(.)>([^<]+)"};           // Suchmuster mit Gruppen
    regex_search(text.c_str(), res, muster); // Details nach res
    std::cout << res[1] << ". "              // ()-Gruppe 1: H-Ebene
         << res[2] << std::endl;             // ()-Gruppe 2: H-Text
}

Listing 28.13: Treffer durch neuen Text ersetzen

Book listing lst-0908-book.cpp:

// https://godbolt.org/z/rErP43G89 
#include <regex>
#include <string>
#include <iostream>
using std::string;
int main() {
    string text = "Titel;Album;Interpret";
    std::regex muster{";"};
    string neu = std::regex_replace(text, muster, string{","});
    std::cout << neu << "\n"; // Ausgabe: Titel,Album,Interpret
}

Godbolt Listing lst-0908-godb.cpp, https://godbolt.org/z/rErP43G89:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rErP43G89 
#include <regex>
#include <string>
#include <iostream>
using std::string;
int main() {
    string text = "Titel;Album;Interpret";
    std::regex muster{";"};
    string neu = std::regex_replace(text, muster, string{","});
    std::cout << neu << "\n"; // Ausgabe: Titel,Album,Interpret
}

Listing 28.14: Schwer zu wartender regulärer Ausdruck

Book listing lst-0911-book.cpp:

// https://godbolt.org/z/v91WoqjPj 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
const regex muster{R"(^score\s+(\d+)\s+for\s+(\d+)\s+nights?\s+at\s+(.*))"};
void extract(const std::string &text) {
    cmatch res;
    regex_search(text.c_str(), res, muster);
    std::cout << res[1] << "," << res[2] << "," << res[3] << "\n";
}
int main() {
    extract("score 400 for 2 nights at Minas Tirith Airport");
    extract("score 84 for 1 night at Prancing Pony");
}

Godbolt Listing lst-0911-godb.cpp, https://godbolt.org/z/v91WoqjPj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/v91WoqjPj 
#include <regex>
#include <string>
#include <iostream>
using std::regex; using std::regex_search; using std::cmatch;
const regex muster{R"(^score\s+(\d+)\s+for\s+(\d+)\s+nights?\s+at\s+(.*))"};
void extract(const std::string &text) {
    cmatch res;
    regex_search(text.c_str(), res, muster);
    std::cout << res[1] << "," << res[2] << "," << res[3] << "\n";
}
int main() {
    extract("score 400 for 2 nights at Minas Tirith Airport");
    extract("score 84 for 1 night at Prancing Pony");
}

Listing 28.15: Teile benennen und dann zusammenfügen

Book listing lst-0912-book.cpp:

// https://godbolt.org/z/TK6n4dG37 
const string scoreKeyword = R"(^score\s+)";
const string numberOfPoints = R"((\d+))";
const string forKeyword = R"(\s+for\s+)";
const string numberOfNights = R"((\d+))";
const string nightsAtKeyword = R"(\s+nights?\s+at\s+)";
const string hotelName = R"((.*))";
const regex muster{ scoreKeyword + numberOfPoints +
    forKeyword + numberOfNights + nightsAtKeyword + hotelName };
}

Godbolt Listing lst-0912-godb.cpp, https://godbolt.org/z/TK6n4dG37:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TK6n4dG37 
const string scoreKeyword = R"(^score\s+)";
const string numberOfPoints = R"((\d+))";
const string forKeyword = R"(\s+for\s+)";
const string numberOfNights = R"((\d+))";
const string nightsAtKeyword = R"(\s+nights?\s+at\s+)";
const string hotelName = R"((.*))";
const regex muster{ scoreKeyword + numberOfPoints +
    forKeyword + numberOfNights + nightsAtKeyword + hotelName };
}

Listing 28.16: Innerhalb des Ausdrucks kommentieren

Book listing lst-0913-book.cpp:

// https://godbolt.org/z/MszTjE3dv 
const regex muster{R"(^score)"
    R"(\s+)"
    R"((\d+))"          // Punkte
    R"(\s+)"
    R"(for)"
    R"(\s+)"
    R"((\d+))"          // Anzahl Nächte
    R"(\s+)"
    R"(night)"
    R"(s?)"             // optional: Plural
    R"(\s+)"
    R"(at)"
    R"(\s+)"
    R"((.*))"           // Hotelname
    R"()"};

Godbolt Listing lst-0913-godb.cpp, https://godbolt.org/z/MszTjE3dv:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/MszTjE3dv 
const regex muster{R"(^score)"
    R"(\s+)"
    R"((\d+))"          // Punkte
    R"(\s+)"
    R"(for)"
    R"(\s+)"
    R"((\d+))"          // Anzahl Nächte
    R"(\s+)"
    R"(night)"
    R"(s?)"             // optional: Plural
    R"(\s+)"
    R"(at)"
    R"(\s+)"
    R"((.*))"           // Hotelname
    R"()"};

Listing 28.17: So erhalten Sie eine gleichverteilte Zufallszahl zwischen zwei Grenzen.

Book listing lst-0914-book.cpp:

// https://godbolt.org/z/6ecxTsYzj 
#include <random>
#include <vector>
#include <iostream>
void wuerfel() {
  std::default_random_engine engine{};         // Zufall normaler Qualität
  std::vector<size_t> counts{0,0,0,0,0,0};
  std::uniform_int_distribution<int> w6{0, 5}; // gleichverteilte Ganzzahlen
  for(auto i=1200*1000; i>0; --i)
    ++counts[w6(engine)];
  for(auto c : counts) std::cout<<" "<<c;
  std::cout << '\n';
}
int main() {
    wuerfel();
}

Godbolt Listing lst-0914-godb.cpp, https://godbolt.org/z/6ecxTsYzj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6ecxTsYzj 
#include <random>
#include <vector>
#include <iostream>
void wuerfel() {
  std::default_random_engine engine{};         // Zufall normaler Qualität
  std::vector<size_t> counts{0,0,0,0,0,0};
  std::uniform_int_distribution<int> w6{0, 5}; // gleichverteilte Ganzzahlen
  for(auto i=1200*1000; i>0; --i)
    ++counts[w6(engine)];
  for(auto c : counts) std::cout<<" "<<c;
  std::cout << '\n';
}
int main() {
    wuerfel();
}

Listing 28.18: Geschwindigkeiten der Zufallsgeneratoren

Book listing lst-0918-book.cpp:

// https://godbolt.org/z/W8WbbxY78 
#include <random>
#include <chrono>  // system_clock
#include <format>
#include <iostream>

using namespace std;
using namespace chrono;
const size_t LOOPS = 10*1000*1000;

template<typename ENGINE>
void messen(const string &title, ENGINE &engine) {
  const auto start = steady_clock::now();

  /* hart arbeiten */
  unsigned long long checksum = 0;
  size_t loops = LOOPS;
  while(loops-- > 0)
    checksum += engine();

  const auto now = steady_clock::now();
  nanoseconds dur_ns = now - start;
  cout << std::format("  {}: {:5} ns/loop  {:12} ns\n",
      title, dur_ns.count() / LOOPS, dur_ns.count());
}

int main() {
  { default_random_engine e{}; messen("      default", e ); }
  { random_device e{};         messen("       device", e ); }
  { minstd_rand0 e{};          messen(" minstd_rand0", e ); }
  { minstd_rand e{};           messen(" minstd_rand ", e ); }
  { mt19937 e{};               messen("   mt19937   ", e ); }
  { mt19937_64 e{};            messen("   mt19937_64", e ); }
  { ranlux24_base e{};         messen("ranlux24_base", e ); }
  { ranlux48_base e{};         messen("ranlux48_base", e ); }
  { ranlux24 e{};              messen("ranlux24     ", e ); }
  { ranlux48 e{};              messen("ranlux48     ", e ); }
  { knuth_b e{};               messen("      knuth_b", e ); }
  {
    using wide_t = unsigned long long ;
    independent_bits_engine<ranlux48, sizeof(wide_t)*8, wide_t> e{};
    messen("indep<ranlux>", e );
  }
  {
    using wide_t = unsigned long long;
    independent_bits_engine<
          default_random_engine,
          sizeof(wide_t)*8, wide_t>
      e {};
    messen("indep<default>", e );
  }
}

Godbolt Listing lst-0918-godb.cpp, https://godbolt.org/z/W8WbbxY78:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/W8WbbxY78 
#include <random>
#include <chrono>  // system_clock
#include <format>
#include <iostream>

using namespace std;
using namespace chrono;
const size_t LOOPS = 10*1000*1000;

template<typename ENGINE>
void messen(const string &title, ENGINE &engine) {
  const auto start = steady_clock::now();

  /* hart arbeiten */
  unsigned long long checksum = 0;
  size_t loops = LOOPS;
  while(loops-- > 0)
    checksum += engine();

  const auto now = steady_clock::now();
  nanoseconds dur_ns = now - start;
  cout << std::format("  {}: {:5} ns/loop  {:12} ns\n",
      title, dur_ns.count() / LOOPS, dur_ns.count());
}

int main() {
  { default_random_engine e{}; messen("      default", e ); }
  { random_device e{};         messen("       device", e ); }
  { minstd_rand0 e{};          messen(" minstd_rand0", e ); }
  { minstd_rand e{};           messen(" minstd_rand ", e ); }
  { mt19937 e{};               messen("   mt19937   ", e ); }
  { mt19937_64 e{};            messen("   mt19937_64", e ); }
  { ranlux24_base e{};         messen("ranlux24_base", e ); }
  { ranlux48_base e{};         messen("ranlux48_base", e ); }
  { ranlux24 e{};              messen("ranlux24     ", e ); }
  { ranlux48 e{};              messen("ranlux48     ", e ); }
  { knuth_b e{};               messen("      knuth_b", e ); }
  {
    using wide_t = unsigned long long ;
    independent_bits_engine<ranlux48, sizeof(wide_t)*8, wide_t> e{};
    messen("indep<ranlux>", e );
  }
  {
    using wide_t = unsigned long long;
    independent_bits_engine<
          default_random_engine,
          sizeof(wide_t)*8, wide_t>
      e {};
    messen("indep<default>", e );
  }
}

Listing 28.19: Eine Binomialverteilung

Book listing lst-0919-book.cpp:

// https://godbolt.org/z/hvM8K4oY6 
#include <random>
#include <vector>
#include <iostream>
using namespace std;
int main() {
    static const size_t size = 10;
    default_random_engine e{};                // Zufallsgenerator
    vector<size_t> counts(size+1);
    binomial_distribution<int> muenzen{size}; // wirft 10 Münzen, 0- bis 10-mal Kopf
    for(auto i=120*1000; i>0; --i)
        ++counts[muenzen(e)];                 // Münzen werfen
    for(auto c : counts) cout<<" "<<c;
    cout << '\n';
    // Beispielausgabe:
    // 109 1159 5344 14043 24806 29505 24544 13973 5252 1150 115
}

Godbolt Listing lst-0919-godb.cpp, https://godbolt.org/z/hvM8K4oY6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hvM8K4oY6 
#include <random>
#include <vector>
#include <iostream>
using namespace std;
int main() {
    static const size_t size = 10;
    default_random_engine e{};                // Zufallsgenerator
    vector<size_t> counts(size+1);
    binomial_distribution<int> muenzen{size}; // wirft 10 Münzen, 0- bis 10-mal Kopf
    for(auto i=120*1000; i>0; --i)
        ++counts[muenzen(e)];                 // Münzen werfen
    for(auto c : counts) cout<<" "<<c;
    cout << '\n';
    // Beispielausgabe:
    // 109 1159 5344 14043 24806 29505 24544 13973 5252 1150 115
}

Listing 28.20: Eine »double«-Zufallszahl

Book listing lst-0920-book.cpp:

// https://godbolt.org/z/94McsP7PG 
#include <random>
#include <iostream>
int main() {
    std::default_random_engine e{};
    std::uniform_real_distribution<double> unif{3,7}; // im halboff. Intervall [3,7)
    double u = unif(e);                          // Zufallszahl ermitteln
    std::cout << u << '\n';                      // Beispielausgabe: 3.52615
}

Godbolt Listing lst-0920-godb.cpp, https://godbolt.org/z/94McsP7PG:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/94McsP7PG 
#include <random>
#include <iostream>
int main() {
    std::default_random_engine e{};
    std::uniform_real_distribution<double> unif{3,7}; // im halboff. Intervall [3,7)
    double u = unif(e);                          // Zufallszahl ermitteln
    std::cout << u << '\n';                      // Beispielausgabe: 3.52615
}

Listing 28.21: Generierungsparameter für jede Zufallszahl einzeln ändern

Book listing lst-0921-book.cpp:

// https://godbolt.org/z/xz64qK3e5 
#include <random>
#include <iostream>
int main() {
    std::default_random_engine e{};
    using Dstr = std::uniform_int_distribution<int>;       // gleichverteilte int
    Dstr karte{};                                          // Verteilung erzeugen
    for(int n=32; n>=1; --n)
      std::cout <<" "<< karte(e, Dstr::param_type{1,n} );  // Parameter erst hier
    std::cout << '\n';
    // Ausgabe zum Beispiel:
    // 1 5 23 14 15 6 2 17 17 22 9 11 17 1 1 10 11 1 6 1 6 8 6 9 7 4 1 4 2 3 2 1
}

Godbolt Listing lst-0921-godb.cpp, https://godbolt.org/z/xz64qK3e5:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xz64qK3e5 
#include <random>
#include <iostream>
int main() {
    std::default_random_engine e{};
    using Dstr = std::uniform_int_distribution<int>;       // gleichverteilte int
    Dstr karte{};                                          // Verteilung erzeugen
    for(int n=32; n>=1; --n)
      std::cout <<" "<< karte(e, Dstr::param_type{1,n} );  // Parameter erst hier
    std::cout << '\n';
    // Ausgabe zum Beispiel:
    // 1 5 23 14 15 6 2 17 17 22 9 11 17 1 1 10 11 1 6 1 6 8 6 9 7 4 1 4 2 3 2 1
}

GodboltId:173nr4xxd

Book listing lst-0926-book.cpp:

// https://godbolt.org/z/173nr4xxd 
sleep(10min);
sleep(std::chrono::minutes{10});
sleep(std::chrono::duration<unsigned long,std::ratio<60>>{10});

Godbolt Listing lst-0926-godb.cpp, https://godbolt.org/z/173nr4xxd:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/173nr4xxd 
sleep(10min);
sleep(std::chrono::minutes{10});
sleep(std::chrono::duration<unsigned long,std::ratio<60>>{10});

GodboltId:5snr1hq9b

Book listing lst-0927-book.cpp:

// https://godbolt.org/z/5snr1hq9b 
#include <chrono>
void sleep(std::chrono::seconds s) { // nimmt Sekunden als Dauer
    /* ... */
}
/* ... */
int main() {
    using namespace std::chrono; // Literale verfügbar machen
    sleep(10min);   // 10 Minuten warten, also 600 Sekunden
    sleep(10ms);    //                     (ERR)  10 Millisekunden? Mit Sekunden nicht abzubilden.
}

Godbolt Listing lst-0927-godb.cpp, https://godbolt.org/z/5snr1hq9b:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5snr1hq9b 
#include <chrono>
void sleep(std::chrono::seconds s) { // nimmt Sekunden als Dauer
    /* ... */
}
/* ... */
int main() {
    using namespace std::chrono; // Literale verfügbar machen
    sleep(10min);   // 10 Minuten warten, also 600 Sekunden
    sleep(10ms);    //                     (ERR)  10 Millisekunden? Mit Sekunden nicht abzubilden.
}

GodboltId:h8vsjxsME

Book listing lst-0929-book.cpp:

// https://godbolt.org/z/h8vsjxsME 
#include <cinttypes> // int64_t
namespace std { namespace chrono {
class seconds {
    int64_t sec_;
public:
    seconds() = default;
    // … etc …
};
} }

Godbolt Listing lst-0929-godb.cpp, https://godbolt.org/z/h8vsjxsME:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/h8vsjxsME 
#include <cinttypes> // int64_t
namespace std { namespace chrono {
class seconds {
    int64_t sec_;
public:
    seconds() = default;
    // … etc …
};
} }

Listing 28.22: Mit »seconds« können Sie rechnen.

Book listing lst-0934-book.cpp:

// https://godbolt.org/z/hPPrPT69h 
#include <chrono>
#include <iostream>
void sleep(std::chrono::seconds dur) {
    std::cout << dur.count() << "s\n";
    /* ... */
}
int main() {
    using namespace std::chrono;
    sleep(3);          //                     (ERR)  Fehler: keine implizite Konvertierung von int
    sleep(seconds{4}); // okay
    sleep(5s);         // okay
    seconds x{6};
    sleep(x);          // okay
    auto y = 10s;
    y += 20s;          // Inkrementieren mit Sekunden
    sleep(y);          // nun also 30s
    y = y - 6s;        // Subtraktion von Sekunden
    sleep(y);          // und nun nur noch 24s
    y /= 2;            // Division durch einen Skalar
    sleep(y);          // 12s
    sleep(y + 7);      //                     (ERR)  Fehler: seconds+int geht nicht
}

Godbolt Listing lst-0934-godb.cpp, https://godbolt.org/z/hPPrPT69h:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hPPrPT69h 
#include <chrono>
#include <iostream>
void sleep(std::chrono::seconds dur) {
    std::cout << dur.count() << "s\n";
    /* ... */
}
int main() {
    using namespace std::chrono;
    sleep(3);          //                     (ERR)  Fehler: keine implizite Konvertierung von int
    sleep(seconds{4}); // okay
    sleep(5s);         // okay
    seconds x{6};
    sleep(x);          // okay
    auto y = 10s;
    y += 20s;          // Inkrementieren mit Sekunden
    sleep(y);          // nun also 30s
    y = y - 6s;        // Subtraktion von Sekunden
    sleep(y);          // und nun nur noch 24s
    y /= 2;            // Division durch einen Skalar
    sleep(y);          // 12s
    sleep(y + 7);      //                     (ERR)  Fehler: seconds+int geht nicht
}

Listing 28.23: Sie können »seconds« vergleichen.

Book listing lst-0935-book.cpp:

// https://godbolt.org/z/8c1r5xrs5 
#include <chrono>
#include <iostream>
using std::chrono::operator""s;  // nur Literalsuffix verfügbar machen
constexpr auto limit = 10s;
void action(std::chrono::seconds dur) {
    if(dur <= limit) {          // vergleichen
       std::cout << dur.count() << "s\n";
    } else {
       std::cout << "zu lang!\n";
    }
}
int main() {
    action(4s);   // Ausgabe: 4s
    action(20s);  // Ausgabe: zu lang!
}

Godbolt Listing lst-0935-godb.cpp, https://godbolt.org/z/8c1r5xrs5:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8c1r5xrs5 
#include <chrono>
#include <iostream>
using std::chrono::operator""s;  // nur Literalsuffix verfügbar machen
constexpr auto limit = 10s;
void action(std::chrono::seconds dur) {
    if(dur <= limit) {          // vergleichen
       std::cout << dur.count() << "s\n";
    } else {
       std::cout << "zu lang!\n";
    }
}
int main() {
    action(4s);   // Ausgabe: 4s
    action(20s);  // Ausgabe: zu lang!
}

Listing 28.24: Automatische Umrechnung zwischen Zeiteinheiten

Book listing lst-0936-book.cpp:

// https://godbolt.org/z/qrs63vdz1 
#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;             // Suffixe erlauben
    seconds mySecs = 121s;                   // seconds{121}
    std::cout << mySecs.count() << "s\n";    // Ausgabe: 121s
    milliseconds myMillis = mySecs;          // automatisch umgewandelt
    std::cout << myMillis.count() << "ms\n"; // Ausgabe: 121000ms
    nanoseconds myNanos = mySecs;
    std::cout << myNanos.count() << "ns\n"; // Ausgabe: 121000000000ns
    minutes myMinutesErr = mySecs;          //                     (ERR)  Fehler: Konvertierung mit Verlust
    minutes myMinutes = duration_cast<minutes>(mySecs); // explizit geht's
    std::cout<<myMinutes.count()<<"min\n";  // Ausgabe: 2min
}

Godbolt Listing lst-0936-godb.cpp, https://godbolt.org/z/qrs63vdz1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qrs63vdz1 
#include <chrono>
#include <iostream>
int main() {
    using namespace std::chrono;             // Suffixe erlauben
    seconds mySecs = 121s;                   // seconds{121}
    std::cout << mySecs.count() << "s\n";    // Ausgabe: 121s
    milliseconds myMillis = mySecs;          // automatisch umgewandelt
    std::cout << myMillis.count() << "ms\n"; // Ausgabe: 121000ms
    nanoseconds myNanos = mySecs;
    std::cout << myNanos.count() << "ns\n"; // Ausgabe: 121000000000ns
    minutes myMinutesErr = mySecs;          //                     (ERR)  Fehler: Konvertierung mit Verlust
    minutes myMinutes = duration_cast<minutes>(mySecs); // explizit geht's
    std::cout<<myMinutes.count()<<"min\n";  // Ausgabe: 2min
}

Listing 28.26: Sie können Einheiten mischen.

Book listing lst-0937-book.cpp:

// https://godbolt.org/z/vTx4cdqzq 
#include <chrono>
#include <iostream>
void showDuration(std::chrono::milliseconds dur) {
    std::cout << dur.count() << "ms\n";
}
int main() {
    using namespace std::chrono;
    auto x = 2s;
    auto y = 3ms;
    showDuration(x + y); // Ausgabe: 2003ms
    showDuration(x - y); // Ausgabe: 1997ms
}

Godbolt Listing lst-0937-godb.cpp, https://godbolt.org/z/vTx4cdqzq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vTx4cdqzq 
#include <chrono>
#include <iostream>
void showDuration(std::chrono::milliseconds dur) {
    std::cout << dur.count() << "ms\n";
}
int main() {
    using namespace std::chrono;
    auto x = 2s;
    auto y = 3ms;
    showDuration(x + y); // Ausgabe: 2003ms
    showDuration(x - y); // Ausgabe: 1997ms
}

Listing 28.27: Erstellen Sie neue Zeiteinheiten oder sparsamere Repräsentationen.

Book listing lst-0938-book.cpp:

// https://godbolt.org/z/5Wd1rKrMe 
#include <chrono>
#include <iostream>
using namespace std::chrono; using std::cout;
using seconds32 = duration<int32_t>;                // andere Repräsentation
using zehntag = duration<int,std::ratio<86400*10>>; // andere Zeiteinheit
using fseconds = duration<double>;                  // Fließkommarepräsentation
int main() {
  seconds32 s{5};
  cout << milliseconds(s).count() << "ms\n";
  zehntag z{1};
  hours h = z;                 // Umwandlung kostenlos
  cout << "1 Zehntag hat "<<h.count()<<" Stunden\n";              // …240…
  fseconds fs{23.75};
  cout << fs.count() << "s\n"; // Fließkommaausgabe
  auto printDur = [](fseconds f) { cout << f.count() << "s\n"; }; // Funktion
  printDur(45ms + 63us);       // Umwandlung in fseconds
  // Ausgabe: 0.045063s
}

Godbolt Listing lst-0938-godb.cpp, https://godbolt.org/z/5Wd1rKrMe:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/5Wd1rKrMe 
#include <chrono>
#include <iostream>
using namespace std::chrono; using std::cout;
using seconds32 = duration<int32_t>;                // andere Repräsentation
using zehntag = duration<int,std::ratio<86400*10>>; // andere Zeiteinheit
using fseconds = duration<double>;                  // Fließkommarepräsentation
int main() {
  seconds32 s{5};
  cout << milliseconds(s).count() << "ms\n";
  zehntag z{1};
  hours h = z;                 // Umwandlung kostenlos
  cout << "1 Zehntag hat "<<h.count()<<" Stunden\n";              // …240…
  fseconds fs{23.75};
  cout << fs.count() << "s\n"; // Fließkommaausgabe
  auto printDur = [](fseconds f) { cout << f.count() << "s\n"; }; // Funktion
  printDur(45ms + 63us);       // Umwandlung in fseconds
  // Ausgabe: 0.045063s
}

GodboltId:Gvz4crW75

Book listing lst-0939-book.cpp:

// https://godbolt.org/z/Gvz4crW75 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    year y{2021};
    std::cout << y << "\n";
    month m{October};
    auto result = m + months{3};   // 'months', nicht 'month': 3 Monate später
    std::cout << result << "\n";   // übergelaufen zu Januar
    weekday wd{Thursday};
    auto result = wd + days{4};    // 'days', nicht 'day': 4 Tage später
    std::cout << result << "\n";   // übergelaufen zu Montag
    weekday sun1{0};               // 0 ist Sonntag
    weekday sun2{7};               // 7 ist auch Sonntag
    std::cout << sun1 << "\t" << sun2 << "\n";
    weekday_indexed wdi{wd, 4};    // unbestimmter 4. Donnerstag
    std::cout << wdi << "\n";      // Ausgabe: Thu[4] — so gibt chrono 
                                   // unbestimmte Werte aus
}

Godbolt Listing lst-0939-godb.cpp, https://godbolt.org/z/Gvz4crW75:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gvz4crW75 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    year y{2021};
    std::cout << y << "\n";
    month m{October};
    auto result = m + months{3};   // 'months', nicht 'month': 3 Monate später
    std::cout << result << "\n";   // übergelaufen zu Januar
    weekday wd{Thursday};
    auto result = wd + days{4};    // 'days', nicht 'day': 4 Tage später
    std::cout << result << "\n";   // übergelaufen zu Montag
    weekday sun1{0};               // 0 ist Sonntag
    weekday sun2{7};               // 7 ist auch Sonntag
    std::cout << sun1 << "\t" << sun2 << "\n";
    weekday_indexed wdi{wd, 4};    // unbestimmter 4. Donnerstag
    std::cout << wdi << "\n";      // Ausgabe: Thu[4] — so gibt chrono 
                                   // unbestimmte Werte aus
}

GodboltId:oaKbd9bd4

Book listing lst-0940-book.cpp:

// https://godbolt.org/z/oaKbd9bd4 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
  year this_year{2021};
  year last_year{2020};
  year_month_day ymd{this_year, October, day{28}};
  std::cout << ymd << "\n";
  month_weekday mwd{November, Thursday[4]};  // in einem unbestimmten Jahr
  std::cout << mwd << "\n";                  // Ausgabe: Nov/Thu[4]
  month_day_last mdlast{February};      // letzter Tag eines unbestimmten Februars
  year_month_day_last leap{last_year, mdlast};         // Jahr hinzufügen
  year_month_day_last noleap{this_year, mdlast};       // Jahr hinzufügen
  std::cout << leap << "\t" << leap.day() << "\n";     // Ausgabe: 2020-02-29 29
  std::cout << noleap << "\t" << noleap.day() << "\n"; // Ausgabe: 2021-02-28 28
}

Godbolt Listing lst-0940-godb.cpp, https://godbolt.org/z/oaKbd9bd4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/oaKbd9bd4 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
  year this_year{2021};
  year last_year{2020};
  year_month_day ymd{this_year, October, day{28}};
  std::cout << ymd << "\n";
  month_weekday mwd{November, Thursday[4]};  // in einem unbestimmten Jahr
  std::cout << mwd << "\n";                  // Ausgabe: Nov/Thu[4]
  month_day_last mdlast{February};      // letzter Tag eines unbestimmten Februars
  year_month_day_last leap{last_year, mdlast};         // Jahr hinzufügen
  year_month_day_last noleap{this_year, mdlast};       // Jahr hinzufügen
  std::cout << leap << "\t" << leap.day() << "\n";     // Ausgabe: 2020-02-29 29
  std::cout << noleap << "\t" << noleap.day() << "\n"; // Ausgabe: 2021-02-28 28
}

GodboltId:4s69W7qd3

Book listing lst-0942-book.cpp:

// https://godbolt.org/z/4s69W7qd3 
auto a_date = 2024y/11/14d;
auto b_date = 2024y/11/14;
auto c_date = 14d/11/2024;
auto d_date = November/14/2024;

Godbolt Listing lst-0942-godb.cpp, https://godbolt.org/z/4s69W7qd3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4s69W7qd3 
auto a_date = 2024y/11/14d;
auto b_date = 2024y/11/14;
auto c_date = 14d/11/2024;
auto d_date = November/14/2024;

Listing 28.28: Ausgabe von Datum und Zeit mit format

Book listing lst-0944-book.cpp:

// https://godbolt.org/z/Md38b9zvf 
#include <chrono>
#include <iostream>
#include <format>
using namespace std::chrono;
int main() {
  auto ymd = last/February/2024;   // letzter Tag im Februar 2024: 29.2.2024
  std::cout << ymd << "\n";        // die Ausgabe mit << ist einfach
  std::cout << std::format("{:%Y-%m-%d}\n", ymd);  // format ist flexibler
  std::cout << std::format("{:%e. %B %y}\n", ymd); // viel flexibler!
}

Godbolt Listing lst-0944-godb.cpp, https://godbolt.org/z/Md38b9zvf:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Md38b9zvf 
#include <chrono>
#include <iostream>
#include <format>
using namespace std::chrono;
int main() {
  auto ymd = last/February/2024;   // letzter Tag im Februar 2024: 29.2.2024
  std::cout << ymd << "\n";        // die Ausgabe mit << ist einfach
  std::cout << std::format("{:%Y-%m-%d}\n", ymd);  // format ist flexibler
  std::cout << std::format("{:%e. %B %y}\n", ymd); // viel flexibler!
}

Listing 28.29: Immer der zweite Dienstag eines Monats

Book listing lst-0945-book.cpp:

// https://godbolt.org/z/19vf9jfTM 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    for (int mo = 1; mo <= 12; ++mo) {
        year_month_weekday patch_tues{mo/Tuesday[2]/2024y};
        year_month_day ymd{sys_days{patch_tues}};
        std::cout << ymd.month() << " " << ymd.day() << "\n";
    }
}

Godbolt Listing lst-0945-godb.cpp, https://godbolt.org/z/19vf9jfTM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/19vf9jfTM 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    for (int mo = 1; mo <= 12; ++mo) {
        year_month_weekday patch_tues{mo/Tuesday[2]/2024y};
        year_month_day ymd{sys_days{patch_tues}};
        std::cout << ymd.month() << " " << ymd.day() << "\n";
    }
}

Listing 28.30: Umwandlung in eine zeitzonenbehaftete Zeit und die Ausnahmen

Book listing lst-0947-book.cpp:

// https://godbolt.org/z/hP7nhEW69 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
  auto fruehl = local_days{31d/March/2024} + 2h + 1min;
  try {
      auto zt = zoned_time{"Europe/Berlin", fruehl};
  } catch (const nonexistent_local_time& e) {
      std::cout << e.what() << '\n'; // Ausnahme geworfen: existiert nicht
  }
  auto herbst = local_days{27d/October/2024} + 2h + 1min;
  try {
      auto zt = zoned_time{"Europe/Berlin", herbst};
  } catch (const ambiguous_local_time& e) {
     std::cout << e.what() << '\n'; // Ausnahme geworfen: existiert doppelt
  }
  std::cout << zoned_time{"Europe/Berlin", herbst, choose::earliest} << '\n';
  // Ausgabe: 2024-10-27 02:01:00 CEST
  std::cout << zoned_time{"Europe/Berlin", herbst, choose::latest} << '\n';
  // Ausgabe: 2024-10-27 02:01:00 CET
}

Godbolt Listing lst-0947-godb.cpp, https://godbolt.org/z/hP7nhEW69:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hP7nhEW69 
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
  auto fruehl = local_days{31d/March/2024} + 2h + 1min;
  try {
      auto zt = zoned_time{"Europe/Berlin", fruehl};
  } catch (const nonexistent_local_time& e) {
      std::cout << e.what() << '\n'; // Ausnahme geworfen: existiert nicht
  }
  auto herbst = local_days{27d/October/2024} + 2h + 1min;
  try {
      auto zt = zoned_time{"Europe/Berlin", herbst};
  } catch (const ambiguous_local_time& e) {
     std::cout << e.what() << '\n'; // Ausnahme geworfen: existiert doppelt
  }
  std::cout << zoned_time{"Europe/Berlin", herbst, choose::earliest} << '\n';
  // Ausgabe: 2024-10-27 02:01:00 CEST
  std::cout << zoned_time{"Europe/Berlin", herbst, choose::latest} << '\n';
  // Ausgabe: 2024-10-27 02:01:00 CET
}

Listing 28.31: Die Zeitzonendatenbank

Book listing lst-0948-book.cpp:

// https://godbolt.org/z/YTKK3vT7s 
#include <chrono>
#include <iostream>
#include <ranges> // views::transform, views::filter
#include <algorithm> // ranges::for_each
using namespace std; namespace c = std::chrono;
namespace v = std::views; namespace r = std::ranges;
int main() {
  auto show_name = [](const string_view name) { cout << name << ' '; };
  const auto& db = c::get_tzdb();
  auto names = db.zones
   | v::transform([](const c::time_zone& z) {return z.name();})
   | v::filter([](const string_view name) {
       return name.starts_with("Europe/Be");});
  r::for_each(names, show_name);
  cout << " <- Europe/Be*\n"; // Ausgabe: Europe/Belgrade Europe/Berlin
  r::for_each(
   db.links
   | v::filter([](const c::time_zone_link& l){
       return l.target()=="Europe/Berlin";})
   | v::transform([](const c::time_zone_link& l)->string_view {
       return l.name();})
   , show_name);
  cout << " <- Links nach Europe/Berlin\n"; // Ausgabe: Arctic/Longyearbyen …
}

Godbolt Listing lst-0948-godb.cpp, https://godbolt.org/z/YTKK3vT7s:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YTKK3vT7s 
#include <chrono>
#include <iostream>
#include <ranges> // views::transform, views::filter
#include <algorithm> // ranges::for_each
using namespace std; namespace c = std::chrono;
namespace v = std::views; namespace r = std::ranges;
int main() {
  auto show_name = [](const string_view name) { cout << name << ' '; };
  const auto& db = c::get_tzdb();
  auto names = db.zones
   | v::transform([](const c::time_zone& z) {return z.name();})
   | v::filter([](const string_view name) {
       return name.starts_with("Europe/Be");});
  r::for_each(names, show_name);
  cout << " <- Europe/Be*\n"; // Ausgabe: Europe/Belgrade Europe/Berlin
  r::for_each(
   db.links
   | v::filter([](const c::time_zone_link& l){
       return l.target()=="Europe/Berlin";})
   | v::transform([](const c::time_zone_link& l)->string_view {
       return l.name();})
   , show_name);
  cout << " <- Links nach Europe/Berlin\n"; // Ausgabe: Arctic/Longyearbyen …
}

GodboltId:YsjvxTKGj

Book listing lst-0949-book.cpp:

// https://godbolt.org/z/YsjvxTKGj 
#include <iostream>
#include <ratio>
using std::cout; using std::endl;
int main() {
  using einDrittel = std::ratio<1,3>;
  using zweiViertel = std::ratio<2,4>;
  cout << einDrittel::num << "/" << einDrittel::den << endl;   // Ausgabe: 1/3
  cout << zweiViertel::num << "/" << zweiViertel::den << endl; // Ausgabe: 1/2
  using sum = std::ratio_add<einDrittel,zweiViertel>;          // addieren
  cout << sum::num << "/" << sum::den;                         // Ausgabe: 5/6
}

Godbolt Listing lst-0949-godb.cpp, https://godbolt.org/z/YsjvxTKGj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YsjvxTKGj 
#include <iostream>
#include <ratio>
using std::cout; using std::endl;
int main() {
  using einDrittel = std::ratio<1,3>;
  using zweiViertel = std::ratio<2,4>;
  cout << einDrittel::num << "/" << einDrittel::den << endl;   // Ausgabe: 1/3
  cout << zweiViertel::num << "/" << zweiViertel::den << endl; // Ausgabe: 1/2
  using sum = std::ratio_add<einDrittel,zweiViertel>;          // addieren
  cout << sum::num << "/" << sum::den;                         // Ausgabe: 5/6
}

GodboltId:q1znGWb85

Book listing lst-0954-book.cpp:

// https://godbolt.org/z/q1znGWb85 
#include <iostream>
#include <chrono>
int main() {
    using namespace std::chrono;
    time_point<system_clock, seconds> t1{10000s};
    time_point<system_clock, seconds> t2{50000s};
    auto dur = t2 - t1;
    std::cout << duration_cast<hours>(dur).count() << "h"; // Ausgabe: 11h
}

Godbolt Listing lst-0954-godb.cpp, https://godbolt.org/z/q1znGWb85:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/q1znGWb85 
#include <iostream>
#include <chrono>
int main() {
    using namespace std::chrono;
    time_point<system_clock, seconds> t1{10000s};
    time_point<system_clock, seconds> t2{50000s};
    auto dur = t2 - t1;
    std::cout << duration_cast<hours>(dur).count() << "h"; // Ausgabe: 11h
}

Listing 28.32: Einfache Zeitmessung eines Funktionsaufrufs

Book listing lst-0958-book.cpp:

// https://godbolt.org/z/8hxd9bPb4 
#include <iostream>
#include <chrono>
long fib(long n) { return n<2L ? 1L : fib(n-1L)+fib(n-2L); }
int main() {
    using namespace std::chrono;
    auto t0 = steady_clock::now();  // Auf die Plätze, fertig …
    auto res = fib(17);             // … los!
    auto t1 = steady_clock::now();  // Stopp!
    std::cout << "Ergebnis: " << res << "\n"; // Ausgabe: Ergebnis: 2584
    std::cout << "Zeit: " << nanoseconds{t1-t0}.count() << "ns\n";
    // Ausgabe: Zeit: 50727ns (z. B.)
}

Godbolt Listing lst-0958-godb.cpp, https://godbolt.org/z/8hxd9bPb4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8hxd9bPb4 
#include <iostream>
#include <chrono>
long fib(long n) { return n<2L ? 1L : fib(n-1L)+fib(n-2L); }
int main() {
    using namespace std::chrono;
    auto t0 = steady_clock::now();  // Auf die Plätze, fertig …
    auto res = fib(17);             // … los!
    auto t1 = steady_clock::now();  // Stopp!
    std::cout << "Ergebnis: " << res << "\n"; // Ausgabe: Ergebnis: 2584
    std::cout << "Zeit: " << nanoseconds{t1-t0}.count() << "ns\n";
    // Ausgabe: Zeit: 50727ns (z. B.)
}

GodboltId:rz38hc1cx

Book listing lst-0959-book.cpp:

// https://godbolt.org/z/rz38hc1cx 
auto res = fib(45);
// …
std::cout << "Zeit: " << duration_cast<seconds>(t1-t0).count() << "s\n";
// Ausgabe: Zeit: 7s (z. B.)
std::cout << "Zeit: " << duration<double>{t1-t0}.count() << "s\n";
// Ausgabe: Zeit: 7.35303s (z. B.)
}

Godbolt Listing lst-0959-godb.cpp, https://godbolt.org/z/rz38hc1cx:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rz38hc1cx 
auto res = fib(45);
// …
std::cout << "Zeit: " << duration_cast<seconds>(t1-t0).count() << "s\n";
// Ausgabe: Zeit: 7s (z. B.)
std::cout << "Zeit: " << duration<double>{t1-t0}.count() << "s\n";
// Ausgabe: Zeit: 7.35303s (z. B.)
}

GodboltId:1xbhhTdEv

Book listing lst-0960-book.cpp:

// https://godbolt.org/z/1xbhhTdEv 
#include <iostream>
#include <chrono>
int main() {
    using namespace std::chrono;
    auto tp = time_point_cast<seconds>(system_clock::now());
    auto d = tp.time_since_epoch();
    std::cout << d.count() << "s\n";
    std::cout << duration<double,std::ratio<86400>>{d}.count() << "days\n";
}

Godbolt Listing lst-0960-godb.cpp, https://godbolt.org/z/1xbhhTdEv:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xbhhTdEv 
#include <iostream>
#include <chrono>
int main() {
    using namespace std::chrono;
    auto tp = time_point_cast<seconds>(system_clock::now());
    auto d = tp.time_since_epoch();
    std::cout << d.count() << "s\n";
    std::cout << duration<double,std::ratio<86400>>{d}.count() << "days\n";
}

GodboltId:o359TThMj

Book listing lst-0961-book.cpp:

// https://godbolt.org/z/o359TThMj 
#include <iostream>
#include <string>
#include <chrono>
#include <complex>
using std::cout;
int main() {
    { using namespace std;
      cout << "string"s << "\n";           // string
      cout << (1.2+3.4i) << "\n";          // complex
      }
    { using namespace std::chrono;
      cout << (35ms).count() << "ms\n";    // chrono
      }
    { using namespace std::literals;
      cout << (41s).count() << "ms\n";     // chrono seconds
      cout << "text"s << "\n";             // string
    }
    { using namespace std::chrono; 
      cout << (4h).count() << "h\n";       // chrono hours
    }
    { using namespace std::literals::chrono_literals; 
      cout << (16min).count() << "min\n";  // chrono minutes
    }
    { using std::literals::string_literals::operator""s; 
      cout << "buchstaben"s << "\n";        // string
    }
}

Godbolt Listing lst-0961-godb.cpp, https://godbolt.org/z/o359TThMj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/o359TThMj 
#include <iostream>
#include <string>
#include <chrono>
#include <complex>
using std::cout;
int main() {
    { using namespace std;
      cout << "string"s << "\n";           // string
      cout << (1.2+3.4i) << "\n";          // complex
      }
    { using namespace std::chrono;
      cout << (35ms).count() << "ms\n";    // chrono
      }
    { using namespace std::literals;
      cout << (41s).count() << "ms\n";     // chrono seconds
      cout << "text"s << "\n";             // string
    }
    { using namespace std::chrono; 
      cout << (4h).count() << "h\n";       // chrono hours
    }
    { using namespace std::literals::chrono_literals; 
      cout << (16min).count() << "min\n";  // chrono minutes
    }
    { using std::literals::string_literals::operator""s; 
      cout << "buchstaben"s << "\n";        // string
    }
}

Listing 28.34: Sehr einfaches Beispiel dafür, wie man den Erfolg einer Operation prüfen kann

Book listing lst-0962-book.cpp:

// https://godbolt.org/z/1xnY8vd8Y 
#include <system_error> // error_code
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
  std::error_code ec;
  create_dir("/some/path", ec);
  if(!ec) {  // Erfolg …
  } else {   // Misserfolg …
  }
}

Godbolt Listing lst-0962-godb.cpp, https://godbolt.org/z/1xnY8vd8Y:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1xnY8vd8Y 
#include <system_error> // error_code
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
  std::error_code ec;
  create_dir("/some/path", ec);
  if(!ec) {  // Erfolg …
  } else {   // Misserfolg …
  }
}

Listing 28.35: Vergleich von »error_code« mit »error_condition«

Book listing lst-0963-book.cpp:

// https://godbolt.org/z/TPWc5nexq 
#include <system_error> // error_code, errc
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
  std::error_code ec;
  create_dir("/some/path", ec);
  if(ec == std::errc::file_exists) {   // speziell …
  } else if(!ec) {                     // Erfolg …
  } else {                             // Misserfolg …
  }
}

Godbolt Listing lst-0963-godb.cpp, https://godbolt.org/z/TPWc5nexq:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TPWc5nexq 
#include <system_error> // error_code, errc
#include <string>
void create_dir(const std::string& pathname, std::error_code& ec);
void run() {
  std::error_code ec;
  create_dir("/some/path", ec);
  if(ec == std::errc::file_exists) {   // speziell …
  } else if(!ec) {                     // Erfolg …
  } else {                             // Misserfolg …
  }
}

Listing 28.36: Überladungen von »operator==()« (abgekürzt)

Book listing lst-0964-book.cpp:

bool operator==
   (const error_code&    lhs, const error_code&      rhs) noexcept;
(const error_code&      lhs, const error_condition& rhs) noexcept;
(const error_condition& lhs, const error_code&      rhs) noexcept;
(const error_condition& lhs, const error_condition& rhs) noexcept;

Listing 28.37: Definition von »enum class errc«

Book listing lst-0965-book.cpp:

enum class errc {
  address_family_not_supported,
  address_in_use,
  // ...
  value_too_large,
  wrong_protocol_type,
};

Listing 28.38: Spezialisierung von »is_error_condition_enum« für »errc«

Book listing lst-0966-book.cpp:

template <>
struct is_error_condition_enum<errc> : true_type {};

Listing 28.39: Unter den Überladungen von make_error_condition ist auch eine mit »errc«.

Book listing lst-0967-book.cpp:

error_condition make_error_condition(errc c) noexcept {
  return error_condition(
      static_cast<int>(e),
      generic_category());
}
error_condition make_error_condition(io_errc c) noexcept /*...*/
error_condition make_error_condition(future_errc c) noexcept /*...*/

Listing 28.40: Erzeugung systemspezifischer Fehlercodes in einem portablen Programm

Book listing lst-0968-book.cpp:

// https://godbolt.org/z/n4v78WWod 
#include <system_error>
#include <string>

void create_dir(const std::string& pathname, std::error_code& ec) {
#if defined(_WIN32)
  // Windows-Implementierung, mit Windows-Fehlercodes
#elif defined(linux)
  // Linux-Implementierung, mit Linux-Fehlercodes
#else
  // allgemeingültiger 'generischer' Fall
  ec = std::make_error_code(std::errc::not_supported);
#endif
}

Godbolt Listing lst-0968-godb.cpp, https://godbolt.org/z/n4v78WWod:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n4v78WWod 
#include <system_error>
#include <string>

void create_dir(const std::string& pathname, std::error_code& ec) {
#if defined(_WIN32)
  // Windows-Implementierung, mit Windows-Fehlercodes
#elif defined(linux)
  // Linux-Implementierung, mit Linux-Fehlercodes
#else
  // allgemeingültiger 'generischer' Fall
  ec = std::make_error_code(std::errc::not_supported);
#endif
}

GodboltId:vxTxT4ajW

Book listing lst-0969-book.cpp:

// https://godbolt.org/z/vxTxT4ajW 
#include <system_error>
#include <iostream>
using std::error_code; using std::system_category;
namespace mylib {
    // eigene Errorcodes
    enum class errc { LOAD_ERR = 1, UNLOAD_ERR = 2, OTHER_ERR = 3 };
    error_code make_error_code(errc ec) {
        switch(ec) {
        case errc::LOAD_ERR: return error_code((int)ec, system_category());
        case errc::UNLOAD_ERR: return error_code((int)ec, system_category());
        case errc::OTHER_ERR: return error_code((int)ec, system_category());
        }
    }
    error_code run(int arg) {
        if(arg == 667) {
            return make_error_code(errc::OTHER_ERR);
        }
        return error_code{}; // alles gut.
    }
}
int main() {
    std::error_code ec = mylib::run(667);
    if(!ec) {
        std::cout << "Klasse, klappt!\n";
    } else if (ec == mylib::make_error_code(mylib::errc::OTHER_ERR)) {
        std::cout << "Anderer Fehler\n";
    } else {
        std::cout << "Nix los hier\n" << ec;
    }
}

Godbolt Listing lst-0969-godb.cpp, https://godbolt.org/z/vxTxT4ajW:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/vxTxT4ajW 
#include <system_error>
#include <iostream>
using std::error_code; using std::system_category;
namespace mylib {
    // eigene Errorcodes
    enum class errc { LOAD_ERR = 1, UNLOAD_ERR = 2, OTHER_ERR = 3 };
    error_code make_error_code(errc ec) {
        switch(ec) {
        case errc::LOAD_ERR: return error_code((int)ec, system_category());
        case errc::UNLOAD_ERR: return error_code((int)ec, system_category());
        case errc::OTHER_ERR: return error_code((int)ec, system_category());
        }
    }
    error_code run(int arg) {
        if(arg == 667) {
            return make_error_code(errc::OTHER_ERR);
        }
        return error_code{}; // alles gut.
    }
}
int main() {
    std::error_code ec = mylib::run(667);
    if(!ec) {
        std::cout << "Klasse, klappt!\n";
    } else if (ec == mylib::make_error_code(mylib::errc::OTHER_ERR)) {
        std::cout << "Anderer Fehler\n";
    } else {
        std::cout << "Nix los hier\n" << ec;
    }
}

GodboltId:a8zP84j1x

Book listing lst-0971-book.cpp:

// https://godbolt.org/z/a8zP84j1x 
#include <thread>
#include <iostream>
#include <system_error>
int main() {
    try {
        std::thread().detach(); // das wird fehlschlagen
    } catch(std::system_error& e) {
        std::cout
            << "system_error mit Code:" << e.code()
            << " Meldung:" << e.what()
            << '\n';
    }
}

Godbolt Listing lst-0971-godb.cpp, https://godbolt.org/z/a8zP84j1x:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a8zP84j1x 
#include <thread>
#include <iostream>
#include <system_error>
int main() {
    try {
        std::thread().detach(); // das wird fehlschlagen
    } catch(std::system_error& e) {
        std::cout
            << "system_error mit Code:" << e.code()
            << " Meldung:" << e.what()
            << '\n';
    }
}

GodboltId:cjh93oPcr

Book listing lst-0972-book.cpp:

// https://godbolt.org/z/cjh93oPcr 
#include <iostream>
#include <system_error> // std::make_error_condition, std::ios_errc
int main () {
  // umschalten auf Exceptions:
  std::cin.exceptions (std::ios::failbit|std::ios::badbit);
  try {
    std::cin.rdbuf(nullptr);       // löst eine Exception aus
  } catch (std::ios::failure& e) { // abgeleitet von system_error
    std::cerr << "Fehler: ";
    if (e.code() == std::make_error_condition(std::io_errc::stream)) {
      std::cerr << "stream\n";
    } else {
      std::cerr << "andere\n";
    }
  }
}

Godbolt Listing lst-0972-godb.cpp, https://godbolt.org/z/cjh93oPcr:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/cjh93oPcr 
#include <iostream>
#include <system_error> // std::make_error_condition, std::ios_errc
int main () {
  // umschalten auf Exceptions:
  std::cin.exceptions (std::ios::failbit|std::ios::badbit);
  try {
    std::cin.rdbuf(nullptr);       // löst eine Exception aus
  } catch (std::ios::failure& e) { // abgeleitet von system_error
    std::cerr << "Fehler: ";
    if (e.code() == std::make_error_condition(std::io_errc::stream)) {
      std::cerr << "stream\n";
    } else {
      std::cerr << "andere\n";
    }
  }
}

Listing 28.41: Nutzen Sie »typeindex« für verlässliche Typinformationen.

Book listing lst-0973-book.cpp:

// https://godbolt.org/z/x1dq1Wof6 
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>
struct Base {
    virtual ~Base() {}
};
struct Derived_One : public Base {};
struct Derived_Two : public Base {};
int main() {
  using std::string; using std::cout; using std::type_index;
  std::map<std::type_index, string> namen {
      { type_index(typeid(int)), "int" },
      { type_index(typeid(double)), "double" },
      { type_index(typeid(Base)), "Base" },
      { type_index(typeid(Derived_One)), "Derived_One" },
      { type_index(typeid(Derived_Two)), "Derived_Two" },
      { type_index(typeid(string)), "string" },
      { type_index(typeid(string::const_iterator)), "string" },
  };
  namen[type_index(typeid(namen))] = "namen-map";
  int ganz;
  double fliessend;
  Base base{};
  Base *one = new Derived_One{};
  Base *two = new Derived_Two{};
  // typeid.name() ist implementierungs- und laufzeitabhängig:
  cout << typeid(ganz).name() << '\n';      // Bei mir: i
  cout << typeid(fliessend).name() << '\n'; // Bei mir: d
  cout << typeid(base).name() << '\n';      // Bei mir: 4Base
  cout << typeid(*one).name() << '\n';      // Bei mir: 11Derived_One
  cout << typeid(*two).name() << '\n';      // Bei mir: 11Derived_Two
  cout << typeid(string).name() << '\n';    // Bei mir: Ss
  cout << typeid(string{"Welt"}.begin()).name() << '\n';
      // Bei mir: N9__gnu_cxx17__normal_iteratorIPcSsEE
  cout << typeid(namen).name() << '\n';
      // Bei mir: St3mapISt10type_indexSsSt4lessIS0_ESaISt4pairIKS0_SsEEE
  cout << typeid(666/0).name() << '\n'; // Ausdruck wird nicht ausgeführt! Bei mir: i
  // type_index macht type_infos vergleichbar:
  cout << namen[type_index(typeid(ganz))] << '\n';      // Ausgabe: int
  cout << namen[type_index(typeid(fliessend))] << '\n'; // Ausgabe: double
  cout << namen[type_index(typeid(base))] << '\n';      // Ausgabe: Base
  cout << namen[type_index(typeid(*one))] << '\n';      // Ausgabe: Derived_One
  cout << namen[type_index(typeid(*two))] << '\n';      // Ausgabe: Derived_Two
  cout << namen[type_index(typeid(string))] << '\n';    // Ausgabe: string
  cout << namen[type_index(typeid(namen))] << '\n';     // Ausgabe: namen-map
}

Godbolt Listing lst-0973-godb.cpp, https://godbolt.org/z/x1dq1Wof6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/x1dq1Wof6 
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>
struct Base {
    virtual ~Base() {}
};
struct Derived_One : public Base {};
struct Derived_Two : public Base {};
int main() {
  using std::string; using std::cout; using std::type_index;
  std::map<std::type_index, string> namen {
      { type_index(typeid(int)), "int" },
      { type_index(typeid(double)), "double" },
      { type_index(typeid(Base)), "Base" },
      { type_index(typeid(Derived_One)), "Derived_One" },
      { type_index(typeid(Derived_Two)), "Derived_Two" },
      { type_index(typeid(string)), "string" },
      { type_index(typeid(string::const_iterator)), "string" },
  };
  namen[type_index(typeid(namen))] = "namen-map";
  int ganz;
  double fliessend;
  Base base{};
  Base *one = new Derived_One{};
  Base *two = new Derived_Two{};
  // typeid.name() ist implementierungs- und laufzeitabhängig:
  cout << typeid(ganz).name() << '\n';      // Bei mir: i
  cout << typeid(fliessend).name() << '\n'; // Bei mir: d
  cout << typeid(base).name() << '\n';      // Bei mir: 4Base
  cout << typeid(*one).name() << '\n';      // Bei mir: 11Derived_One
  cout << typeid(*two).name() << '\n';      // Bei mir: 11Derived_Two
  cout << typeid(string).name() << '\n';    // Bei mir: Ss
  cout << typeid(string{"Welt"}.begin()).name() << '\n';
      // Bei mir: N9__gnu_cxx17__normal_iteratorIPcSsEE
  cout << typeid(namen).name() << '\n';
      // Bei mir: St3mapISt10type_indexSsSt4lessIS0_ESaISt4pairIKS0_SsEEE
  cout << typeid(666/0).name() << '\n'; // Ausdruck wird nicht ausgeführt! Bei mir: i
  // type_index macht type_infos vergleichbar:
  cout << namen[type_index(typeid(ganz))] << '\n';      // Ausgabe: int
  cout << namen[type_index(typeid(fliessend))] << '\n'; // Ausgabe: double
  cout << namen[type_index(typeid(base))] << '\n';      // Ausgabe: Base
  cout << namen[type_index(typeid(*one))] << '\n';      // Ausgabe: Derived_One
  cout << namen[type_index(typeid(*two))] << '\n';      // Ausgabe: Derived_Two
  cout << namen[type_index(typeid(string))] << '\n';    // Ausgabe: string
  cout << namen[type_index(typeid(namen))] << '\n';     // Ausgabe: namen-map
}

Listing 28.42: Boosts »demangled_name« ist für die Ausgabe von Typnamen extrem nützlich.

Book listing lst-0974-book.cpp:

// https://godbolt.org/z/n54566cqT 
#include <iostream>
#include <typeinfo>
#include <string>
#include <map>
#include <boost/core/typeinfo.hpp>
int main() {
  using std::string; using std::cout;
  std::map<int, string> namen;
  int ganz;
  double fliessend;
  // demangled_name
  using boost::core::demangled_name;
  cout<<demangled_name(BOOST_CORE_TYPEID(ganz))<<'\n';      // Ausgabe: int
  cout<<demangled_name(BOOST_CORE_TYPEID(fliessend))<<'\n'; // Ausgabe: double
  cout<<demangled_name(BOOST_CORE_TYPEID(string))<<'\n';  // Ausgabe: std::string
  cout<<demangled_name(BOOST_CORE_TYPEID(string{}.begin()))<<'\n';
  // Ausgabe: __gnu_cxx::__normal_iterator<char*, std::string>
  cout<<demangled_name(BOOST_CORE_TYPEID(namen))<<'\n';
  // Ausgabe: std::map<int, std::string, std::less<int>,
  //                                                         std::allocator<std::pair<int const, std::string> > >
  cout<<demangled_name(BOOST_CORE_TYPEID(666/0))<<'\n';  // Ausgabe: int
}

Godbolt Listing lst-0974-godb.cpp, https://godbolt.org/z/n54566cqT:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/n54566cqT 
#include <iostream>
#include <typeinfo>
#include <string>
#include <map>
#include <boost/core/typeinfo.hpp>
int main() {
  using std::string; using std::cout;
  std::map<int, string> namen;
  int ganz;
  double fliessend;
  // demangled_name
  using boost::core::demangled_name;
  cout<<demangled_name(BOOST_CORE_TYPEID(ganz))<<'\n';      // Ausgabe: int
  cout<<demangled_name(BOOST_CORE_TYPEID(fliessend))<<'\n'; // Ausgabe: double
  cout<<demangled_name(BOOST_CORE_TYPEID(string))<<'\n';  // Ausgabe: std::string
  cout<<demangled_name(BOOST_CORE_TYPEID(string{}.begin()))<<'\n';
  // Ausgabe: __gnu_cxx::__normal_iterator<char*, std::string>
  cout<<demangled_name(BOOST_CORE_TYPEID(namen))<<'\n';
  // Ausgabe: std::map<int, std::string, std::less<int>,
  //                                                         std::allocator<std::pair<int const, std::string> > >
  cout<<demangled_name(BOOST_CORE_TYPEID(666/0))<<'\n';  // Ausgabe: int
}

GodboltId:Y3GsPd97d

Book listing lst-0976-book.cpp:

// https://godbolt.org/z/Y3GsPd97d 
#include <set>
#include <string>
struct Drachen {
    std::string name_;
};
namespace std {
    template<> struct less<Drachen> { // Templatespezialisierung
        bool operator()(const Drachen &lhs, const Drachen &rhs) const {
            return lhs.name_ < rhs.name_;
} }; }
int main() {
  std::set<Drachen> drachen {
    Drachen{"Smaug"},Drachen{"Glaurung"},
        Drachen{"Ancalagon"},Drachen{"Scatha"}};
}

Godbolt Listing lst-0976-godb.cpp, https://godbolt.org/z/Y3GsPd97d:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y3GsPd97d 
#include <set>
#include <string>
struct Drachen {
    std::string name_;
};
namespace std {
    template<> struct less<Drachen> { // Templatespezialisierung
        bool operator()(const Drachen &lhs, const Drachen &rhs) const {
            return lhs.name_ < rhs.name_;
} }; }
int main() {
  std::set<Drachen> drachen {
    Drachen{"Smaug"},Drachen{"Glaurung"},
        Drachen{"Ancalagon"},Drachen{"Scatha"}};
}

Listing 28.43: Dieser Taschenrechner bildet Tasten auf Funktoren ab.

Book listing lst-0977-book.cpp:

// https://godbolt.org/z/j85P7b3oq 
#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <functional>
std::map<char,std::function<int(int,int)>> binOps { // zweistellige Operatoren
    {'+', std::plus<int>{} },
    {'-', std::minus<int>{} },
    {'*', std::multiplies<int>{} },
    {'/', std::divides<int>{} },
    {'%', std::modulus<int>{} },
    };
std::map<char,std::function<int(int)>> unOps { };    // einstellige Operatoren
auto val = [](auto n) { return [n](){ return n; };}; // gibt ein Lambda zurück
std::map<char,std::function<int()>> zeroOps {        // nullstellige Operatoren
  {'0', val(0)}, {'1', val(1)}, {'2', val(2)}, {'3', val(3)}, {'4', val(4)},
  {'5', val(5)}, {'6', val(6)}, {'7', val(7)}, {'8', val(8)}, {'9', val(9)},
  };
std::map<char,std::function<void(std::vector<int>&)>> stapelOps { 
  { ' ', [](auto &stapel) { } },           // keine Operation
  { 'c', [](auto &stapel) { stapel.clear(); } }, // Stapel ganz löschen
  { ':', [](auto &stapel) {                // obersten zwei Elemente vertauschen
            auto top = stapel.back(); stapel.pop_back();
            auto second = stapel.back(); stapel.pop_back();
            stapel.push_back(top);
            stapel.push_back(second);
  } },
  { '=', [](auto &stapel) {                // ganzen Stapel ausgeben
            for(int elem : stapel) { std::cout << elem; }
            std::cout << "\n";
  } },
};
void rechner(std::string input) {
  std::vector<int> stapel {};
  for(char c : input) {
    int top, second;
    if(auto it = unOps.find(c); it != unOps.end()) {
      // falls einstelliger Operator …
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); // … hole oberstes Element
      stapel.push_back(func(top));         // … wende func an, Ergebnis auf Stapel
    } else if(auto it = binOps.find(c); it != binOps.end()) {
      // falls zweistelliger Operator …
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); // … hole die obersten 2 Elemente
      second = stapel.back(); stapel.pop_back();
      stapel.push_back(func(second, top)); // … wende func an, Ergebnis auf Stapel
    } else if(auto it = zeroOps.find(c); it !=zeroOps.end()) {
      // falls nullstelliger Operator …
      auto func = it->second;
      stapel.push_back(func());            // … Ergebnis von func auf Stapel
    } else if(auto it = stapelOps.find(c); it !=stapelOps.end()) {
      // falls Stapeloperator
      auto func = it->second;
      func(stapel);                        // … wende func auf Stapel an
    } else {
      std::cout << "\n'" << c << "' verstehe ich nicht.\n";
    }
  } /* for c */
}
int main(int argc, const char* argv[]) {
    if(argc > 1) {
        rechner(argv[1]);
    } else {
        // 3+4*5+6 mit Punkt- vor Strichrechnung ergibt 29
        rechner("345*+6+=");
    }
    rechner("93-=");                     // 9 – 3 = Ausgabe: 6
    rechner("82/=");                     // 8 / 2 = Ausgabe: 4
    rechner("92%=");                     // 9 % 2 = Ausgabe: 1
}

Godbolt Listing lst-0977-godb.cpp, https://godbolt.org/z/j85P7b3oq:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/j85P7b3oq 
#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <functional>
std::map<char,std::function<int(int,int)>> binOps { // zweistellige Operatoren
    {'+', std::plus<int>{} },
    {'-', std::minus<int>{} },
    {'*', std::multiplies<int>{} },
    {'/', std::divides<int>{} },
    {'%', std::modulus<int>{} },
    };
std::map<char,std::function<int(int)>> unOps { };    // einstellige Operatoren
auto val = [](auto n) { return [n](){ return n; };}; // gibt ein Lambda zurück
std::map<char,std::function<int()>> zeroOps {        // nullstellige Operatoren
  {'0', val(0)}, {'1', val(1)}, {'2', val(2)}, {'3', val(3)}, {'4', val(4)},
  {'5', val(5)}, {'6', val(6)}, {'7', val(7)}, {'8', val(8)}, {'9', val(9)},
  };
std::map<char,std::function<void(std::vector<int>&)>> stapelOps { 
  { ' ', [](auto &stapel) { } },           // keine Operation
  { 'c', [](auto &stapel) { stapel.clear(); } }, // Stapel ganz löschen
  { ':', [](auto &stapel) {                // obersten zwei Elemente vertauschen
            auto top = stapel.back(); stapel.pop_back();
            auto second = stapel.back(); stapel.pop_back();
            stapel.push_back(top);
            stapel.push_back(second);
  } },
  { '=', [](auto &stapel) {                // ganzen Stapel ausgeben
            for(int elem : stapel) { std::cout << elem; }
            std::cout << "\n";
  } },
};
void rechner(std::string input) {
  std::vector<int> stapel {};
  for(char c : input) {
    int top, second;
    if(auto it = unOps.find(c); it != unOps.end()) {
      // falls einstelliger Operator …
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); // … hole oberstes Element
      stapel.push_back(func(top));         // … wende func an, Ergebnis auf Stapel
    } else if(auto it = binOps.find(c); it != binOps.end()) {
      // falls zweistelliger Operator …
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); // … hole die obersten 2 Elemente
      second = stapel.back(); stapel.pop_back();
      stapel.push_back(func(second, top)); // … wende func an, Ergebnis auf Stapel
    } else if(auto it = zeroOps.find(c); it !=zeroOps.end()) {
      // falls nullstelliger Operator …
      auto func = it->second;
      stapel.push_back(func());            // … Ergebnis von func auf Stapel
    } else if(auto it = stapelOps.find(c); it !=stapelOps.end()) {
      // falls Stapeloperator
      auto func = it->second;
      func(stapel);                        // … wende func auf Stapel an
    } else {
      std::cout << "\n'" << c << "' verstehe ich nicht.\n";
    }
  } /* for c */
}
int main(int argc, const char* argv[]) {
    if(argc > 1) {
        rechner(argv[1]);
    } else {
        // 3+4*5+6 mit Punkt- vor Strichrechnung ergibt 29
        rechner("345*+6+=");
    }
    rechner("93-=");                     // 9 – 3 = Ausgabe: 6
    rechner("82/=");                     // 8 / 2 = Ausgabe: 4
    rechner("92%=");                     // 9 % 2 = Ausgabe: 1
}

GodboltId:e6xT638ch

Book listing lst-0978-book.cpp:

// https://godbolt.org/z/e6xT638ch 
#include <functional> // substract, minus, bind
#include <iostream>
using std::cout;
int substract(int a, int b) { return a - b; }
int main() {
    using namespace std::placeholders;
    cout << substract(9, 3) << '\n';  // Ausgabe: 6
    auto minus3 = std::bind(substract, _1, 3);
    cout << minus3(9) << '\n';        // Ausgabe: 6
    auto von9 = std::bind(substract, 9, _1);
    cout << von9(3) << '\n';          // Ausgabe: 6
    auto nochmalMinus3 = std::bind(std::minus<int>{}, _1, 3);
    cout << nochmalMinus3(9) << '\n'; // Ausgabe: 6
}

Godbolt Listing lst-0978-godb.cpp, https://godbolt.org/z/e6xT638ch:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/e6xT638ch 
#include <functional> // substract, minus, bind
#include <iostream>
using std::cout;
int substract(int a, int b) { return a - b; }
int main() {
    using namespace std::placeholders;
    cout << substract(9, 3) << '\n';  // Ausgabe: 6
    auto minus3 = std::bind(substract, _1, 3);
    cout << minus3(9) << '\n';        // Ausgabe: 6
    auto von9 = std::bind(substract, 9, _1);
    cout << von9(3) << '\n';          // Ausgabe: 6
    auto nochmalMinus3 = std::bind(std::minus<int>{}, _1, 3);
    cout << nochmalMinus3(9) << '\n'; // Ausgabe: 6
}

Listing 28.44: Mit »bind« können Sie auch alle Parameter einer Funktion festlegen.

Book listing lst-0979-book.cpp:

// https://godbolt.org/z/xxfbGd9Ma 
#include <random>
#include <vector>
#include <iostream>
#include <functional>
void wuerfel() {
  std::default_random_engine engine{};
  std::vector<size_t> counts{0,0,0,0,0,0};
  std::uniform_int_distribution<int> w6{0, 5}; // gleichverteilte Ganzzahlen
  auto w = std::bind(w6, engine);              // w() = w6(engine)
  for(auto i=1200*1000; i>0; --i) ++counts[w()];
  for(auto c : counts) std::cout<<" "<<c;
  std::cout << '\n';
}
int main() {
    wuerfel();
}

Godbolt Listing lst-0979-godb.cpp, https://godbolt.org/z/xxfbGd9Ma:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xxfbGd9Ma 
#include <random>
#include <vector>
#include <iostream>
#include <functional>
void wuerfel() {
  std::default_random_engine engine{};
  std::vector<size_t> counts{0,0,0,0,0,0};
  std::uniform_int_distribution<int> w6{0, 5}; // gleichverteilte Ganzzahlen
  auto w = std::bind(w6, engine);              // w() = w6(engine)
  for(auto i=1200*1000; i>0; --i) ++counts[w()];
  for(auto c : counts) std::cout<<" "<<c;
  std::cout << '\n';
}
int main() {
    wuerfel();
}

Listing 28.45: So machen Sie aus Klassenmitgliedern freie Funktionen.

Book listing lst-0982-book.cpp:

// https://godbolt.org/z/a3aTx7K7h 
#include <functional>
#include <iostream>
struct Zahlen {
    int dieZahl() {
        return 42;
    }
    int mehr(int n) {
        return n + data;
    }
    int data = 7;
};
int main() {
    auto func = std::mem_fn(&Zahlen::dieZahl);
    auto func2 = std::mem_fn(&Zahlen::mehr);
    auto zugriff = std::mem_fn(&Zahlen::data);
    Zahlen zahlen;
    std::cout << func(zahlen) << '\n';        // Ausgabe: 42
    std::cout << func2(zahlen, 66) << '\n';   // Ausgabe: 73
    std::cout << zugriff(zahlen) << '\n';     // Ausgabe: 7
}

Godbolt Listing lst-0982-godb.cpp, https://godbolt.org/z/a3aTx7K7h:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/a3aTx7K7h 
#include <functional>
#include <iostream>
struct Zahlen {
    int dieZahl() {
        return 42;
    }
    int mehr(int n) {
        return n + data;
    }
    int data = 7;
};
int main() {
    auto func = std::mem_fn(&Zahlen::dieZahl);
    auto func2 = std::mem_fn(&Zahlen::mehr);
    auto zugriff = std::mem_fn(&Zahlen::data);
    Zahlen zahlen;
    std::cout << func(zahlen) << '\n';        // Ausgabe: 42
    std::cout << func2(zahlen, 66) << '\n';   // Ausgabe: 73
    std::cout << zugriff(zahlen) << '\n';     // Ausgabe: 7
}

Listing 28.46: Basisfunktionalitäten von »variant«

Book listing lst-0983-book.cpp:

// https://godbolt.org/z/P8d494P6c 
#include <variant> 
using std::get;
int main() {
    std::variant<int, float> v{};
    v = 12;                  // Zustand wechselt auf int
    auto i = get<int>(v);    // holt den int
    std::cout << i << '\n';  // Ausgabe: 12
    v = 3.456f;              // Zustand wechselt auf float
    std::cout << get<float>(v) << '\n';  // Ausgabe: 3.456
    get<double>(v);          //             (ERR)  Fehler
    get<3>(v);               //             (ERR)  Fehler
    std::variant<int, float> w{};
    w = get<float>(v);       // Zugriff über Typ
    w = get<1>(v);           // Zugriff geht auch über Index
    w = v;                   // ganze Zuweisung geht auch
    try {
        get<int>(w);         // löst Exception aus
    } catch (std::bad_variant_access&) { /* ... */ }
}

Godbolt Listing lst-0983-godb.cpp, https://godbolt.org/z/P8d494P6c:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/P8d494P6c 
#include <variant> 
using std::get;
int main() {
    std::variant<int, float> v{};
    v = 12;                  // Zustand wechselt auf int
    auto i = get<int>(v);    // holt den int
    std::cout << i << '\n';  // Ausgabe: 12
    v = 3.456f;              // Zustand wechselt auf float
    std::cout << get<float>(v) << '\n';  // Ausgabe: 3.456
    get<double>(v);          //             (ERR)  Fehler
    get<3>(v);               //             (ERR)  Fehler
    std::variant<int, float> w{};
    w = get<float>(v);       // Zugriff über Typ
    w = get<1>(v);           // Zugriff geht auch über Index
    w = v;                   // ganze Zuweisung geht auch
    try {
        get<int>(w);         // löst Exception aus
    } catch (std::bad_variant_access&) { /* ... */ }
}

Listing 28.47: Einen »variant« per Visitor inspizieren

Book listing lst-0984-book.cpp:

// https://godbolt.org/z/ce3jETW6W 
#include <variant>
#include <iostream>
using std::cout;
struct TypGruss {
  void operator()(int) const { cout << "Hallo int"; }
  void operator()(float) const { cout << "Servus float"; }
};
int main() {
    std::variant<int, float> var{};
    var = 12;                                   // Zustand int
    std::visit([](auto a) { cout << a; }, var); // generisches Lambda
    cout << std::endl;
    var = 3.456f;                               // Zustand float
    std::visit(TypGruss{}, var);                // Funktor mit Überladungen
    cout << std::endl;
}

Godbolt Listing lst-0984-godb.cpp, https://godbolt.org/z/ce3jETW6W:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ce3jETW6W 
#include <variant>
#include <iostream>
using std::cout;
struct TypGruss {
  void operator()(int) const { cout << "Hallo int"; }
  void operator()(float) const { cout << "Servus float"; }
};
int main() {
    std::variant<int, float> var{};
    var = 12;                                   // Zustand int
    std::visit([](auto a) { cout << a; }, var); // generisches Lambda
    cout << std::endl;
    var = 3.456f;                               // Zustand float
    std::visit(TypGruss{}, var);                // Funktor mit Überladungen
    cout << std::endl;
}

GodboltId:1eco9Wcr3

Book listing lst-0985-book.cpp:

// https://godbolt.org/z/1eco9Wcr3 
#include <any>
#include <iostream>
#include <vector>
#include <string>
int main() {
    std::any a = 5;
    std::cout << std::any_cast<int>(a) << '\n';
    a = 3.456;
    std::cout << std::any_cast<double>(a) << '\n';
    using namespace std::literals;
    std::vector<std::any> data { 4, 8.976, "Geronimo"s };
    std::cout << std::any_cast<double>( data[1] ) << '\n';
    std::cout << data[1].type().name()  << '\n';
}

Godbolt Listing lst-0985-godb.cpp, https://godbolt.org/z/1eco9Wcr3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1eco9Wcr3 
#include <any>
#include <iostream>
#include <vector>
#include <string>
int main() {
    std::any a = 5;
    std::cout << std::any_cast<int>(a) << '\n';
    a = 3.456;
    std::cout << std::any_cast<double>(a) << '\n';
    using namespace std::literals;
    std::vector<std::any> data { 4, 8.976, "Geronimo"s };
    std::cout << std::any_cast<double>( data[1] ) << '\n';
    std::cout << data[1].type().name()  << '\n';
}

GodboltId:r5PqK8M8o

Book listing lst-0988-book.cpp:

// https://godbolt.org/z/r5PqK8M8o 
#include <charconv>
#include <vector>
#include <iostream>
#include <string>

std::vector<size_t> num_to_vec(const std::string& nums) {
    std::vector<size_t> result {};
    // ohne Leerzeichen am Ende
    const auto end = nums.data() + nums.find_last_not_of( ' ' ) + 1;
    const char* st = nullptr; // Zählpointer in der Schleife
    auto last = nums.data();  // letztes nicht übersetztes Zeichen
    size_t n;                 // konvertierte Zahl
    do {
        for(st = last; (st<end)&&(*st==' ' ); ++st); // überspringe ' '
        if (last = std::from_chars(st, end, n).ptr; last != st)
            result.push_back(n);                     // speichere Zahl
    } while (last != st);
    return result;
}

void fehlerDemo(const char* buf, size_t sz) {
    int n;
    auto [p, ec] = std::from_chars(buf, buf+sz, n);
    if (ec != std::errc{}) {
       const auto error = std::make_error_code(ec);
       std::cout << error.message() << '\n';
    }
}

int main() {
    auto result = num_to_vec("12 33 43");

    for(auto r : result) std::cout << r << " ";
    std::cout << '\n';
    // Ausgabe: 12 33 43

    fehlerDemo("XYZ", 4);
    // Ausgabe: Invalid argument

    fehlerDemo("123123123123123", 16);
    // Ausgabe: Numerical result out of range
}

Godbolt Listing lst-0988-godb.cpp, https://godbolt.org/z/r5PqK8M8o:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/r5PqK8M8o 
#include <charconv>
#include <vector>
#include <iostream>
#include <string>

std::vector<size_t> num_to_vec(const std::string& nums) {
    std::vector<size_t> result {};
    // ohne Leerzeichen am Ende
    const auto end = nums.data() + nums.find_last_not_of( ' ' ) + 1;
    const char* st = nullptr; // Zählpointer in der Schleife
    auto last = nums.data();  // letztes nicht übersetztes Zeichen
    size_t n;                 // konvertierte Zahl
    do {
        for(st = last; (st<end)&&(*st==' ' ); ++st); // überspringe ' '
        if (last = std::from_chars(st, end, n).ptr; last != st)
            result.push_back(n);                     // speichere Zahl
    } while (last != st);
    return result;
}

void fehlerDemo(const char* buf, size_t sz) {
    int n;
    auto [p, ec] = std::from_chars(buf, buf+sz, n);
    if (ec != std::errc{}) {
       const auto error = std::make_error_code(ec);
       std::cout << error.message() << '\n';
    }
}

int main() {
    auto result = num_to_vec("12 33 43");

    for(auto r : result) std::cout << r << " ";
    std::cout << '\n';
    // Ausgabe: 12 33 43

    fehlerDemo("XYZ", 4);
    // Ausgabe: Invalid argument

    fehlerDemo("123123123123123", 16);
    // Ausgabe: Numerical result out of range
}

GodboltId:dcqenEd31

Book listing lst-0990-book.cpp:

// https://godbolt.org/z/dcqenEd31 
#include <iostream>
#include <charconv>
#include <string_view>
#include <array>
int main() {
    std::array<char, 10> str {};
    if(auto [p, ec] = std::to_chars(str.data(), str.data() + str.size(), 42);
       ec == std::errc{} )
        std::cout << std::string_view(str.data(), p - str.data()) << "\n";
}

Godbolt Listing lst-0990-godb.cpp, https://godbolt.org/z/dcqenEd31:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/dcqenEd31 
#include <iostream>
#include <charconv>
#include <string_view>
#include <array>
int main() {
    std::array<char, 10> str {};
    if(auto [p, ec] = std::to_chars(str.data(), str.data() + str.size(), 42);
       ec == std::errc{} )
        std::cout << std::string_view(str.data(), p - str.data()) << "\n";
}

Listing 29.1: So starten Sie einen Thread.

Book listing lst-0991-book.cpp:

// https://godbolt.org/z/qnadYPWh1 
#include <iostream>
#include <thread>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }
void aufgabe2() { auto r = fib(41); cout << "fib(41)=" << r << endl; }
void aufgabe3() { auto r = fib(42); cout << "fib(42)=" << r << endl; }

struct HintergrundAufgabe {
    void operator()() const {
        aufgabe1();
        aufgabe2();
        aufgabe3();
    }
};

int main() {
    HintergrundAufgabe hintergrundAufgabe{};  // Initialisierung, berechnet noch nichts
    std::jthread meinThread{ hintergrundAufgabe }; // Berechnung startet
}

Godbolt Listing lst-0991-godb.cpp, https://godbolt.org/z/qnadYPWh1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/qnadYPWh1 
#include <iostream>
#include <thread>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }
void aufgabe2() { auto r = fib(41); cout << "fib(41)=" << r << endl; }
void aufgabe3() { auto r = fib(42); cout << "fib(42)=" << r << endl; }

struct HintergrundAufgabe {
    void operator()() const {
        aufgabe1();
        aufgabe2();
        aufgabe3();
    }
};

int main() {
    HintergrundAufgabe hintergrundAufgabe{};  // Initialisierung, berechnet noch nichts
    std::jthread meinThread{ hintergrundAufgabe }; // Berechnung startet
}

GodboltId:nPGY47r4K

Book listing lst-0993-book.cpp:

// https://godbolt.org/z/nPGY47r4K 
std::jthread meinThread{ [] {
    aufgabe1();
    aufgabe2();
    aufgabe3();
} };

Godbolt Listing lst-0993-godb.cpp, https://godbolt.org/z/nPGY47r4K:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/nPGY47r4K 
std::jthread meinThread{ [] {
    aufgabe1();
    aufgabe2();
    aufgabe3();
} };

Listing 29.2: Mit »stop_token« kommuniziert die Außenwelt in den Thread hinein.

Book listing lst-0994-book.cpp:

// https://godbolt.org/z/6cqd7Tsae 
struct HintergrundAufgabe {
    void operator()(std::stop_token st) const { // Token fürs Kommunizieren
        aufgabe1();
        if(st.stop_requested()) return;
        aufgabe2();
        if(st.stop_requested()) return;
        aufgabe3();
    }
};
int main() {
    HintergrundAufgabe hintergrundAufgabe{};
    std::jthread meinThread{ hintergrundAufgabe };
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // warte 100ms
    meinThread.request_stop(); // bitte den Thread, sich zu beenden
}

Godbolt Listing lst-0994-godb.cpp, https://godbolt.org/z/6cqd7Tsae:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/6cqd7Tsae 
struct HintergrundAufgabe {
    void operator()(std::stop_token st) const { // Token fürs Kommunizieren
        aufgabe1();
        if(st.stop_requested()) return;
        aufgabe2();
        if(st.stop_requested()) return;
        aufgabe3();
    }
};
int main() {
    HintergrundAufgabe hintergrundAufgabe{};
    std::jthread meinThread{ hintergrundAufgabe };
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // warte 100ms
    meinThread.request_stop(); // bitte den Thread, sich zu beenden
}

GodboltId:Tzs93MzfK

Book listing lst-0995-book.cpp:

// https://godbolt.org/z/Tzs93MzfK 
std::thread meinThread{ [] {  // purer Thread
    aufgabe1();
    aufgabe2();
    aufgabe3();
} };
meinThread.join();   // wartet auf das Ende des Threads

Godbolt Listing lst-0995-godb.cpp, https://godbolt.org/z/Tzs93MzfK:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Tzs93MzfK 
std::thread meinThread{ [] {  // purer Thread
    aufgabe1();
    aufgabe2();
    aufgabe3();
} };
meinThread.join();   // wartet auf das Ende des Threads

GodboltId:1jhrx1MMn

Book listing lst-0996-book.cpp:

// https://godbolt.org/z/1jhrx1MMn 
#include <iostream>
#include <thread>
#include <vector>
#include <exception>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }

void hauptprogramm() {
    try {
        std::thread th{ &aufgabe1 };
        std::vector data{ 0,1,2 };
        data.at(666);                     //             (ERR)  löst out_of_range aus
        th.join();                        // würde warten
    } catch(std::runtime_error &ex) {           //             (ERR)  passt nicht auf out_of_range
         /*...*/
    }
}

int main() {
  try {
    hauptprogramm();
  } catch( ... ) {                               // so weit, so gut, sieht sicher aus
    std::cout << "Ein Fehler ist aufgetreten\n"; // bekommen Sie nicht zu Gesicht
  }
}

Godbolt Listing lst-0996-godb.cpp, https://godbolt.org/z/1jhrx1MMn:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1jhrx1MMn 
#include <iostream>
#include <thread>
#include <vector>
#include <exception>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }

void hauptprogramm() {
    try {
        std::thread th{ &aufgabe1 };
        std::vector data{ 0,1,2 };
        data.at(666);                     //             (ERR)  löst out_of_range aus
        th.join();                        // würde warten
    } catch(std::runtime_error &ex) {           //             (ERR)  passt nicht auf out_of_range
         /*...*/
    }
}

int main() {
  try {
    hauptprogramm();
  } catch( ... ) {                               // so weit, so gut, sieht sicher aus
    std::cout << "Ein Fehler ist aufgetreten\n"; // bekommen Sie nicht zu Gesicht
  }
}

GodboltId:1aj16d7Ga

Book listing lst-0997-book.cpp:

// https://godbolt.org/z/1aj16d7Ga 
#include <iostream>
#include <thread>
#include <vector>
#include <exception>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }

void hauptprogramm() {
    std::thread th{ &aufgabe1 };
    try {
        std::vector data{ 0,1,2 };
        data.at(666);                 //             (ERR)  löst out_of_range aus
    } catch(std::runtime_error &ex) { // passt nicht auf out_of_range
         /* ... */                        // speziellen Fehler hier behandeln
    } catch( ... ) {
        th.join();
        throw;                        // Fehlerbehandlung außen fortsetzen
    }
    th.join();                        // wartet nach Okay oder speziellem Fehler
}

int main() {
    try {
        hauptprogramm();
    } catch( ... ) {
        std::cout << "Ein Fehler ist aufgetreten\n";
    }
}

Godbolt Listing lst-0997-godb.cpp, https://godbolt.org/z/1aj16d7Ga:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1aj16d7Ga 
#include <iostream>
#include <thread>
#include <vector>
#include <exception>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void aufgabe1() { auto r = fib(40); cout << "fib(40)=" << r << endl; }

void hauptprogramm() {
    std::thread th{ &aufgabe1 };
    try {
        std::vector data{ 0,1,2 };
        data.at(666);                 //             (ERR)  löst out_of_range aus
    } catch(std::runtime_error &ex) { // passt nicht auf out_of_range
         /* ... */                        // speziellen Fehler hier behandeln
    } catch( ... ) {
        th.join();
        throw;                        // Fehlerbehandlung außen fortsetzen
    }
    th.join();                        // wartet nach Okay oder speziellem Fehler
}

int main() {
    try {
        hauptprogramm();
    } catch( ... ) {
        std::cout << "Ein Fehler ist aufgetreten\n";
    }
}

GodboltId:8TdzEGf3d

Book listing lst-0998-book.cpp:

// https://godbolt.org/z/8TdzEGf3d 
void hauptprogramm() {
    std::jthread th{ &aufgabe1 };
    std::vector data{ 0,1,2 };
    data.at(666);                 //             (ERR)  löst out_of_range aus
}

Godbolt Listing lst-0998-godb.cpp, https://godbolt.org/z/8TdzEGf3d:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/8TdzEGf3d 
void hauptprogramm() {
    std::jthread th{ &aufgabe1 };
    std::vector data{ 0,1,2 };
    data.at(666);                 //             (ERR)  löst out_of_range aus
}

Listing 29.3: Parameter an die Threadfunktion fügen Sie dem Konstruktor hinzu.

Book listing lst-0999-book.cpp:

// https://godbolt.org/z/PP4GT3oc6 
#include <iostream>
#include <thread>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long n) {
    auto r = fib(n);
    cout << "fib("<<n<<")=" << r << endl;
}
long ack(long m, long n) { // Ackermannfunktion
    if(m==0) return n+1;
    if(n==0) return ack(m-1, 1);
    return ack(m - 1, ack(m, n-1));
}
void runAck(long m, long n) {
    auto r = ack(m, n);
    cout << "ack("<<m<<','<<n<<")=" << r << endl;
}

int main() {
    std::jthread f40{ runFib, 40 };
    std::jthread f41{ runFib, 41 };
    std::jthread f42{ runFib, 42 };

    f40.join(); f41.join(); f42.join();

    std::thread a1{ runAck, 4, 0 };
    std::thread a2{ runAck, 4, 1 };
    std::thread a3{ runAck, 2, 700 };
    std::thread a4{ runAck, 3, 10 };
}

Godbolt Listing lst-0999-godb.cpp, https://godbolt.org/z/PP4GT3oc6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/PP4GT3oc6 
#include <iostream>
#include <thread>
using std::cout; using std::endl;

long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long n) {
    auto r = fib(n);
    cout << "fib("<<n<<")=" << r << endl;
}
long ack(long m, long n) { // Ackermannfunktion
    if(m==0) return n+1;
    if(n==0) return ack(m-1, 1);
    return ack(m - 1, ack(m, n-1));
}
void runAck(long m, long n) {
    auto r = ack(m, n);
    cout << "ack("<<m<<','<<n<<")=" << r << endl;
}

int main() {
    std::jthread f40{ runFib, 40 };
    std::jthread f41{ runFib, 41 };
    std::jthread f42{ runFib, 42 };

    f40.join(); f41.join(); f42.join();

    std::thread a1{ runAck, 4, 0 };
    std::thread a2{ runAck, 4, 1 };
    std::thread a3{ runAck, 2, 700 };
    std::thread a4{ runAck, 3, 10 };
}

Listing 29.4: Parameter werden in den Thread kopiert.

Book listing lst-1000-book.cpp:

// https://godbolt.org/z/fbnbKzrs1 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s

void delayPrint(seconds s, const std::string& msg) {
    std::this_thread::sleep_for(s);
    std::cout << msg << std::endl;
}
int main() {
    std::jthread m1{ delayPrint, 1s, "Auf die Plaetze" };
    std::jthread m2{ delayPrint, 2s, std::string{"fertig"} };
    std::string los = "los";
    std::jthread m3{ delayPrint, 3s, los };
}

Godbolt Listing lst-1000-godb.cpp, https://godbolt.org/z/fbnbKzrs1:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/fbnbKzrs1 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s

void delayPrint(seconds s, const std::string& msg) {
    std::this_thread::sleep_for(s);
    std::cout << msg << std::endl;
}
int main() {
    std::jthread m1{ delayPrint, 1s, "Auf die Plaetze" };
    std::jthread m2{ delayPrint, 2s, std::string{"fertig"} };
    std::string los = "los";
    std::jthread m3{ delayPrint, 3s, los };
}

Listing 29.5: Achtung mit rohen Zeigern als Parameter

Book listing lst-1001-book.cpp:

// https://godbolt.org/z/hvq5dbzde 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s

void delayPrint(seconds s, const char* msg) { //                     (ERR)  roher Zeiger
    std::this_thread::sleep_for(s);
    std::cout << msg << std::endl;            //                     (ERR)  das klappt nicht
}

void lauf() {
    const char risiko[] = "Das geht nicht gut...";
    std::jthread m{ delayPrint, 1s, risiko }; //                     (ERR)  roher Zeiger
    m.detach();
    // hier wird der Bereich von 'risiko' verlassen
}
int main() {
    lauf();
    std::this_thread::sleep_for(2s);          // noch 2 Sekunden warten
}

Godbolt Listing lst-1001-godb.cpp, https://godbolt.org/z/hvq5dbzde:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/hvq5dbzde 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s

void delayPrint(seconds s, const char* msg) { //                     (ERR)  roher Zeiger
    std::this_thread::sleep_for(s);
    std::cout << msg << std::endl;            //                     (ERR)  das klappt nicht
}

void lauf() {
    const char risiko[] = "Das geht nicht gut...";
    std::jthread m{ delayPrint, 1s, risiko }; //                     (ERR)  roher Zeiger
    m.detach();
    // hier wird der Bereich von 'risiko' verlassen
}
int main() {
    lauf();
    std::this_thread::sleep_for(2s);          // noch 2 Sekunden warten
}

Listing 29.6: Mit ref eine Referenz erzwingen

Book listing lst-1002-book.cpp:

// https://godbolt.org/z/GnsWYvecv 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
struct Zustand {
    int zaehler;
};
void zeigeZustand(const Zustand& zustand) {
    for(auto i : { 5,4,3,2,1 }) {
        std::cout << "zaehler: " << zustand.zaehler << std::endl;
        std::this_thread::sleep_for(1s);
    }
}
int main() {
    Zustand zustand { 4 };
    std::jthread th{zeigeZustand, std::ref(zustand)}; // bleibt Referenz auf zustand
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 501;
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 87;
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 2;
}

Godbolt Listing lst-1002-godb.cpp, https://godbolt.org/z/GnsWYvecv:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/GnsWYvecv 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
struct Zustand {
    int zaehler;
};
void zeigeZustand(const Zustand& zustand) {
    for(auto i : { 5,4,3,2,1 }) {
        std::cout << "zaehler: " << zustand.zaehler << std::endl;
        std::this_thread::sleep_for(1s);
    }
}
int main() {
    Zustand zustand { 4 };
    std::jthread th{zeigeZustand, std::ref(zustand)}; // bleibt Referenz auf zustand
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 501;
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 87;
    std::this_thread::sleep_for(1s);
    zustand.zaehler = 2;
}

Listing 29.7: Mit move Eingaben in den Thread verschieben

Book listing lst-1003-book.cpp:

// https://godbolt.org/z/j5Y15Esx7 
// … includes …
#include <thread>
using namespace std::chrono; // seconds, suffix s
struct Image {
    std::vector<char> data_; // Kopie teuer
    explicit Image() : data_(1'000'000) {}
};
void zeigeImage(Image img) {
    std::cout << img.data_.size() << '\n';
}
void zeigeIptr(std::unique_ptr<int> iptr) {
    std::cout << *iptr << '\n';
}
int main() {
    // teuer zu kopieren, aber dafür gut zu verschieben:
    Image image{};
    std::cout << image.data_.size() << std::endl;    // Ausgabe: 1000000
    std::jthread th1{ zeigeImage, std::move(image) };// Ausgabe: 1000000
    std::this_thread::sleep_for(1s);
    std::cout << image.data_.size() << std::endl;    // Ausgabe: 0
    th1.join();  // explizit warten, bis der Thread fertig ist
    // unmöglich zu kopieren, aber gut zu verschieben:
    auto iptr = std::make_unique<int>( 657 );
    std::cout << (bool)iptr << std::endl;            // Ausgabe: 1 für wahr
    std::jthread th2{ zeigeIptr, std::move(iptr) };  // Ausgabe: 657
    std::this_thread::sleep_for(1s);
    std::cout << (bool)iptr.get() << std::endl;      // Ausgabe: 0 für falsch
}

Godbolt Listing lst-1003-godb.cpp, https://godbolt.org/z/j5Y15Esx7:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/j5Y15Esx7 
// … includes …
#include <thread>
using namespace std::chrono; // seconds, suffix s
struct Image {
    std::vector<char> data_; // Kopie teuer
    explicit Image() : data_(1'000'000) {}
};
void zeigeImage(Image img) {
    std::cout << img.data_.size() << '\n';
}
void zeigeIptr(std::unique_ptr<int> iptr) {
    std::cout << *iptr << '\n';
}
int main() {
    // teuer zu kopieren, aber dafür gut zu verschieben:
    Image image{};
    std::cout << image.data_.size() << std::endl;    // Ausgabe: 1000000
    std::jthread th1{ zeigeImage, std::move(image) };// Ausgabe: 1000000
    std::this_thread::sleep_for(1s);
    std::cout << image.data_.size() << std::endl;    // Ausgabe: 0
    th1.join();  // explizit warten, bis der Thread fertig ist
    // unmöglich zu kopieren, aber gut zu verschieben:
    auto iptr = std::make_unique<int>( 657 );
    std::cout << (bool)iptr << std::endl;            // Ausgabe: 1 für wahr
    std::jthread th2{ zeigeIptr, std::move(iptr) };  // Ausgabe: 657
    std::this_thread::sleep_for(1s);
    std::cout << (bool)iptr.get() << std::endl;      // Ausgabe: 0 für falsch
}

Listing 29.8: Einen Thread zurückgeben

Book listing lst-1004-book.cpp:

// https://godbolt.org/z/Kv84eb96E 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
auto makeThread(std::string wer) {
    return std::jthread{ [wer] {
        std::this_thread::sleep_for(1s);
        std::cout << "Viel Glueck, " << wer << std::endl;
    } };
}
int main() {
    auto th = makeThread("Jim"); // Ausgabe: Viel Glueck, Jim
    th.join();
}

Godbolt Listing lst-1004-godb.cpp, https://godbolt.org/z/Kv84eb96E:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Kv84eb96E 
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
auto makeThread(std::string wer) {
    return std::jthread{ [wer] {
        std::this_thread::sleep_for(1s);
        std::cout << "Viel Glueck, " << wer << std::endl;
    } };
}
int main() {
    auto th = makeThread("Jim"); // Ausgabe: Viel Glueck, Jim
    th.join();
}

Listing 29.9: Einen Thread verschieben

Book listing lst-1005-book.cpp:

// https://godbolt.org/z/39x4bafco 
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
void kobraUebernehmenSie(std::jthread job) {
    job.join();
}
int main() {
     std::jthread th{ [] {
        std::this_thread::sleep_for(1s);
        std::cout << "Viel Glueck, Dan" << std::endl;
    } };
    kobraUebernehmenSie( std::move(th) );  // Zuständigkeit übertragen
}

Godbolt Listing lst-1005-godb.cpp, https://godbolt.org/z/39x4bafco:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/39x4bafco 
#include <thread>
#include <chrono>
using namespace std::chrono; // seconds, suffix s
void kobraUebernehmenSie(std::jthread job) {
    job.join();
}
int main() {
     std::jthread th{ [] {
        std::this_thread::sleep_for(1s);
        std::cout << "Viel Glueck, Dan" << std::endl;
    } };
    kobraUebernehmenSie( std::move(th) );  // Zuständigkeit übertragen
}

Listing 29.10: Threads im Container

Book listing lst-1006-book.cpp:

// https://godbolt.org/z/YrEPnYMaP 
#include <iostream>
#include <thread>
#include <vector>
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long n) { auto r = fib(n); cout << "fib("<<n<<")=" << r << endl; }
int main() {
    std::vector<std::jthread> threads;
    // starten
    for( auto n : { 38, 39, 40, 41, 42, 43, }) {
        threads.emplace_back( runFib, n );
    }
}

Godbolt Listing lst-1006-godb.cpp, https://godbolt.org/z/YrEPnYMaP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/YrEPnYMaP 
#include <iostream>
#include <thread>
#include <vector>
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
void runFib(long n) { auto r = fib(n); cout << "fib("<<n<<")=" << r << endl; }
int main() {
    std::vector<std::jthread> threads;
    // starten
    for( auto n : { 38, 39, 40, 41, 42, 43, }) {
        threads.emplace_back( runFib, n );
    }
}

Listing 29.11: Parallelität der Hardware herausfinden

Book listing lst-1009-book.cpp:

// https://godbolt.org/z/Gen1rfEn6 
#include <thread>
#include <iostream>
#include <vector>
#include <chrono>  // steady_clock
using std::cout; using std::endl; using namespace std::chrono;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
  cout << std::thread::hardware_concurrency() << '\n';
  for(int nthreads : { 1,2,3,4,5,6 }) {
    cout << "Threads: ";
    const auto start = steady_clock::now();

    std::vector<std::jthread> threads;
    for(int ti = 1; ti <= nthreads; ++ti) {
      threads.emplace_back( std::jthread{fib, 40});
      cout << ti << "... "; cout.flush();
    }
    for(auto &th : threads) th.join(); // explizit joinen vor der Zeitmessung

    const auto now = steady_clock::now();
    cout << "  Zeit:  " << duration_cast<milliseconds>(
        now-start).count()<<"ms\n";
  }
}

Godbolt Listing lst-1009-godb.cpp, https://godbolt.org/z/Gen1rfEn6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gen1rfEn6 
#include <thread>
#include <iostream>
#include <vector>
#include <chrono>  // steady_clock
using std::cout; using std::endl; using namespace std::chrono;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
  cout << std::thread::hardware_concurrency() << '\n';
  for(int nthreads : { 1,2,3,4,5,6 }) {
    cout << "Threads: ";
    const auto start = steady_clock::now();

    std::vector<std::jthread> threads;
    for(int ti = 1; ti <= nthreads; ++ti) {
      threads.emplace_back( std::jthread{fib, 40});
      cout << ti << "... "; cout.flush();
    }
    for(auto &th : threads) th.join(); // explizit joinen vor der Zeitmessung

    const auto now = steady_clock::now();
    cout << "  Zeit:  " << duration_cast<milliseconds>(
        now-start).count()<<"ms\n";
  }
}

Listing 29.12: Jeder Thread hat eine Kennung.

Book listing lst-1010-book.cpp:

// https://godbolt.org/z/TM6c7cdss 
#include <thread>
#include <iostream>
int main() {
    std::cout << "Main: " << std::this_thread::get_id() << '\n';
    std::jthread th{ []{
        std::cout << "Thread: " << std::this_thread::get_id() << '\n';
    }};
}

Godbolt Listing lst-1010-godb.cpp, https://godbolt.org/z/TM6c7cdss:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TM6c7cdss 
#include <thread>
#include <iostream>
int main() {
    std::cout << "Main: " << std::this_thread::get_id() << '\n';
    std::jthread th{ []{
        std::cout << "Thread: " << std::this_thread::get_id() << '\n';
    }};
}

Listing 29.13: Ein klassisches Data Race

Book listing lst-1011-book.cpp:

// https://godbolt.org/z/7GEs9a4n6 
#include <thread>
#include <iostream>

int count = 0; // wird simultan verändert

void run() {
    for(int i=0; i<1'000'000; ++i) {
        count += 1;   // ungeschützt
    }
}

int main() {
    std::cout << "Start: " << count << '\n';  // Ausgabe: Start: 0
    std::thread th1{ run };
    std::thread th2{ run };
    std::thread th3{ run };
    th1.join(); th2.join(); th3.join();
    std::cout << "Ende: " << count << '\n';  // Ausgabe sicher nicht: 3000000
}

Godbolt Listing lst-1011-godb.cpp, https://godbolt.org/z/7GEs9a4n6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7GEs9a4n6 
#include <thread>
#include <iostream>

int count = 0; // wird simultan verändert

void run() {
    for(int i=0; i<1'000'000; ++i) {
        count += 1;   // ungeschützt
    }
}

int main() {
    std::cout << "Start: " << count << '\n';  // Ausgabe: Start: 0
    std::thread th1{ run };
    std::thread th2{ run };
    std::thread th3{ run };
    th1.join(); th2.join(); th3.join();
    std::cout << "Ende: " << count << '\n';  // Ausgabe sicher nicht: 3000000
}

Listing 29.14: Gutartige Data Races sind auch undefiniert.

Book listing lst-1012-book.cpp:

// https://godbolt.org/z/v3b6sxEab 
#include <thread>
/* exakte Zählung nicht so wichtig */
int count = 0; // wird simultan verändert
void run() {
    for(int i=0; i<1'000; ++i) {
        count += 1; // ungeschützt
        if(count > 1000) return;  //                 (ERR)  Endbedingung
        for(int j=0; j<1'000; ++j)
            ;
    }
}

int main() {
    std::thread th1{ run };
    std::thread th2{ run };
    std::thread th3{ run };
    th1.join(); th2.join(); th3.join();
}

Godbolt Listing lst-1012-godb.cpp, https://godbolt.org/z/v3b6sxEab:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/v3b6sxEab 
#include <thread>
/* exakte Zählung nicht so wichtig */
int count = 0; // wird simultan verändert
void run() {
    for(int i=0; i<1'000; ++i) {
        count += 1; // ungeschützt
        if(count > 1000) return;  //                 (ERR)  Endbedingung
        for(int j=0; j<1'000; ++j)
            ;
    }
}

int main() {
    std::thread th1{ run };
    std::thread th2{ run };
    std::thread th3{ run };
    th1.join(); th2.join(); th3.join();
}

Listing 29.15: Latches können herunterzählen und warten.

Book listing lst-1013-book.cpp:

// https://godbolt.org/z/rrfn4d5WP 
#include <thread>
#include <latch>
#include <iostream>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    std::latch la{ 3 };                                // wir erwarten 3 Threads
    std::jthread th1{ [&la] { fib(39); la.count_down(); } };
    std::jthread th2{ [&la] { fib(38); la.count_down(); } };
    std::jthread th3{ [&la] { fib(40); la.count_down(); } };
    fib(37); // Hauptthread
    std::cout << "Haupthread: fertig\n";
    la.wait();                                         // wartet bis la == 0
    std::cout << "Rest fertig\n";
}

Godbolt Listing lst-1013-godb.cpp, https://godbolt.org/z/rrfn4d5WP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/rrfn4d5WP 
#include <thread>
#include <latch>
#include <iostream>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    std::latch la{ 3 };                                // wir erwarten 3 Threads
    std::jthread th1{ [&la] { fib(39); la.count_down(); } };
    std::jthread th2{ [&la] { fib(38); la.count_down(); } };
    std::jthread th3{ [&la] { fib(40); la.count_down(); } };
    fib(37); // Hauptthread
    std::cout << "Haupthread: fertig\n";
    la.wait();                                         // wartet bis la == 0
    std::cout << "Rest fertig\n";
}

Listing 29.16: Eine Barriere wartet auf eine bestimmte Anzahl von Threads.

Book listing lst-1014-book.cpp:

// https://godbolt.org/z/d3dc1Tsj8 
#include <thread>
#include <barrier>
#include <iostream>
#include <vector>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

constexpr int anz = 8;             // 8 Worker
constexpr int max_n = 32;          // bis 32 berechnen
std::vector<long> ergebnisse(anz); // Puffer: Platz für 8 Ergebnisse

void ausgeben() {                  // Signalisierungsfunktion druckt Puffer
    for (auto n : ergebnisse) std::cout << n << ' ';
    std::cout << '\n';
}

std::barrier ba{anz, ausgeben};    // immer nach 8 ausgeben

void worker(std::stop_token st, int idx) {
    // n = 0, 9, 17, 25, … ; 1, 10, 18, 26, …
    for(int n = idx; n<max_n; n += anz) {
        if(st.stop_requested()) return;
        ergebnisse[idx] = fib(n);  // schreibe Ergebnis in Puffer
        ba.arrive_and_wait();      // warte, bis 8 Threads hier sind
    }
}

int main() {
    std::vector<std::jthread> threads;     // 8 Threads
    for (int idx=0; idx<anz; ++idx) {
        threads.emplace_back(worker, idx); // erzeuge Thread mit Index
    }
    for (auto& t : threads) t.join();      // warte, bis alle fertig sind
}

Godbolt Listing lst-1014-godb.cpp, https://godbolt.org/z/d3dc1Tsj8:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/d3dc1Tsj8 
#include <thread>
#include <barrier>
#include <iostream>
#include <vector>
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

constexpr int anz = 8;             // 8 Worker
constexpr int max_n = 32;          // bis 32 berechnen
std::vector<long> ergebnisse(anz); // Puffer: Platz für 8 Ergebnisse

void ausgeben() {                  // Signalisierungsfunktion druckt Puffer
    for (auto n : ergebnisse) std::cout << n << ' ';
    std::cout << '\n';
}

std::barrier ba{anz, ausgeben};    // immer nach 8 ausgeben

void worker(std::stop_token st, int idx) {
    // n = 0, 9, 17, 25, … ; 1, 10, 18, 26, …
    for(int n = idx; n<max_n; n += anz) {
        if(st.stop_requested()) return;
        ergebnisse[idx] = fib(n);  // schreibe Ergebnis in Puffer
        ba.arrive_and_wait();      // warte, bis 8 Threads hier sind
    }
}

int main() {
    std::vector<std::jthread> threads;     // 8 Threads
    for (int idx=0; idx<anz; ++idx) {
        threads.emplace_back(worker, idx); // erzeuge Thread mit Index
    }
    for (auto& t : threads) t.join();      // warte, bis alle fertig sind
}

Listing 29.17: Ein Mutex zusammen mit einem einfachen Lock

Book listing lst-1015-book.cpp:

// https://godbolt.org/z/3fz5a4vYv 
#include <mutex> // mutex, lock_guard
#include <list>
#include <algorithm> // find
using std::lock_guard; using std::mutex; using std::find;
class MxIntList {
    std::list <int> data_;
    mutable mutex mx_;
public:
    void add(int value) {
        lock_guard guard{mx_};  // schützt bis Ende der Methode
        data_.push_back(value);
    }
    bool contains(int searchVal) const {
        lock_guard guard{mx_};  // schützt bis Ende der Methode
        return find(data_.begin(), data_.end(), searchVal) != data_.end();
    }
};

Godbolt Listing lst-1015-godb.cpp, https://godbolt.org/z/3fz5a4vYv:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3fz5a4vYv 
#include <mutex> // mutex, lock_guard
#include <list>
#include <algorithm> // find
using std::lock_guard; using std::mutex; using std::find;
class MxIntList {
    std::list <int> data_;
    mutable mutex mx_;
public:
    void add(int value) {
        lock_guard guard{mx_};  // schützt bis Ende der Methode
        data_.push_back(value);
    }
    bool contains(int searchVal) const {
        lock_guard guard{mx_};  // schützt bis Ende der Methode
        return find(data_.begin(), data_.end(), searchVal) != data_.end();
    }
};

Listing 29.18: Die Schnittstelle zu einem multithreadfähigen Stack

Book listing lst-1016-book.cpp:

// https://godbolt.org/z/4j7njd763 
#include <vector>

template<class T>
class MxStack {
public:
    bool isEmpty() const;
    void push(const T&);
    void pop();
    const T& top() const;
};

Godbolt Listing lst-1016-godb.cpp, https://godbolt.org/z/4j7njd763:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/4j7njd763 
#include <vector>

template<class T>
class MxStack {
public:
    bool isEmpty() const;
    void push(const T&);
    void pop();
    const T& top() const;
};

Listing 29.19: Problematischer Code für den MxStack

Book listing lst-1017-book.cpp:

// https://godbolt.org/z/1boeTMMvf 
MxStack<int> mxs{};
// …
// mehr Code
// …
if( ! mxs.isEmpty()) {            //                 (ERR)  nicht sicher
    const auto value = mxs.top(); //                 (ERR)  nicht sicher
    mxs.pop();                    //                 (ERR)  nicht sicher
    // …
    // mehr Code
    // …
}

Godbolt Listing lst-1017-godb.cpp, https://godbolt.org/z/1boeTMMvf:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1boeTMMvf 
MxStack<int> mxs{};
// …
// mehr Code
// …
if( ! mxs.isEmpty()) {            //                 (ERR)  nicht sicher
    const auto value = mxs.top(); //                 (ERR)  nicht sicher
    mxs.pop();                    //                 (ERR)  nicht sicher
    // …
    // mehr Code
    // …
}

Listing 29.20: Eine Möglichkeit, wie zwei Threads obigen Code ausführen könnten

Book listing lst-1018-book.cpp:

/* Thread 1 */                         /* Thread 2 */
if( ! mxs.isEmpty()) {
                                    if( ! mxs.isEmpty()) {
    const auto value = mxs.top();
                                        const auto value = mxs.top();
    mxs.pop();
    // … mehr Code …
                                        mxs.pop();
                                        // … mehr Code …

Listing 29.21: Ein sehr einfacher threadsicherer Stack

Book listing lst-1019-book.cpp:

// https://godbolt.org/z/xGv9drh73 
#include <vector>
#include <thread>
#include <mutex>
#include <iostream>
#include <numeric>  // iota

/* T: noexcept kopier- und zuweisbar */
template<typename T>
class MxStack {
    std::vector<T> data_;
    std::mutex mx_;

public:
    MxStack() : data_{} {}

    bool isEmpty() const { return data_.empty(); }

    void push(const T& val) {
        std::lock_guard<std::mutex> g{mx_};
        data_.push_back(val);
    }

    T pop() {
        std::lock_guard g{mx_};
        if(data_.empty())
            throw std::length_error{"empty stack"};
        T tmp{std::move(data_.back())};
        data_.pop_back();
        return tmp;
    }
};

int main() {
    // Stack vorbereiten
    MxStack<int> mxs{};
    for(int i=1; i<=1'000'000; ++i) mxs.push(i);
    // Berechnung definieren
    auto sumIt = [&mxs](long &sum) {
        int val{};
        try {
            while( ! mxs.isEmpty()) {
                sum += mxs.pop(); // könnte immer noch werfen
            }
        } catch(std::length_error &ex) {}
    };
    // Berechnen
    long sum1 = 0;          // fürs Teilergebnis
    std::jthread th1{sumIt, std::ref(sum1)};
    long sum2 = 0;          // fürs Teilergebnis
    std::thread th2{sumIt, std::ref(sum2)};
    th1.join(); th2.join();
    long sum = sum1 + sum2; // Gesamtergebnis
    // Ergebnis
    std::cout << "Sollergebnis: "
        << (1'000'000L*1'000'001)/2 << '\n'; // Ausgabe: 500000500000
    std::cout << "Tatsaechlich: "
        << sum << '\n';                      // Ausgabe: 500000500000
}

Godbolt Listing lst-1019-godb.cpp, https://godbolt.org/z/xGv9drh73:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xGv9drh73 
#include <vector>
#include <thread>
#include <mutex>
#include <iostream>
#include <numeric>  // iota

/* T: noexcept kopier- und zuweisbar */
template<typename T>
class MxStack {
    std::vector<T> data_;
    std::mutex mx_;

public:
    MxStack() : data_{} {}

    bool isEmpty() const { return data_.empty(); }

    void push(const T& val) {
        std::lock_guard<std::mutex> g{mx_};
        data_.push_back(val);
    }

    T pop() {
        std::lock_guard g{mx_};
        if(data_.empty())
            throw std::length_error{"empty stack"};
        T tmp{std::move(data_.back())};
        data_.pop_back();
        return tmp;
    }
};

int main() {
    // Stack vorbereiten
    MxStack<int> mxs{};
    for(int i=1; i<=1'000'000; ++i) mxs.push(i);
    // Berechnung definieren
    auto sumIt = [&mxs](long &sum) {
        int val{};
        try {
            while( ! mxs.isEmpty()) {
                sum += mxs.pop(); // könnte immer noch werfen
            }
        } catch(std::length_error &ex) {}
    };
    // Berechnen
    long sum1 = 0;          // fürs Teilergebnis
    std::jthread th1{sumIt, std::ref(sum1)};
    long sum2 = 0;          // fürs Teilergebnis
    std::thread th2{sumIt, std::ref(sum2)};
    th1.join(); th2.join();
    long sum = sum1 + sum2; // Gesamtergebnis
    // Ergebnis
    std::cout << "Sollergebnis: "
        << (1'000'000L*1'000'001)/2 << '\n'; // Ausgabe: 500000500000
    std::cout << "Tatsaechlich: "
        << sum << '\n';                      // Ausgabe: 500000500000
}

Listing 29.22: »swap« für »MxStack«

Book listing lst-1022-book.cpp:

// https://godbolt.org/z/9PMcz1cqP 
friend void swap(MxStack& re, MxStack& li) {
    if(&re==&li) return; // Adresse dieselbe? Mit sich selbst tauschen unnötig
    std::lock( re.mx_, li.mx_ );   // mehrere Sperren gleichzeitig
    std::lock_guard lkre{re.mx_, std::adopt_lock}; // schon gesperrt
    std::lock_guard lkli{li.mx_, std::adopt_lock}; // schon gesperrt
    std::swap(li.data_, re.data_); // vertauschen ausführen
}

Godbolt Listing lst-1022-godb.cpp, https://godbolt.org/z/9PMcz1cqP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9PMcz1cqP 
friend void swap(MxStack& re, MxStack& li) {
    if(&re==&li) return; // Adresse dieselbe? Mit sich selbst tauschen unnötig
    std::lock( re.mx_, li.mx_ );   // mehrere Sperren gleichzeitig
    std::lock_guard lkre{re.mx_, std::adopt_lock}; // schon gesperrt
    std::lock_guard lkli{li.mx_, std::adopt_lock}; // schon gesperrt
    std::swap(li.data_, re.data_); // vertauschen ausführen
}

Listing 29.23: Mutexe kann man transferieren.

Book listing lst-1023-book.cpp:

// https://godbolt.org/z/e7rraPGx4 
#include <thread>
#include <mutex>
#include <vector>
#include <numeric> // accumulate, iota
using std::mutex; using std::unique_lock;

std::vector<int> myData;             // geteilte Daten
mutex myMutex;                       // Mutex zu den Daten
unique_lock<mutex> bereiteDatenVor() {
    unique_lock lk1{myMutex};        // sperren
    myData.resize(1000);
    std::iota(myData.begin(), myData.end(), 1); // 1..1000
    return lk1;                                 // Sperre transferieren
}
int verarbeiteDaten() {
    unique_lock lk2 = bereiteDatenVor();        // Sperre transferiert
    return std::accumulate(myData.begin(), myData.end(), 0);
}

Godbolt Listing lst-1023-godb.cpp, https://godbolt.org/z/e7rraPGx4:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/e7rraPGx4 
#include <thread>
#include <mutex>
#include <vector>
#include <numeric> // accumulate, iota
using std::mutex; using std::unique_lock;

std::vector<int> myData;             // geteilte Daten
mutex myMutex;                       // Mutex zu den Daten
unique_lock<mutex> bereiteDatenVor() {
    unique_lock lk1{myMutex};        // sperren
    myData.resize(1000);
    std::iota(myData.begin(), myData.end(), 1); // 1..1000
    return lk1;                                 // Sperre transferieren
}
int verarbeiteDaten() {
    unique_lock lk2 = bereiteDatenVor();        // Sperre transferiert
    return std::accumulate(myData.begin(), myData.end(), 0);
}

Listing 29.24: Späte Initialisierung mit nur einem Thread

Book listing lst-1024-book.cpp:

// https://godbolt.org/z/T7vehq58b 
std::shared_ptr<BigData> bigData{};
BigData& getBigData() {
    if(!bigData) bigData.reset(new BigData{});
    return *bigData;
}
int useBigData() {
    auto bigData = getBigData();
    // bigData->…
}

Godbolt Listing lst-1024-godb.cpp, https://godbolt.org/z/T7vehq58b:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/T7vehq58b 
std::shared_ptr<BigData> bigData{};
BigData& getBigData() {
    if(!bigData) bigData.reset(new BigData{});
    return *bigData;
}
int useBigData() {
    auto bigData = getBigData();
    // bigData->…
}

Listing 29.25: Späte Initialisierung mit mehreren Threads

Book listing lst-1025-book.cpp:

// https://godbolt.org/z/3vcnzfqfM 
#include <mutex> // once_flag, call_once
std::shared_ptr<BigData> bigData{};
std::once_flag bigDataInitFlag;
void initBigData() {
    bigData = std::make_shared<BigData>();
}
int useBigData() {
    std::call_once(bigDataInitFlag, initBigData);
    // bigData->…
}

Godbolt Listing lst-1025-godb.cpp, https://godbolt.org/z/3vcnzfqfM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3vcnzfqfM 
#include <mutex> // once_flag, call_once
std::shared_ptr<BigData> bigData{};
std::once_flag bigDataInitFlag;
void initBigData() {
    bigData = std::make_shared<BigData>();
}
int useBigData() {
    std::call_once(bigDataInitFlag, initBigData);
    // bigData->…
}

Listing 29.26: Späte Initialisierung kann auch innerhalb eines Threads nützlich sein.

Book listing lst-1026-book.cpp:

// https://godbolt.org/z/TcsrefEPh 
#include <mutex> // once_flag, call_once
#include <memory>
struct Connection {
    void csend(const char *data) {} // dummy
    const char* crecv() {} // dummy
};
class Sender {
    std::shared_ptr<Connection> conn_;
    std::once_flag connInitFlag_;
    void open() {
        conn_.reset( new Connection{} );
    }
public:
    void send(const char* data) {
        std::call_once(connInitFlag_, &Sender::open, this); // Methodenzeiger
        conn_->csend(data);
    }
    const char* recv() {
        std::call_once(connInitFlag_, [this] {this->open();} ); // Lambda
        return conn_->crecv();
    }
};

Godbolt Listing lst-1026-godb.cpp, https://godbolt.org/z/TcsrefEPh:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/TcsrefEPh 
#include <mutex> // once_flag, call_once
#include <memory>
struct Connection {
    void csend(const char *data) {} // dummy
    const char* crecv() {} // dummy
};
class Sender {
    std::shared_ptr<Connection> conn_;
    std::once_flag connInitFlag_;
    void open() {
        conn_.reset( new Connection{} );
    }
public:
    void send(const char* data) {
        std::call_once(connInitFlag_, &Sender::open, this); // Methodenzeiger
        conn_->csend(data);
    }
    const char* recv() {
        std::call_once(connInitFlag_, [this] {this->open();} ); // Lambda
        return conn_->crecv();
    }
};

Listing 29.27: Es sind Vorkehrungen nötig, wenn ein Mutex mehrmals gesperrt werden soll.

Book listing lst-1027-book.cpp:

// https://godbolt.org/z/38qMMWoz6 
#include <mutex> // recursive_mutex
#include <iostream>
struct MulDiv {
    std::recursive_mutex mx_;
    int value_;
    explicit MulDiv(int value) : value_{value} {}
    void mul(int x) {
        std::lock_guard lk1(mx_);  // innen
        value_ *= x;
    }
    void div(int x) {
        std::lock_guard lk2(mx_);  // innen
        value_ /= x;
    }
    void muldiv(int x, int y){
        std::lock_guard lk3(mx_);  // außen
        mul(x);
        div(y);
    }
};
int main() {
   MulDiv m{42}; // 3*7*2 *5
   m.muldiv(5, 15);
   std::cout << m.value_ << '\n';  // Ausgabe: 14
}

Godbolt Listing lst-1027-godb.cpp, https://godbolt.org/z/38qMMWoz6:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/38qMMWoz6 
#include <mutex> // recursive_mutex
#include <iostream>
struct MulDiv {
    std::recursive_mutex mx_;
    int value_;
    explicit MulDiv(int value) : value_{value} {}
    void mul(int x) {
        std::lock_guard lk1(mx_);  // innen
        value_ *= x;
    }
    void div(int x) {
        std::lock_guard lk2(mx_);  // innen
        value_ /= x;
    }
    void muldiv(int x, int y){
        std::lock_guard lk3(mx_);  // außen
        mul(x);
        div(y);
    }
};
int main() {
   MulDiv m{42}; // 3*7*2 *5
   m.muldiv(5, 15);
   std::cout << m.value_ << '\n';  // Ausgabe: 14
}

Listing 29.28: Speicher nur für den aktuellen Thread

Book listing lst-1028-book.cpp:

// https://godbolt.org/z/1j8W7GjTf 
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
thread_local unsigned int usage = 0;
static std::mutex cout_mutex;
void use(const std::string thread_name) {
    ++usage;
    std::lock_guard lock(cout_mutex); // Ausgabe schützen
    std::cout << thread_name << ": " << usage << '\n';
}
int main() {
    std::jthread a{use, "a"}, b{use, "b"};
    use("main");
}

Godbolt Listing lst-1028-godb.cpp, https://godbolt.org/z/1j8W7GjTf:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/1j8W7GjTf 
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
thread_local unsigned int usage = 0;
static std::mutex cout_mutex;
void use(const std::string thread_name) {
    ++usage;
    std::lock_guard lock(cout_mutex); // Ausgabe schützen
    std::cout << thread_name << ": " << usage << '\n';
}
int main() {
    std::jthread a{use, "a"}, b{use, "b"};
    use("main");
}

Listing 29.29: Zwei Threads kommunizieren über eine Bedingungsvariable.

Book listing lst-1030-book.cpp:

// https://godbolt.org/z/af6jK9dKo 
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <deque>
#include <iostream>
#include <syncstream>   // osyncstream
std::deque<int> g_data{};          // Datenaustausch zwischen Threads
std::condition_variable g_condvar; // benachrichtigen
std::mutex g_mx;                   // schützt g_data während Veränderungen
void produziere(int limit) {
  std::vector prims{2};          // bisherige Prims als Prüfteiler
  for(int kandidat=3; kandidat < limit; kandidat+=2) {
    for(int teiler : prims) {
      if(teiler*teiler > kandidat) {          // kandidat ist prim
        std::lock_guard lk{g_mx};             // data schützen
        g_data.push_back(kandidat);           // füllen
        g_condvar.notify_one();               // benachrichtigen
        prims.push_back(kandidat);            // für interne Berechnungen
        break; // nächster Prim-Kandidat
      } else if(kandidat % teiler == 0) {     // nicht prim
        break;                                // nächster Prim-Kandidat
      } else {
        // nächster Prüfteiler
      }
    }
  }
  // ganze Arbeit fertig mitteilen
  std::lock_guard lk{g_mx};          // data schützen
  g_data.push_back(0);               // mit Endemarkierung füllen
  g_condvar.notify_all();            // benachrichtigen
}
void konsumiere(char l, char r) {
  while(true) {                      // für immer
    std::unique_lock lk{g_mx};
    g_condvar.wait(lk, []{ return !g_data.empty();});
    int prim = g_data.front();       // Daten holen
    if(prim == 0) return;            // fertig; 0 drin lassen für andere Konsumenten
    g_data.pop_front();
    lk.unlock();                     // Sperre freigeben
    std::osyncstream osync{std::cout};  // Ausgabe synchronisieren
    osync << l << prim << r <<' ';
  }
}
int main() {
  // ein Produzent:
  std::jthread thProd{produziere, 1'000};
  // drei Konsumenten
  std::jthread thKon1{konsumiere, '[', ']' };
  std::jthread thKon2{konsumiere, '<', '>' };
  std::jthread thKon3{konsumiere, '{', '}' };
  // warten und beenden
  thProd.join();
  thKon1.join(); thKon2.join(); thKon3.join();
  std::cout << '\n';
}

Godbolt Listing lst-1030-godb.cpp, https://godbolt.org/z/af6jK9dKo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/af6jK9dKo 
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <deque>
#include <iostream>
#include <syncstream>   // osyncstream
std::deque<int> g_data{};          // Datenaustausch zwischen Threads
std::condition_variable g_condvar; // benachrichtigen
std::mutex g_mx;                   // schützt g_data während Veränderungen
void produziere(int limit) {
  std::vector prims{2};          // bisherige Prims als Prüfteiler
  for(int kandidat=3; kandidat < limit; kandidat+=2) {
    for(int teiler : prims) {
      if(teiler*teiler > kandidat) {          // kandidat ist prim
        std::lock_guard lk{g_mx};             // data schützen
        g_data.push_back(kandidat);           // füllen
        g_condvar.notify_one();               // benachrichtigen
        prims.push_back(kandidat);            // für interne Berechnungen
        break; // nächster Prim-Kandidat
      } else if(kandidat % teiler == 0) {     // nicht prim
        break;                                // nächster Prim-Kandidat
      } else {
        // nächster Prüfteiler
      }
    }
  }
  // ganze Arbeit fertig mitteilen
  std::lock_guard lk{g_mx};          // data schützen
  g_data.push_back(0);               // mit Endemarkierung füllen
  g_condvar.notify_all();            // benachrichtigen
}
void konsumiere(char l, char r) {
  while(true) {                      // für immer
    std::unique_lock lk{g_mx};
    g_condvar.wait(lk, []{ return !g_data.empty();});
    int prim = g_data.front();       // Daten holen
    if(prim == 0) return;            // fertig; 0 drin lassen für andere Konsumenten
    g_data.pop_front();
    lk.unlock();                     // Sperre freigeben
    std::osyncstream osync{std::cout};  // Ausgabe synchronisieren
    osync << l << prim << r <<' ';
  }
}
int main() {
  // ein Produzent:
  std::jthread thProd{produziere, 1'000};
  // drei Konsumenten
  std::jthread thKon1{konsumiere, '[', ']' };
  std::jthread thKon2{konsumiere, '<', '>' };
  std::jthread thKon3{konsumiere, '{', '}' };
  // warten und beenden
  thProd.join();
  thKon1.join(); thKon2.join(); thKon3.join();
  std::cout << '\n';
}

Listing 29.30: »async« kann einfach asynchrone Berechnungen anstoßen.

Book listing lst-1035-book.cpp:

// https://godbolt.org/z/Gh9Y5srd7 
#include <iostream>
#include <future>  // async
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    auto f40 = std::async(fib, 40);
    auto f41 = std::async(fib, 41);
    auto f42 = std::async(fib, 42);
    auto f43 = std::async(fib, 43);
    /* ... an dieser Stelle können weitere Berechnungen stehen ... */
    cout << "fib(40): " << f40.get() << endl; // Ausgabe: fib(40): 102334155
    cout << "fib(41): " << f41.get() << endl; // Ausgabe: fib(41): 165580141
    cout << "fib(42): " << f42.get() << endl; // Ausgabe: fib(42): 267914296
    cout << "fib(43): " << f43.get() << endl; // Ausgabe: fib(43): 433494437
}

Godbolt Listing lst-1035-godb.cpp, https://godbolt.org/z/Gh9Y5srd7:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Gh9Y5srd7 
#include <iostream>
#include <future>  // async
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    auto f40 = std::async(fib, 40);
    auto f41 = std::async(fib, 41);
    auto f42 = std::async(fib, 42);
    auto f43 = std::async(fib, 43);
    /* ... an dieser Stelle können weitere Berechnungen stehen ... */
    cout << "fib(40): " << f40.get() << endl; // Ausgabe: fib(40): 102334155
    cout << "fib(41): " << f41.get() << endl; // Ausgabe: fib(41): 165580141
    cout << "fib(42): " << f42.get() << endl; // Ausgabe: fib(42): 267914296
    cout << "fib(43): " << f43.get() << endl; // Ausgabe: fib(43): 433494437
}

Listing 29.31: Es ist in Ordnung, ein Ergebnis nicht abzuholen.

Book listing lst-1036-book.cpp:

// https://godbolt.org/z/7Mea1Y3Mn 
#include <iostream>
#include <future>  // async
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    auto f40 = std::async(fib, 40);
    auto f41 = std::async(fib, 41);
    auto f42 = std::async(fib, 42);
    auto f43 = std::async(fib, 43);
    cout << "fib(40): " << f40.get() << endl; // Ausgabe: fib(40): 102334155
} // wartet auch auf f41, f42 und f43.

Godbolt Listing lst-1036-godb.cpp, https://godbolt.org/z/7Mea1Y3Mn:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/7Mea1Y3Mn 
#include <iostream>
#include <future>  // async
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }

int main() {
    auto f40 = std::async(fib, 40);
    auto f41 = std::async(fib, 41);
    auto f42 = std::async(fib, 42);
    auto f43 = std::async(fib, 43);
    cout << "fib(40): " << f40.get() << endl; // Ausgabe: fib(40): 102334155
} // wartet auch auf f41, f42 und f43.

Listing 29.32: So erzwingen Sie die verzögerte Ausführung.

Book listing lst-1037-book.cpp:

// https://godbolt.org/z/P9MjGe6Mn 
#include <iostream>
#include <future>  // async
#include <vector>
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
int main() {
    // Aufgaben vorbereiten
    std::vector< std::future<long> > fibs;
    for(int n=0; n<50; ++n) {
        auto fut = std::async(std::launch::deferred, fib, n);
        fibs.push_back( std::move(fut) );
    }
    // nur das benötigte Ergebnis abholen
    cout << "fib(42): " << fibs[42].get() << endl; // Ausgabe: fib(42): 267914296
}

Godbolt Listing lst-1037-godb.cpp, https://godbolt.org/z/P9MjGe6Mn:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/P9MjGe6Mn 
#include <iostream>
#include <future>  // async
#include <vector>
using std::cout; using std::endl;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
int main() {
    // Aufgaben vorbereiten
    std::vector< std::future<long> > fibs;
    for(int n=0; n<50; ++n) {
        auto fut = std::async(std::launch::deferred, fib, n);
        fibs.push_back( std::move(fut) );
    }
    // nur das benötigte Ergebnis abholen
    cout << "fib(42): " << fibs[42].get() << endl; // Ausgabe: fib(42): 267914296
}

Listing 29.33: Warten für eine gewisse Zeit bei »async«

Book listing lst-1038-book.cpp:

// https://godbolt.org/z/o9oYrvMcj 
#include <iostream>
#include <future>  // async
#include <chrono>
using std::cout; using std::endl; using namespace std::chrono;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
int main() {
    auto f43 = std::async(fib, 43);
    while(true) {
        auto fertig = f43.wait_for(500ms);
        if(fertig==std::future_status::timeout) {
            std::cout << "noch nicht..." << std::endl;
        } else {
            break;
        }
    }
    // abholen, ist sofort da
    cout << "fib(43): " << f43.get() << endl; // Ausgabe: fib(43): 701408733
}

Godbolt Listing lst-1038-godb.cpp, https://godbolt.org/z/o9oYrvMcj:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/o9oYrvMcj 
#include <iostream>
#include <future>  // async
#include <chrono>
using std::cout; using std::endl; using namespace std::chrono;
long fib(long n) { return n<=1 ? n : fib(n-1)+fib(n-2); }
int main() {
    auto f43 = std::async(fib, 43);
    while(true) {
        auto fertig = f43.wait_for(500ms);
        if(fertig==std::future_status::timeout) {
            std::cout << "noch nicht..." << std::endl;
        } else {
            break;
        }
    }
    // abholen, ist sofort da
    cout << "fib(43): " << f43.get() << endl; // Ausgabe: fib(43): 701408733
}

Listing 29.34: Warten auf einen Lock mit einem »timed_mutex«

Book listing lst-1039-book.cpp:

// https://godbolt.org/z/xzY8hj9oP 
#include <chrono>
#include <future>
#include <mutex>
#include <vector>
#include <iostream>
std::timed_mutex mtx;
long fibX(long n) { return n < 2L ? 1L : fibX(n-1L) + fibX(n-2L); }
long fibCall(long n) {
    using namespace std::chrono; // Suffixe
    if(mtx.try_lock_for(1000ms)) {
        auto res = fibX(n);
        mtx.unlock();
        return res;
    } else {
        return 0L;
    }
}

int main() {
    std::vector< std::future<long> > fs;
    for(long n=1; n<= 42; ++n) {
        fs.emplace_back( std::async(std::launch::async, fibCall, n) );
    }
    for(auto &f : fs) {
        std::cout << f.get() << " ";
    }
    std::cout << std::endl;
}

Godbolt Listing lst-1039-godb.cpp, https://godbolt.org/z/xzY8hj9oP:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/xzY8hj9oP 
#include <chrono>
#include <future>
#include <mutex>
#include <vector>
#include <iostream>
std::timed_mutex mtx;
long fibX(long n) { return n < 2L ? 1L : fibX(n-1L) + fibX(n-2L); }
long fibCall(long n) {
    using namespace std::chrono; // Suffixe
    if(mtx.try_lock_for(1000ms)) {
        auto res = fibX(n);
        mtx.unlock();
        return res;
    } else {
        return 0L;
    }
}

int main() {
    std::vector< std::future<long> > fs;
    for(long n=1; n<= 42; ++n) {
        fs.emplace_back( std::async(std::launch::async, fibCall, n) );
    }
    for(auto &f : fs) {
        std::cout << f.get() << " ";
    }
    std::cout << std::endl;
}

Listing 29.35: Exceptions kommen erst bei »get« beim äußeren Thread an.

Book listing lst-1040-book.cpp:

// https://godbolt.org/z/Pj63xfn7x 
#include <future> // async
#include <vector>
#include <algorithm> // max
#include <iostream>

int berechneHoehe(int count, int maxCount, int scale) {
  if(maxCount == 0)
      throw std::logic_error("Alle Hoehen 0");
  return (count * scale) / maxCount;
}

void balken(const std::vector<int> &counts) {
  // Berechnung starten
  auto maxCount = *std::max_element(counts.begin(), counts.end());
  std::vector< std::future<int> > futs;
  for(int count : counts) {
    futs.push_back(
          std::async(std::launch::async,
              berechneHoehe, count, maxCount, 200) );
  }

  // Ergebnisse einsammeln
  for(auto &fut : futs) {
    std::cout << fut.get() << ' ';                // löst Exception aus
  }
  std::cout << '\n';
}

int main() {
  try {
    balken(std::vector {10,23,13,0,33,4 });       // Ausgabe: 60 139 78 0 200 24
    balken(std::vector { 0, 0, 0, 0 });           // löst Exception aus
  } catch(std::exception &ex) {
    std::cout << "Fehler: " << ex.what() << '\n'; // Ausgabe: Fehler: Alle Hoehen 0
  }
}

Godbolt Listing lst-1040-godb.cpp, https://godbolt.org/z/Pj63xfn7x:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Pj63xfn7x 
#include <future> // async
#include <vector>
#include <algorithm> // max
#include <iostream>

int berechneHoehe(int count, int maxCount, int scale) {
  if(maxCount == 0)
      throw std::logic_error("Alle Hoehen 0");
  return (count * scale) / maxCount;
}

void balken(const std::vector<int> &counts) {
  // Berechnung starten
  auto maxCount = *std::max_element(counts.begin(), counts.end());
  std::vector< std::future<int> > futs;
  for(int count : counts) {
    futs.push_back(
          std::async(std::launch::async,
              berechneHoehe, count, maxCount, 200) );
  }

  // Ergebnisse einsammeln
  for(auto &fut : futs) {
    std::cout << fut.get() << ' ';                // löst Exception aus
  }
  std::cout << '\n';
}

int main() {
  try {
    balken(std::vector {10,23,13,0,33,4 });       // Ausgabe: 60 139 78 0 200 24
    balken(std::vector { 0, 0, 0, 0 });           // löst Exception aus
  } catch(std::exception &ex) {
    std::cout << "Fehler: " << ex.what() << '\n'; // Ausgabe: Fehler: Alle Hoehen 0
  }
}

Listing 29.36: Nur das »get« muss in »try« gekapselt werden.

Book listing lst-1041-book.cpp:

// https://godbolt.org/z/ndc4f8T3P 
#include <future> // async
#include <iostream>

int berechneHoehe(int count, int maxCount, int scale) {
  if(maxCount == 0)
      throw std::logic_error("maxCount ist 0");
  return (count * scale) / maxCount;
}

int main() {
  auto fut = std::async(std::launch::async, berechneHoehe, 0, 0, 200); //                 (ERR)  wirft
  try {
    std::cout << fut.get() << '\n';               // löst Exception aus
  } catch(std::exception &ex) {
    std::cout << "Fehler: " << ex.what() << '\n'; // Ausgabe: Fehler: maxCount ist 0
  }
}

Godbolt Listing lst-1041-godb.cpp, https://godbolt.org/z/ndc4f8T3P:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/ndc4f8T3P 
#include <future> // async
#include <iostream>

int berechneHoehe(int count, int maxCount, int scale) {
  if(maxCount == 0)
      throw std::logic_error("maxCount ist 0");
  return (count * scale) / maxCount;
}

int main() {
  auto fut = std::async(std::launch::async, berechneHoehe, 0, 0, 200); //                 (ERR)  wirft
  try {
    std::cout << fut.get() << '\n';               // löst Exception aus
  } catch(std::exception &ex) {
    std::cout << "Fehler: " << ex.what() << '\n'; // Ausgabe: Fehler: maxCount ist 0
  }
}

Listing 29.37: »future« und »promise« arbeiten zusammen.

Book listing lst-1043-book.cpp:

// https://godbolt.org/z/9Ys4s5qjs 
#include <future>
#include <thread>
#include <iostream>
#include <exception>
int ack(int m, int n); // Ackermannfunktion
void langeBerechnung(std::promise<int> intPromise) {
  try {
    int result = ack(3,12);
    intPromise.set_value(result);                        // Ergebnis mitteilen
  } catch (std::exception &e) {
    intPromise.set_exception(make_exception_ptr(e));     // Exception mitteilen
  } catch ( ... ) {
    intPromise.set_exception(std::current_exception());  // Exc. ohne Namen
  }
}
int main () {
  std::promise<int> intPromise;                          // Promise erzeugen
  std::future<int> intFuture = intPromise.get_future();  // Future anfordern
  std::jthread th{ langeBerechnung,                      // starten
             std::move(intPromise) };                    // Promise übergeben
  th.detach();                                           // weiterlaufen lassen
  // könnte eine Exception werfen:
  int result = intFuture.get();                          // Ergebnis anfordern
  std::cout << result << std::endl;
}

Godbolt Listing lst-1043-godb.cpp, https://godbolt.org/z/9Ys4s5qjs:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9Ys4s5qjs 
#include <future>
#include <thread>
#include <iostream>
#include <exception>
int ack(int m, int n); // Ackermannfunktion
void langeBerechnung(std::promise<int> intPromise) {
  try {
    int result = ack(3,12);
    intPromise.set_value(result);                        // Ergebnis mitteilen
  } catch (std::exception &e) {
    intPromise.set_exception(make_exception_ptr(e));     // Exception mitteilen
  } catch ( ... ) {
    intPromise.set_exception(std::current_exception());  // Exc. ohne Namen
  }
}
int main () {
  std::promise<int> intPromise;                          // Promise erzeugen
  std::future<int> intFuture = intPromise.get_future();  // Future anfordern
  std::jthread th{ langeBerechnung,                      // starten
             std::move(intPromise) };                    // Promise übergeben
  th.detach();                                           // weiterlaufen lassen
  // könnte eine Exception werfen:
  int result = intFuture.get();                          // Ergebnis anfordern
  std::cout << result << std::endl;
}

Listing 29.38: Packaged Task vorbereiten für die spätere Ausführung

Book listing lst-1044-book.cpp:

// https://godbolt.org/z/9s94nbrx3 
#include <future>
#include <thread>
#include <iostream>
int ack(int m, int n); // Ackermannfunktion
int main () {
    std::packaged_task<int(void)> task1 {          // Signatur der Restfunktion
    []{ return ack(3,11);}  };                     // ack(3,11) vorbereiten
  auto f1 = task1.get_future();                    // Kommunikationskanal
  std::jthread th1 { move(task1) };                // in neuen Thread
  std::cout << "  ack(3,11):" << f1.get()          // Ergebnis abholen
      << '\n';                                     // Ausgabe: ack(3,11):16381
}

Godbolt Listing lst-1044-godb.cpp, https://godbolt.org/z/9s94nbrx3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9s94nbrx3 
#include <future>
#include <thread>
#include <iostream>
int ack(int m, int n); // Ackermannfunktion
int main () {
    std::packaged_task<int(void)> task1 {          // Signatur der Restfunktion
    []{ return ack(3,11);}  };                     // ack(3,11) vorbereiten
  auto f1 = task1.get_future();                    // Kommunikationskanal
  std::jthread th1 { move(task1) };                // in neuen Thread
  std::cout << "  ack(3,11):" << f1.get()          // Ergebnis abholen
      << '\n';                                     // Ausgabe: ack(3,11):16381
}

Listing 29.39: Packaged Task erst später mit Argumenten versorgen

Book listing lst-1045-book.cpp:

// https://godbolt.org/z/bq1hn5rjo 
#include <future>
#include <thread>
#include <iostream>
int ack(int m, int n); // Ackermannfunktion
int main () {
  std::packaged_task<int(int,int)> task2 { &ack }; // andere Signatur
  auto f2 = task2.get_future();
  std::jthread th2 { move(task2), 3, 12 };         // Parameter hier
  std::cout << "  ack(3,12):" << f2.get() << '\n'; // Ausgabe: ack(3,12):32765
  th2.join();
}

Godbolt Listing lst-1045-godb.cpp, https://godbolt.org/z/bq1hn5rjo:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/bq1hn5rjo 
#include <future>
#include <thread>
#include <iostream>
int ack(int m, int n); // Ackermannfunktion
int main () {
  std::packaged_task<int(int,int)> task2 { &ack }; // andere Signatur
  auto f2 = task2.get_future();
  std::jthread th2 { move(task2), 3, 12 };         // Parameter hier
  std::cout << "  ack(3,12):" << f2.get() << '\n'; // Ausgabe: ack(3,12):32765
  th2.join();
}

Listing 29.40: So finden Sie heraus, ob die Operationen sperrfrei sind.

Book listing lst-1046-book.cpp:

// https://godbolt.org/z/3Y5WP6qWM 
#include <iostream>
#include <atomic>

struct CArray { int a[100]; };
struct Einfach { int x, y; };

int main() {
    std::atomic<CArray> carray{};
    std::cout << (carray.is_lock_free() ? "sperrfrei" : "sperrt")
        << '\n';                                        // Ausgabe: sperrt
    std::atomic<Einfach> einfach{};
    std::cout << (einfach.is_lock_free() ? "sperrfrei" : "sperrt")
        << '\n';                                        // Ausgabe: sperrfrei
}

Godbolt Listing lst-1046-godb.cpp, https://godbolt.org/z/3Y5WP6qWM:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/3Y5WP6qWM 
#include <iostream>
#include <atomic>

struct CArray { int a[100]; };
struct Einfach { int x, y; };

int main() {
    std::atomic<CArray> carray{};
    std::cout << (carray.is_lock_free() ? "sperrfrei" : "sperrt")
        << '\n';                                        // Ausgabe: sperrt
    std::atomic<Einfach> einfach{};
    std::cout << (einfach.is_lock_free() ? "sperrfrei" : "sperrt")
        << '\n';                                        // Ausgabe: sperrfrei
}

Listing 29.41: Die Klasse »SpinlockMutex« verhindert das Schlafenlegen beim Warten.

Book listing lst-1047-book.cpp:

// https://godbolt.org/z/W47YTYcEb 
#include <atomic>
class SpinlockMutex {
  std::atomic_flag flag_;
public:
  SpinlockMutex()
  : flag_{ATOMIC_FLAG_INIT}
  {}
  void lock() {                                 // z. B. von lock_guard aufgerufen
    while(flag_.test_and_set(std::memory_order_acquire)) // hauptsächlich lesen
      { /* nothing */ }
  }
  void unlock() {
    flag_.clear(std::memory_order_release);              // Schreiboperation
  }
};

Godbolt Listing lst-1047-godb.cpp, https://godbolt.org/z/W47YTYcEb:

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/W47YTYcEb 
#include <atomic>
class SpinlockMutex {
  std::atomic_flag flag_;
public:
  SpinlockMutex()
  : flag_{ATOMIC_FLAG_INIT}
  {}
  void lock() {                                 // z. B. von lock_guard aufgerufen
    while(flag_.test_and_set(std::memory_order_acquire)) // hauptsächlich lesen
      { /* nothing */ }
  }
  void unlock() {
    flag_.clear(std::memory_order_release);              // Schreiboperation
  }
};

Listing 29.42: Ihre Koroutine liefert einen »generator« zurück.

Book listing lst-1048-book.cpp:

// https://godbolt.org/z/Gfazq6GE7 
#include <generator>
#include <iostream>
#include <vector>

std::generator<int> fib(int n) { // generiert int-Werte
  int a = 0, b = 1;
  while (--n) {
    co_yield b;                  // macht diese Funktion zu einer Koroutine
    auto tmp = a;
    a = b;
    b += tmp;
  }
}
int main() {
  for (auto i : fib(10)) std::cout << i << ' ';
  std::cout << '\n';             // Ausgabe: 1 1 2 3 5 8 13 21 34 55
}

Godbolt Listing lst-1048-godb.cpp, https://godbolt.org/z/Gfazq6GE7:

//#(compile) c++; compiler:gsnapshot; options:"-std=c++23"; libs:-
// https://godbolt.org/z/Gfazq6GE7 
#include <generator>
#include <iostream>
#include <vector>

std::generator<int> fib(int n) { // generiert int-Werte
  int a = 0, b = 1;
  while (--n) {
    co_yield b;                  // macht diese Funktion zu einer Koroutine
    auto tmp = a;
    a = b;
    b += tmp;
  }
}
int main() {
  for (auto i : fib(10)) std::cout << i << ' ';
  std::cout << '\n';             // Ausgabe: 1 1 2 3 5 8 13 21 34 55
}

Listing 29.43: Ein einfaches Beispiel für einen Koroutinen-Rückgabetyp mit seinem »promise_type«

Book listing lst-1049-book.cpp:

// 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
  }
}

Godbolt Listing lst-1049-godb.cpp, https://godbolt.org/z/4ed3oWK7q:

//#(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
  }
}

GodboltId:veEq4dcET

Book listing lst-1052-book.cpp:

// https://godbolt.org/z/veEq4dcET 
struct Tag {
    Tag(int a, int b) : Tag{} {       // delegiert
        if(a==0 || b == 0)
            throw 666;                // löst Ausnahme aus
    }
    Tag() {}
};
int main() {
    try {
        Tag tag{1,2};
    } catch(int) { }
}

Godbolt Listing lst-1052-godb.cpp, https://godbolt.org/z/veEq4dcET:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/veEq4dcET 
struct Tag {
    Tag(int a, int b) : Tag{} {       // delegiert
        if(a==0 || b == 0)
            throw 666;                // löst Ausnahme aus
    }
    Tag() {}
};
int main() {
    try {
        Tag tag{1,2};
    } catch(int) { }
}

GodboltId:Y8KK3nEG3

Book listing lst-1057-book.cpp:

// https://godbolt.org/z/Y8KK3nEG3
void sortData(std::ranges::random_access_range auto &&data) {
    std::ranges::sort(data);
}

Godbolt Listing lst-1057-godb.cpp, https://godbolt.org/z/Y8KK3nEG3:

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Y8KK3nEG3
void sortData(std::ranges::random_access_range auto &&data) {
    std::ranges::sort(data);
}

Okt 23, 2024

lst-0017-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/eWfGbv1dG 
#          include <iostream>        // # muss am Zeilenanfang stehen
int             main(
    ){
    std::cout
<<"Dies ist "
        "Text mit <Klammern>\n"   // String-Literal unterbrochen durch neue Zeile
        ;
    /*Typ:*/ int
    /*Variable:*/ ein_Wert
    /*Init:*/ = 100;               // innere Kommentare
std::cout<<ein_Wert<<"\n";}       // keine Leerzeichen

Okt 23, 2024

lst-0008-book.cpp

// https://godbolt.org/z/Mdj7bGvar 
#include <iostream>                         // Module/Bibliotheken einbinden
int main()                                  // main() ist der Beginn des Programms
{
    int wert = 100;                         // Variable mit Anfangswert
    std::cout << "Teiler von " << wert << " sind:\n";    // Ausgabe von Text
    for(int teiler=1; teiler <= wert; teiler = teiler+1) // Schleife von 1 bis 100
    {                                       // hier beginnt der Wiederholungsteil
        if(wert % teiler == 0)              // Test für eine bedingte Ausführung
            std::cout << teiler << ", ";    // nur bei positivem Test
    }                                       // Ende der Schleife
    std::cout << "\n";                      // einmalige Ausgabe
    return 0;                               // bedeutet in main() Programmende
}                                           // Ende von main()

Okt 23, 2024

lst-0036-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/9943MfExc 
#include <vector>
class Image {
    std::vector<char> data_;
public:
    void load(const char* filename); // lädt Bilddaten
};
class Screen {
public:
    void show(Image& image);         //                 (ERR)  image sollte const sein
};
void paint(Screen &screen, const Image& image) {
     screen.show(image);
}
int main() {
    Image image {};
    image.load("peter.png");
    Screen screen {};
    paint(screen, image);
}

Okt 23, 2024

Okt 23, 2024

lst-1018-book.cpp

/* Thread 1 */                         /* Thread 2 */
if( ! mxs.isEmpty()) {
                                    if( ! mxs.isEmpty()) {
    const auto value = mxs.top();
                                        const auto value = mxs.top();
    mxs.pop();
    //  mehr Code 
                                        mxs.pop();
                                        //  mehr Code 

Okt 23, 2024

lst-0003-book.cpp

// https://godbolt.org/z/Tbx6qdrfx 
// modern102.cpp : Fibonacci-Konsole
#include <iostream>
#include <map>
int fib(int n) {
    static std::map<int, int> table{};
    table[n] = n<=1 ? n : table[n-2] + table[n-1];
    return table[n];
}
int main() {
    std::cout << "Wie viele Fibonacci-Zahlen? ";
    int n = 0;
    std::cin >> n;
    for (int i = 1; i <= n; ++i)
        std::cout << "fib(" << i << ")=" << fib(i) << "\n";
}

Okt 23, 2024

Okt 23, 2024

lst-0003-godb.cpp

//#(execute) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Tbx6qdrfx 
// modern102.cpp : Fibonacci-Konsole
#include <iostream>
#include <map>
int fib(int n) {
    static std::map<int, int> table{};
    table[n] = n<=1 ? n : table[n-2] + table[n-1];
    return table[n];
}
int main() {
    std::cout << "Wie viele Fibonacci-Zahlen? ";
    int n = 0;
    std::cin >> n;
    for (int i = 1; i <= n; ++i)
        std::cout << "fib(" << i << ")=" << fib(i) << "\n";
}

Okt 23, 2024

lst-0008-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/Mdj7bGvar 
#include <iostream>                         // Module/Bibliotheken einbinden
int main()                                  // main() ist der Beginn des Programms
{
    int wert = 100;                         // Variable mit Anfangswert
    std::cout << "Teiler von " << wert << " sind:\n";    // Ausgabe von Text
    for(int teiler=1; teiler <= wert; teiler = teiler+1) // Schleife von 1 bis 100
    {                                       // hier beginnt der Wiederholungsteil
        if(wert % teiler == 0)              // Test für eine bedingte Ausführung
            std::cout << teiler << ", ";    // nur bei positivem Test
    }                                       // Ende der Schleife
    std::cout << "\n";                      // einmalige Ausgabe
    return 0;                               // bedeutet in main() Programmende
}                                           // Ende von main()

Okt 23, 2024

lst-0022-book.cpp

// https://godbolt.org/z/4Mr6fnaEr 
#include <iostream> // cout
int main() {
    int basis = 2;
    int index = 10;
    int zahl = 3 * (basis + ++index) - 1;  // zuerst wird index erhöht
    std::cout << zahl << '\n';             // Ausgabe: 38
}

Okt 23, 2024

lst-0035-book.cpp

// https://godbolt.org/z/bh1MsPhje 
#include <iostream>
int main() {
    int a = 3;
    int b = 7 + (a = 12) + 6;   // enthält eine Zuweisung
    std::cout << a << std::endl;
}

Okt 23, 2024

lst-0007-book.cpp

// https://godbolt.org/z/Moe5M7sK8 
Data const * data = new Data(5);
data->value = 7;         // dieses const schützt Data
data = new Data(6);      // Zeiger neu zuweisen ist okay
Data * const mehr = new Data(8);
mehr->value = 9;         // jetzt okay
mehr = new Data(10);     // Referenz ist geschützt

Okt 23, 2024

lst-0037-book.cpp

// https://godbolt.org/z/zK9Ke9n48 
#include <iostream>                     // cout
int main(int argc, const char* argv[]) {
    bool mitParametern = argc > 1;      // Vergleichsergebnis zwischengespeichert
    if(mitParametern) {                 // … und verwendet
        std::cout << "Sie haben das Programm mit Parametern aufgerufen.\n";
    }
    return 0;
}

Okt 23, 2024

lst-0036-book.cpp

// https://godbolt.org/z/9943MfExc 
#include <vector>
class Image {
    std::vector<char> data_;
public:
    void load(const char* filename); // lädt Bilddaten
};
class Screen {
public:
    void show(Image& image);         //                 (ERR)  image sollte const sein
};
void paint(Screen &screen, const Image& image) {
     screen.show(image);
}
int main() {
    Image image {};
    image.load("peter.png");
    Screen screen {};
    paint(screen, image);
}

Okt 23, 2024

lst-0878-book.cpp

#include <fstream>
#include <iostream>
using std::cout;
int main() {
    std::ifstream file("data.dat");
    if( !file ) { /* Fehler */ cout << "ERR\n"; return 1; }
    std::ofstream filecopy("backup.dat");
    if( !filecopy ) { /* Fehler */ cout << "ERR\n"; return 1; }
    char ch;
    while(file.get(ch) ) {
        filecopy.put(ch);
    }
}

Okt 23, 2024

Okt 23, 2024

lst-0514-book.cpp

Planet erzeugePlanet(const Event &evt) { // Rückgabe als Wert
    Planet result{"Erde"};               // Stackobjekt
    result.setLocation(evt.getPosition());
    return result;                       // Rückgabe erzeugt (potenziell) Kopie
}

Okt 23, 2024

Okt 23, 2024

Okt 23, 2024

Okt 23, 2024

lst-0528-book.cpp

vector<Zahl*> primZeiger(unsigned long bis) { //             (ERR)  Vektor von Zeigern ist verdächtig
    vector<Zahl> alleZahlen;
    vector<Zahl*> prims{};
    // …
    for(Zahl &z : alleZahlen)
        if(isPrim(z, prims))
            prims.push_back( &z ); // speichere Adresse
    return prims; //             (ERR)  Zeiger auf funktionslokale Objekte
}

Okt 23, 2024

lst-0188-book.cpp

// Auszug
std::vector<int> prims{2};   // vector ist ein Container, bereit für Ranged For
void testeObPrim(int n) {
    /* prims muss aufsteigend sortiert sein */
    for(int teil : prims) {   // bereichsbasierte for-Schleife
        if(teil*teil > n)
            return true;
        if(n%teil==0)
            return false;
    }
    return true;
}
// …

void ausgabePrims() {
    for(int i=1; int prim : prims) {   // bereichsbasierte for-Schleife
        std::cout << i++ << ". Primzahl: " <<prim << " ";
    }
    std::cout << "\n";
}
// …

Okt 23, 2024

lst-0026-book.cpp

for(int teiler=1; teiler <= n; ++teiler)  // for-Schleife
{                                         // Beginn des Schleifenblocks
    if(n % teiler == 0)
        std::cout << teiler << ", ";
}                                         // Ende des Schleifenblocks

Okt 23, 2024

lst-0363-book.cpp

#include <iostream>
#include <chrono> // milliseconds
#include <thread> // this_thread::sleep

struct Pos {
  volatile int x;
  volatile int y;
};
Pos pos{};

// irgendwo anders definiert:
int installMouseDriver(Pos *p);

constexpr auto DELAY = std::chrono::milliseconds(100);
constexpr auto LOOPS = 30; // 30*100ms = 3s
int main() {
    installMouseDriver( &pos );  // MouseDriver aktualisiert x und y
    for(int i=0; i<LOOPS; ++i) {
        std::cout << "maus bei ("<<pos.x<<","<<pos.y<<")\n";
        std::this_thread::sleep_for(DELAY);
    }
}

Okt 23, 2024

lst-0233-book.cpp

struct Person {
    //… Rest wie zuvor 
    string gruss();
};
string Person::gruss() {
    return format("Hallo {} aus {}", this->name_, this->ort_);
}
int main() {
    Person anna { "Anna", 33, "Hof" };
    Person nina { "Nina", 22, "Wyk" };
    anna.gruss();
    nina.gruss();
}

Okt 23, 2024

lst-0461-book.cpp

int main() {
    shared_ptr<Base> obj{ new Derived{} };
    /* ... mehr Programmzeilen hier ... */
} // obj wird korrekt weggeräumt

Okt 23, 2024

Okt 23, 2024

lst-0135-book.cpp

std::vector<int> prims = {2};        // globale Variable
bool testeObPrim(int n) {            // eigene Funktion
    for(int teil : prims) {          // Zugriff auf globale Variable
        if(teil*teil > n)            // Zugriff auf Parameter
            return true;
        if(n%teil==0)
            return false;
    }
    return true;
}
void berechnePrimsBis(int bis) {     // noch eine eigene Funktion
    for(int n=3; n<bis; n=n+2) {
        if(testeObPrim(n)) {         // eigene Funktion verwenden
            prims.push_back(n);
        }
    }
}

Okt 23, 2024

lst-0027-book.cpp

if(argc<=1) {                             // Beginn der if-Anweisung
    std::cout << "Geben Sie eine Zahl ein: ";
    std::cin >> zahl;
    if(!std::cin) {
        return 1;
    }
} else {
    wert = std::stoi(argv[1]);
}                                         // Ende der if-Anweisung

Okt 23, 2024

lst-0102-book.cpp

// https://godbolt/.org/z/bdaE5nf5T 
#include <iostream>
#include <string>
#include <string_view>
void zeige_mitte(std::string_view msg) {     // string_view ist ein guter Parameter
   auto mitte = msg.substr(2, msg.size()-4); // substr liefert string_view zurück
   std::cout << mitte << "\n";
}
int main() {
    using namespace std::literals;
    const std::string aaa = "##Etwas Text##"s;
    zeige_mitte(aaa);                        // Umwandlung in string_view
    auto bbb = "++Mehr Text++"sv;            // string_view als Literal
    zeige_mitte(bbb);
}

Okt 23, 2024

Okt 23, 2024

lst-0240-book.cpp

std::ostream& Person::drucke(std::ostream& os) {
    return os << format("{} ({}) aus {}", name_, alter_,  ort_);
}
std::ostream& operator<<(std::ostream& os, Person p) {
    return p.drucke(os);
}

Okt 23, 2024

Okt 23, 2024

lst-0423-book.cpp

class Mega {
    std::vector<int>     data_;
    KannWerfen           kannWerfen_;
    std::map<string,int> mehr_;
public:
    Mega()
      : data_{}
      , kannWerfen_{666}  // löst eine Exception aus
      , mehr_{}
      { }
};

Okt 23, 2024

lst-0376-book.cpp

class index_impl {
// ...
public: // test interface
    vector<string> _qgramify(string_view n) const { return qgramify(n); }
    static size_t _q() { return Q; }
    static std::string _prefix() { return PREFIX; }
    static std::string _suffix() { return SUFFIX; }
};

Okt 23, 2024

lst-0429-book.cpp

struct MeinWert {
    //  alles andere wie bisher
    MeinWert& operator=(const MeinWert& rechts) {
        if(this != &rechts) { // 1. auf Selbstzuweisung prüfen
            // 2. Freigeben bisheriger Ressourcen; hier keine
            // 3. elementweises Übertragen durch Zuweisung oder Ähnliches
            name_ = rechts.name_ + "-Zuweisung (zuvor " + name_ + ")";
            /* nummer_ bleibt, und damit die originale Einrückung */
        }
        return *this; // 4. sich selbst zurückgeben
    }
};

Okt 23, 2024

lst-0052-book.cpp

#include <iostream>                               // cin, cout, endl
using std::endl;                                  // gilt global in dieser Datei
void berechne(int n) {
    using std::cout;                              // gilt lokal in dieser Funktion
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    for(int teiler=1; teiler <= n; ++teiler) {
        if(n % teiler == 0)
            cout << teiler << ", ";
    }
    cout << endl;
}

Okt 23, 2024

lst-0448-book.cpp

auto operator<=>(const Adresse& re) const {
  array a{strasse, plz, ort};
  array b{re.strasse, re.plz, re.ort};
  return lexicographical_compare_three_way(begin(a), end(a), begin(b), end(b));
}

Okt 23, 2024

lst-0415-book.cpp

Konstruktor mwert1
 Konstruktor temp
  Konstruktor lokal
  Destruktor lokal
 Destruktor temp
   Konstruktor lokal
   Destruktor lokal
    Konstruktor mwert2
    Destruktor mwert2
Destruktor mwert1

Okt 23, 2024

lst-0152-book.cpp

auto func() -> int;
auto func() -> std::string;
auto func() -> void;
auto func() -> std::pair<int,std::string>;
auto func() -> vector<int>;
auto func() -> vector<int>&;
auto func() -> const vector<int>&;

Okt 23, 2024

lst-0162-book.cpp

if(zahl > 50) {                     // äußerer Block
    {                               // 1. innerer Block
        int ergebnis = zahl*zahl;
        std::cout << "Quadrat: " << ergebnis << std::endl;
    }
    {                               // 2. innerer Block
        int ergebnis = zahl+zahl;
        std::cout << "Verdoppelt: " << ergebnis << std::endl;
    }
}

Okt 23, 2024

lst-0213-book.cpp

try {
    cout << zaehleWoerter(filename) << "\n";
} catch(std::exception &exc) {
    cout << "Fehler: " << exc.what() << "\n";
    throw; // weiterwerfen
}

Okt 23, 2024

lst-0248-book.cpp

struct Person {
    string name_;
    int alter_;
    string ort_;
    Person();          // Konstruktor deklarieren
};
Person::Person()
  : name_{"kein Name"} // Initialisierungswert für name_
  , alter_{-1}         // Initialisierungswert für alter_
  , ort_{"kein Ort"}   // Initialisierungswert für ort_
{ }                    // leerer Funktionskörper

Okt 23, 2024

lst-0163-book.cpp

if(zahl > 50) {
    int ergebnis = zahl*zahl;           // Definition von ergebnis
    std::cout << "Quadrat: " << ergebnis << std::endl;
    int ergebnis = zahl+zahl;           //             (ERR)  Fehler: ergebnis wurde schon definiert
    std::cout << "Verdoppelt: " << ergebnis << std::endl;
}

Okt 23, 2024

lst-0160-book.cpp

for(int prim : prims)               // for gefolgt von einer Anweisung
    std::cout << prim << " ";
std::cout << "\n";                  // nicht mehr Teil von for

Okt 23, 2024

lst-0430-book.cpp

struct MeineNummer {

    const int nummer_;         // konstantes Datenfeld

    explicit MeineNummer(int v)
        : nummer_{v}           // Initialisierung des konstanten Datenfelds
        {}
};

int main() {
    MeineNummer c1{4};
    MeineNummer c2{7};
    c1 = c2;                   //             (ERR)  Fehler: Zuweisung vom Compiler gestrichen
}

Okt 23, 2024

lst-0281-book.cpp

// jeweils nur Auszüge
class Year {
    explicit Year(int v) : value_{v} {}
};
class Month {
    explicit Month(int v) : value_{v} {}
};
class Day {
    explicit Day(int v) : value_{v} {}
};
class Date {
    explicit Date(int y) : year_{y} {}
};

Okt 23, 2024

lst-0235-book.cpp

string gruss(Person * const p) {  // impliziter Parameter explizit gemacht
    return format("Hallo {} aus {}", p->name_, p->ort_);
}

Okt 23, 2024

lst-0418-book.cpp

Database::Database(const char* filename)
    : db_{ db_open(filename) }
    {
        if(nullptr == db_) { // Fehler beim Öffnen
            throw IllegalArgumentException("Fehler beim Oeffnen der DB");
        }
    }

Okt 23, 2024

lst-0293-book.cpp

Page page = Html().body()
    .h1("Ueberschrift")
    .table().border(0)
      .tr()
        .td().css("head").text("Hunderasse").end()
        .td().text("Pudel").end()
      .end()
    .end()
    .toPage();

Okt 23, 2024

Okt 23, 2024

lst-0212-book.cpp

void process(const vector<string>& args) {
    if(args.size() == 0) {                 // erwarte Parameter
        throw std::invalid_argument{"Kommandozeilenargument fehlt"};
    } else {
        for(const string filename : args) {
            cout << filename << ": ";
            try {
                cout << zaehleWoerter(filename) << "\n";
            } catch(std::exception &exc) {
                cout << "Fehler: " << exc.what() << "\n";
            }
        }
    }
}

Okt 23, 2024

lst-0051-book.cpp

#include <iostream>
#include <string>
using namespace std; //                 (ERR)  wirkt sich global aus; klappt, ist aber kritisch
void berechne(int n) {
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";
    // …
}
// … auch in weiteren Funktionen …

Okt 23, 2024

Okt 23, 2024

lst-0187-book.cpp

int main() {
    for( ; ; ) {  // kein Init, keine Bedingung, kein Update – also für immer
        /* ... Benutzereingabe */
        /* ... falls Benutzer Quit wählt, Programmende */
        /* ... ansonsten, Berechnung und Ausgabe */
    }
}

Okt 23, 2024

lst-0164-book.cpp

if(zahl > 50) {
    int ergebnis1 = zahl*zahl;          // ein Ergebnis
    std::cout << "Quadrat: " << ergebnis << std::endl;
    int ergebnis2 = zahl+zahl;          // noch ein Ergebnis
    std::cout << "Verdoppelt: " << ergebnis << std::endl;
    int ergebnis3 = zahl+zahl+zahl;     // und noch ein Ergebnis
    //  viele Zeilen Code dazwischen 
    // und hier?
    //  noch mehr Programmzeilen 
}

Okt 23, 2024

lst-0426-book.cpp

void byVal(MeinWert arg) { }
int main() {
    MeinWert wert1{"ABCD"}; // neue Instanz, konstruiert per string
    MeinWert wert2{wert1};  // neue Instanz, konstruiert per Kopie
    MeinWert wert3 = wert1; // neue Instanz, ebenfalls per Kopie, trotz =
    byVal(wert1);           // eine neue Instanz per Kopie
    wert1 = wert2;          // keine neue Instanz, sondern eine Zuweisung
}

Okt 23, 2024

Okt 23, 2024

Okt 23, 2024

lst-0515-book.cpp

// Rückgabe als (smarter) Pointer:
unique_ptr<Planet> erzeugePlanet(const Event &evt) {
    unique_ptr<Planet> result{ new Planet{"Venus"} };  // Heapobjekt
    result->setLocation(evt.getPosition());
    return result; // reicht Adresse weiter
}

Okt 23, 2024

lst-0104-book.cpp

// https://godbolt/.org/z/Gbe7aM4o4 
#include <iostream>                      // cin, cout für Eingabe und Ausgabe
#include <string>
#include <array>
using std::cin; using std::cout;         // Abkürzungen cin und cout
void eingabe(
    std::string &name,
    unsigned &gebTag,
    unsigned &gebMonat,
    unsigned &gebJahr,
    long long &steuernummer,
    std::array<int,12> &monatseinkommen) // array ist ein Container
{
    /* Eingaben noch ohne gute Fehlerbehandlung… */
    cout << "Name: ";
    std::getline(cin, name);   // getline nimmt Eingabestrom und String
    if(name.length() == 0) {
        cout << "Sie haben einen leeren Namen eingegeben.\n";
        exit(1);
    }
    cout << "Geb.-Tag: "; cin >> gebTag;
    cout << "Geb.-Monat: "; cin >> gebMonat;
    cout << "Geb.-Jahr: "; cin >> gebJahr;
    cout << "Steuernummer: "; cin >> steuernummer;
    for(int m=0; m<12; ++m) {
        cout << "Einkommen Monat " << m+1 << ": "; // mehrere Ausgaben
        cin >> monatseinkommen[m];                 // Einlesen mit Operator
    }
    cout << std::endl;
}
int main() {
    std::string name{};
    unsigned tag = 0;
    unsigned monat = 0;
    unsigned jahr = 0;
    long long stNr = 0;
    std::array<int,12> einkommen{};
    eingabe(name, tag, monat, jahr, stNr, einkommen);
    //  Berechnungen 
}

Okt 23, 2024

lst-0174-book.cpp

bis = 99;                     // eine Zuweisung ist ein Ausdruck
bis = bis * 2 + 1;            // Zuweisung mit einer Berechnung verbinden
berechnePrimsBis(bis);        // ein Funktionsaufruf ist ein Ausdruck
std::cout << "Friedrich III"; // der Ausgabeoperator

Okt 23, 2024

lst-0323-book.cpp

Keyboard& getKeyboard() {
    cout << "  getKeyboard()\n";
    static Keyboard keyboard{}; // statische lokale Variable
    return keyboard;
}

Okt 23, 2024

lst-0043-book.cpp

int index = 1;        // alter Stil, sieht wie eine Zuweisung aus
int zaehler { 1 };    // C++11-Stil, eindeutig eine Initialisierung
int counter = { 1 };  // beim C++11-Stil ist das »=« optional und wird ignoriert

Okt 23, 2024

lst-0128-book.cpp

int func();                        // liefert einen int zurück
std::string func();                // eine Zeichenkette aus der Standardbibliothek
void func();                       // kein Rückgabewert
std::pair<int,std::string> func(); // zusammengesetzter Typ aus der Stdlib
vector<int> func();                // liefert einen neuen Container zurück
vector<int>& func();               // Verweis auf anderen Container
const vector<int>& func();         // ebenso, aber Sie können ihn nicht verändern

Okt 23, 2024

lst-0103-book.cpp

// https://godbolt/.org/z/raYaeY357 
// Rufen Sie dieses Programm zum Beispiel mit 'prog.exe > datei.txt' auf.
#include <iostream>  // cout, cerr
int main() {
    std::cout << "Ausgabe nach cout\n";      // wird nach 'datei.txt' ausgegeben
    std::cerr << "Fehlermeldung!\n";         // erscheint trotzdem auf der Konsole
    std::cout << "Wieder normale Ausgabe\n"; // wieder in die Datei
}

Okt 23, 2024

lst-0050-book.cpp

#include <iostream>                            // für std::cin, std::cout, std::endl
#include <string>                              // für std::stoi
void berechne(int n) {
    using namespace std;                       // für std::cout und std::endl
    /* Teiler ausgeben */
    cout << "Teiler von " << n << " sind:\n";  // cout statt std::cout
    for(int teiler=1; teiler <= n; ++teiler) {
        if(n % teiler == 0)
            cout << teiler << ", ";            // cout statt std::cout
    }
    cout << endl;
}

Okt 23, 2024

lst-0402-book.cpp

struct Komponente {
    Color getColor() const { return weiss; }
};
struct Fenster : public Komponente { };
struct Hauptfenster : public Fenster { };
struct Dialog : public Fenster { };
struct Texteingabe : public Komponente { };
struct Druckknopf : public Komponente {
    Color getColor() const  { return grau; }
};

Okt 23, 2024

lst-0136-book.cpp

// … Auszug …
bool testeObPrim(int n);           // Deklaration der später definierten Funktion
void berechnePrimsBis(int bis) {
    for(int n=3; n<bis; n=n+2) {
        if(testeObPrim(n)) {       // Verwendung der später definierten Funktion
            prims.push_back(n);
        }
    }
}
bool testeObPrim(int n) {          // Definition erst nach der Verwendung
    // … wie zuvor …
}

Okt 23, 2024

lst-0315-book.cpp

namespace plant {
    // … wie zuvor …
    std::ostream& operator<<(std::ostream&, const Baum&) {};
    namespace debug {
        std::ostream& operator<<(std::ostream&, const Baum&) {};
    }
}
plant::Baum baum{"MeinBaum"};
void run() {
    using namespace plant;
    cout << baum << "\n";
}
void diagnostic() {
    using namespace plant::debug;
    cout << baum << "\n";
}
int main() {
    run();
    diagnostic();
}

Okt 23, 2024

lst-0165-book.cpp

int main() {  ;;;              // 3 leere Anweisungen
    int zahl = 12 ; ;          // 1 leere Anweisung
    ; int q = zahl*zahl ;      // 1 leere Anweisung
    if(q>50) {
        q = q - 50;
    } ;                        // 1 leere Anweisung
    std::cout << q << std::endl;
}

Okt 23, 2024

Okt 20, 2024

cpp24-listings-README.md

Listings from the book

Okt 20, 2024

Modernes C++ programmieren

Ich bin Torsten T. Will, und ich schreibe hier über C++ Programmierung. Seit 2011 habe ich Artikel über C++ in dem Computer-Fachmagazin c’t veröffentlicht, und seit 2013 habe ich mehrere Bücher zu C++ geschrieben.

Informationen zum aktuellsten Buch der deutschen 🇩🇪 Ausgabe von 2023 finden Sie bei C++ Das umfassende Handbuch (2023).

You can find information about the latest English 🇬🇧🇺🇸 edition from 2024 at C++ The Comprehensive Guide.

Bücher und Artikel zu C++

C++ ist eine moderne Programmiersprache—wenn man sie richtig benutzt. Meine Artikel und Bücher sollen Ihnen dabei helfen, C++ so zu programmieren, dass Sie auch in vielen Jahren noch etwas davon haben—dass Ihr Programm nachhaltig ist.

Aber selbstverständlich spricht nichts dagegen, wenn Sie Ihr Programm “traditionell” schreiben. Das heißt für mich, kurz zusammengefasst, dass Ihr Programm mehr nach C aussieht, als es aussehen könnte. Daran ist nichts falsch, natürlich nicht. Einige der besten Programme sind in C geschrieben. Dennoch, wenn Sie heute ein Projekt beginnen und sich für eine in Maschinencode übersetzte Programmiersprache entscheiden, dann nehmen Sie doch besser C++. Denn in der Sprache tut sich etwas—oder besser gesagt, es hat sich etwas getan. Mit C++11 bis C++23 haben Sie eine Sprache, die Sie auf moderne Art und Weise dabei unterstützt, gute Programme zu schreiben. Das bedeutet, Ihre Programme sind schnell, fehlerresistent und wartbar. Sie können produktiv programmieren.

Ich habe lange überlegt, wie man C++ am besten vermittelt. Bjarne Stroustrup hat auf der C++Con 2017 eine Keynote gehalten, die genau dieses Thema zum Kern hatte. Und er sagte dort Dinge, die, so finde ich, weltbewegend sind. Zumindest, was die C++-Welt angeht. Denn er sagte:

Wir (Lehrende) haben bis C++98 schlechte Arbeit darin geleistet, Menschen C++ beizubringen.

Und er habe sich Gedanken gemacht, warum das so war. Er schließt sich dabei selbst mit ein und resümiert, dass die meisten C++-Bücher lang, eintönig und langsam sind. Sie bringen “bottom-up 1990-C++” bei und verwenden dabei die C++11-Syntax. Und das sei verkehrt. Nun habe ich lange vor dieser Keynote von Bjarne Stroustrup mit dem Schreiben begonnen. Und gerade deshalb fühle ich mich in meiner Art, C++ zu vermitteln, bestätigt. Denn ich sehe das genauso und habe mich von Anfang an bemüht, es anders zu machen.

Mein Ansatz ist, dass, wenn man den Mechanismus versteht, man das Detail mit anderen Dingen kombinieren und Neues erschaffen kann. Ich möchte immer, dass das “Warum” im Vordergrund steht.

Stroustrup sagt in seiner Keynote, dass das neue C++ unter anderem Ressourcensicherheit in den Vordergrund stellt. Er fragt, welches Buch RAII deswegen in den Vordergrund stellt? Es seien wenige. In meinen Artikeln und Büchern wird Ihnen der Begriff RAII mehrmals begegnen. Er kritisiert auch, dass viele Bücher Typsicherheit, Abstraktion, Klassendesign und generische Programmierung nicht einmal erwähnen. Ich tue es.

Übersetzung

Ich übersetze IT-Fachbücher aus dem Englischen ins Deutsche und umgekehrt.

I translate IT technical books from English to German and vice versa. You find an example in C++ The Comprehensive Guide.

Fachgutachten

Seit geraumer Zeit erstelle ich Gutachten für Bücher aus dem IT-Bereich, hauptsächlich zum Thema Programmiersprachen, Softwareentwicklung und der Lehre.