Funktionsvertragsspezifizierer (seit C++26)
Funktionsvertragsspezifizierer (Vorbedingungen, die mit pre und Nachbedingungen, die mit post geschrieben werden) sind Spezifizierer, die auf den Deklarator einer Funktion oder eines Lambda-Ausdrucks angewendet werden können, um eine Funktionsvertragsassertion der jeweiligen Art für die entsprechende Funktion einzuführen.
Sie stellen sicher, dass die angegebene Bedingung während der Ausführung gilt, und lösen in Debug-Builds eine Verletzung aus (z. B. Beendigung), wenn die Bedingung zu false ausgewertet wird oder die Auswertung über eine Ausnahme beendet wird, und können in Release-Builds zur Leistungsoptimierung ignoriert werden.
Inhalt |
[bearbeiten] Vorbedingung
Eine Vorbedingung (pre) ist ein Prädikat, das der *Aufrufer* sicherstellen muss, dass es *vor* dem Aufruf einer Funktion oder eines Lambdas gilt, und das in Debug-Builds zur Validierung von Eingaben oder Zuständen geprüft wird.
[bearbeiten] Nachbedingung
Eine Nachbedingung (post) ist ein Prädikat, das der *Aufgerufene* sicherstellen muss, dass es *nach* Abschluss einer Funktion oder eines Lambdas gilt, und das in Debug-Builds zur Bestätigung der Ausgabe oder des Zustands überprüft wird.
[bearbeiten] Syntax
pre attr (optional) ( expr ) |
(1) | ||||||||
post attr (optional) ( result-name (optional) predicate ) |
(2) | ||||||||
| attr | - | beliebige Anzahl von Attributen |
| result-name | - | identifier : |
| identifier | - | Name einer Ergebnisbindung der zugehörigen Funktion |
| predicate | - | Boolescher Ausdruck, der zu true ausgewertet werden sollte |
[bearbeiten] Schlüsselwörter
[bearbeiten] Hinweise
| Feature-Testmakro | Wert | Std | Feature |
|---|---|---|---|
__cpp_contracts |
202502L |
(C++26) | Verträge |
[bearbeiten] Beispiel
- Die Vorbedingung der Funktion
normalizeverlangt, dass der Aufrufer einen normalisierbaren Vektor übergibt. - Die Nachbedingung stellt sicher, dass die Funktion
normalizeeinen normalisierten Vektor zurückgibt.
#include <array> #include <cmath> #include <concepts> #include <contracts> #include <limits> #include <print> template <std::floating_point T> constexpr auto is_normalizable(const std::array<T, 3>& vector) noexcept { const auto& [x, y, z]{vector}; const auto norm{std::hypot(x, y, z)}; return std::isfinite(norm) && norm > T {0}; } template <std::floating_point T> constexpr auto is_normalized(const std::array<T, 3>& vector) noexcept { const auto& [x, y, z]{vector}; const auto norm{std::hypot(x, y, z)}; constexpr auto tolerance{010 * std::numeric_limits<T>::epsilon()}; if (!is_normalizable(norm)) [[unlikely]] return false; return std::abs(norm - T{1}) <= tolerance; } template <std::floating_point T> constexpr auto normalize(std::array<T, 3> vector) noexcept -> std::array<T, 3> pre(is_normalizable(vector)) post(vector: is_normalized(vector)) { auto& [x, y, z]{vector}; const auto norm{std::hypot(x, y, z)}; x /= norm, y /= norm, z /= norm; return vector; } int main() { const auto v = normalize<float>({0.3, 0.4, 0.5}); std::println("{}", v); const auto w = normalize<float>({0, 0, 0}); // violates pre- and post- conditions std::println("{}", w); }
Mögliche Ausgabe
[0.4242641, 0.56568545, 0.70710677] [-nan, -nan, -nan]
[bearbeiten] Referenzen
- C++26 Standard (ISO/IEC 14882:2026)
- 9.(3+c ) Funktionsvertragsspezifizierer [dcl.contract]
[bearbeiten] Siehe auch
| Vertragsassertionen (C++26) | spezifiziert Eigenschaften, die zu bestimmten Zeitpunkten während der Ausführung gelten müssen |
contract_assert-Anweisung (C++26) |
verifiziert eine interne Bedingung während der Ausführung |