C++ von den Grundlagen bis zum Profi — Folge 16
Template-Anforderungen mit Concepts und requires ausdrücken
Die Artikel in diesem Blog wurden zu Lehrzwecken verfasst. Sie können Fehler enthalten; prüfen Sie die Aussagen daher mit dem Ziel-Compiler und der verwendeten Standardbibliothek.
Templates wenden eine Regel auf viele Typen an. Ein ungeeigneter Typ erzeugt jedoch oft lange Fehlermeldungen tief in der Implementierung. Concepts und requires aus C++20 machen die Anforderungen bereits in der öffentlichen Deklaration sichtbar.
Das Problem eines unbeschränkten Templates
template <typename T>
int GetHealth(const T& value)
{
return value.Health();
}
Die Funktion funktioniert nur mit Typen, die Health() anbieten. Die Signatur sagt das nicht aus, sodass der Compiler den Fehler erst beim Instanziieren des Funktionskörpers erkennt.
Anforderungen mit einem Concept benennen
#include <concepts>
template <typename T>
concept Damageable = requires(T value, int amount)
{
{ value.Health() } -> std::convertible_to<int>;
{ value.ApplyDamage(amount) } -> std::same_as<void>;
};
template <Damageable T>
void Attack(T& target, int damage)
{
target.ApplyDamage(damage);
}
Ein requires-Ausdruck führt den Code nicht aus, sondern prüft Syntax und Ergebnistypen. Der Vertrag von Attack steht nun vor der Implementierung, und ungültige Aufrufe liefern nähere Diagnosen.
Typeigenschaften kombinieren
template <typename T>
concept SmallId = std::integral<T> && (sizeof(T) <= 4);
template <SmallId T>
void WriteId(T id);
Concepts kombinieren Type Traits und Anforderungen mit logischen Operatoren. Constraints beeinflussen auch die Auswahl von Overloads.
void Print(std::integral auto value);
void Print(std::floating_point auto value);
Ein eingeschränktes auto ist die Kurzform eines Funktionstemplates. Haben Ganzzahlen und Fließkommazahlen unterschiedliche Bedeutungen, sind getrennte Overloads meist klarer als ein großes if constexpr.
Gültige Syntax garantiert keine Semantik
Dass a < b kompiliert, beweist keine konsistente Ordnung. Ebenso garantiert syntaktische Kopierbarkeit keine semantisch unabhängigen Kopien.
Standard-Concepts dokumentieren deshalb auch semantische Anforderungen. Eigene Concepts brauchen aussagekräftige Namen; wichtige Bedeutungen bleiben durch Tests zu prüfen.
Beschränken Sie Templates nicht stärker als nötig. Der kleinste reale Vertrag erhöht die Lesbarkeit, ohne brauchbare Typen grundlos auszuschließen.