Namensräume
Varianten
Aktionen

Funktionsvertragsspezifizierer (seit C++26)

Von cppreference.com
< cpp‎ | language‎ | functions
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

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
1) Vorbedingung
2) Nachbedingung

[bearbeiten] Schlüsselwörter

pre, post

[bearbeiten] Hinweise

Feature-Testmakro Wert Std Feature
__cpp_contracts 202502L (C++26) Verträge

[bearbeiten] Beispiel

  • Die Vorbedingung der Funktion normalize verlangt, dass der Aufrufer einen normalisierbaren Vektor übergibt.
  • Die Nachbedingung stellt sicher, dass die Funktion normalize einen 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[bearbeiten]
contract_assert-Anweisung (C++26) verifiziert eine interne Bedingung während der Ausführung[edit]