namespace cpp

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


kennen:concepts

Concepts

God is a concept by which we measure our pain.
— John Lennon

Generische Lambdas mit auto-Parametern seit C++14

auto show = [](auto x) { std::cout << x << '\n'; }

und generische Funktionen mit auto-Parametern seit C++20

void show(auto x) { std::cout << x << '\n'; } // operator<< vorausgesetzt
auto add(auto x, auto y) { return x + y; } // operator+ erforderlich 

entsprechen Schablonen:

template <typename T> 
void show(T x) { std::cout << x << '\n'; }

Was geschieht, wenn einige Operationen für die Parametertypen nicht definiert sind? Vom Compiler erzeugte Fehlermeldungen sind nicht immer verständlich, besonders wenn Anforderungen erst tief in verschachtelten Schablonen benötigt werden.

Anforderungen

sind Prädikate, die beim Übersetzen ausgewertet werden. Sie beschränken Schablonen

template <typename T> 
  requires std::is_integral_v<T> || std::is_floating_point_v<T> 
T add(T x, T y) { return x+y; }

Die Anforderungen können auch nach der Parameterliste angegeben werden. Mit einem concept als benannte Anforderung

template <typename T> 
concept Number = std::is_integral_v<T> || std::is_floating_point_v<T>;

wird das Beispiel zu

template <typename T> 
  requires Number<T> 
T add(T x, T y) { return x+y; }

Neben der Form mit der requires-Klausel gibt es die "Kurzschrift" und die ganz "knappe Syntax".

Shorthand notation

nutzt concept-Namen statt typename:

template <Number T> 
T add(T x, T y) { return x+y; }

Terse syntax

war sehr umstritten. Daher verpassten Concepts den Einzug in C++17. Sie sind nun Bestandteil von C++20:

Number auto add(Number auto x, Number auto y) { return x+y; }

hat eine etwas andere Bedeutung als im Beispiel oben. Unterschiedliche Parametertypen sind möglich. Jeder Parametertyp ist unabhängig von dem anderen beschränkt. Der Ergebnistyp kann wiederum ein anderer sein, sofern er die Anforderung von Number erfüllt. Jetzt ist es auch möglich, Anforderungen an auto-Variablen zu stellen:

Number auto x = add(1, 2);
Number auto y = add(1, 3.14);
Number auto z = add(1, "3"); // Fehler in add(): char* Parameter ist nicht Number
Number auto s = "Hello"; // Fehler: char* ist nicht Number

Concepts definieren

Anforderungen können logisch verknüpft werden (siehe concept Number oben). Innerhalb eines requires-Ausdrucks sind

  • einfache Anforderungen wie x+y;
  • Typanforderungen wie typename T::value_type; oder
  • zusammengesetzte Anforderungen möglich, die auch den Ergebnistyp einer Operation einschränken:
template<typename T>
concept LessThanComparable = requires(T t) 
{ 
    { t<t } -> std::convertible_to<bool>; 
};

Die Standardbibliothek definiert grundlegende Anforderungen in <concepts>.

kennen/concepts.txt · Zuletzt geändert: 2020-07-12 12:25 von rrichter