Namensräume
Varianten
Aktionen

requires Ausdruck (seit C++20)

Von cppreference.com
< cpp‎ | Sprache
 
 
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
 
 
 
 

Liefert einen prvalue-Ausdruck vom Typ bool, der die Constraints beschreibt.

Inhalt

[bearbeiten] Syntax

requires { requirement-seq } (1)
requires ( parameter-list (optional) ) { requirement-seq } (2)
parameter-liste - eine Parameterliste
requirement-seq - Sequenz von Anforderungen, wobei jede Anforderung eine der folgenden ist

[bearbeiten] Erklärung

Anforderungen können auf Template-Parameter verweisen, die im Gültigkeitsbereich liegen, auf die Parameter von parameter-list und auf alle anderen Deklarationen, die aus dem umgebenden Kontext sichtbar sind.

Die Substitution von Template-Argumenten in einem requires-Ausdruck, der in der Deklaration einer templated entity verwendet wird, kann zur Bildung ungültiger Typen oder Ausdrücke in seinen Anforderungen führen oder zur Verletzung semantischer Constraints dieser Anforderungen. In solchen Fällen wird der requires-Ausdruck zu false ausgewertet und führt nicht dazu, dass das Programm fehlerhaft ist. Die Substitution und die Überprüfung semantischer Constraints erfolgen in lexikalischer Reihenfolge und stoppen, sobald eine Bedingung auftritt, die das Ergebnis des requires-Ausdrucks bestimmt. Wenn die Substitution (falls vorhanden) und die Überprüfung semantischer Constraints erfolgreich sind, wird der requires-Ausdruck zu true ausgewertet.

Wenn bei einem requires-Ausdruck für jedes mögliche Template-Argument eine Substitutionsfehlfunktion auftreten würde, ist das Programm fehlerhaft, keine Diagnose erforderlich.

template<class T>
concept C = requires
{
    new int[-(int)sizeof(T)]; // invalid for every T: ill-formed, no diagnostic required
};

Wenn ein requires-Ausdruck ungültige Typen oder Ausdrücke in seinen Anforderungen enthält und er nicht innerhalb der Deklaration einer templated entity erscheint, dann ist das Programm fehlerhaft.

[bearbeiten] Lokale Parameter

Ein requires-Ausdruck kann lokale Parameter mithilfe einer Parameterliste einführen. Diese Parameter haben keine Verknüpfung, keinen Speicher und keine Lebensdauer; sie werden nur als Notation für die Definition von Anforderungen verwendet.

Der Typ jedes Parameters wird auf die gleiche Weise bestimmt wie die tatsächliche Bestimmung des Typs von Funktionsparametern.

template<typename T>
concept C = requires(T p[2])
{
    (decltype(p))nullptr; // OK, p has type T*
};

Wenn eine der folgenden Bedingungen erfüllt ist, ist das Programm ill-formed (wohlgeformt):

  • Ein lokaler Parameter hat ein Standardargument.
  • Die Parameterliste endet mit einer Ellipse.
template<typename T>
concept C1 = requires(T t = 0)  // Error: t has a default argument
{
    t;
};
 
template<typename T>
concept C2 = requires(T t, ...) // Error: terminates with an ellipsis
{
    t;
};

[bearbeiten] Einfache Anforderungen

expression ;
expression - ein Ausdruck, der nicht mit requires beginnt


Eine einfache Anforderung besagt, dass expression gültig ist. expression ist ein nicht ausgewerteter Operand.

template<typename T>
concept Addable = requires (T a, T b)
{
    a + b; // "the expression “a + b” is a valid expression that will compile"
};
 
template<class T, class U = T>
concept Swappable = requires(T&& t, U&& u)
{
    swap(std::forward<T>(t), std::forward<U>(u));
    swap(std::forward<U>(u), std::forward<T>(t));
};

Eine Anforderung, die mit dem Schlüsselwort requires beginnt, wird immer als verschachtelte Anforderung interpretiert. Daher kann eine einfache Anforderung nicht mit einem nicht geklammerten requires-Ausdruck beginnen.

[bearbeiten] Typanforderungen

typename identifier ;
identifier - ein (möglicherweise qualifizierter) Identifikator (einschließlich einfachem Template-Identifikator)


Eine Typanforderung besagt, dass der vom identifier benannte Typ gültig ist: Dies kann verwendet werden, um zu überprüfen, ob ein bestimmter benannter verschachtelter Typ existiert oder ob eine Klassen-/Alias-Template-Spezialisierung einen Typ benennt. Eine Typanforderung, die eine Klassen-Template-Spezialisierung benennt, erfordert nicht, dass der Typ vollständig ist.

template<typename T>
using Ref = T&;
 
template<typename T>
concept C = requires
{
    typename T::inner; // required nested member name
    typename S<T>;     // required class template specialization
    typename Ref<T>;   // required alias template substitution
};
 
template<class T, class U>
using CommonType = std::common_type_t<T, U>;
 
template<class T, class U>
concept Common = requires (T&& t, U&& u)
{
    typename CommonType<T, U>; // CommonType<T, U> is valid and names a type
    { CommonType<T, U>{std::forward<T>(t)} }; 
    { CommonType<T, U>{std::forward<U>(u)} }; 
};

[bearbeiten] Zusammengesetzte Anforderungen

{ expression }; (1)
{ expression } noexcept ; (2)
{ expression } -> type-constraint ; (3)
{ expression } noexcept -> type-constraint ; (4)
expression - ein Ausdruck
type-constraint - ein Constraint


Eine zusammengesetzte Anforderung besagt Eigenschaften von expression . Substitution und Überprüfung semantischer Constraints erfolgen in folgender Reihenfolge

1) Template-Argumente (falls vorhanden) werden in expression  substituiert.
2) Wenn noexcept vorhanden ist, darf expression nicht potenziell werfen.
3) Wenn type-constraint vorhanden ist, dann
a) Template-Argumente werden in type-constraint  substituiert.
b) decltype((expression )) muss dem durch type-constraint  auferlegten Constraint entsprechen. Andernfalls ist der umschließende requires-Ausdruck false.

expression ist ein nicht ausgewerteter Operand.

template<typename T>
concept C2 = requires(T x)
{
    // the expression *x must be valid
    // AND the type T::inner must be valid
    // AND the result of *x must be convertible to T::inner
    {*x} -> std::convertible_to<typename T::inner>;
 
    // the expression x + 1 must be valid
    // AND std::same_as<decltype((x + 1)), int> must be satisfied
    // i.e., (x + 1) must be a prvalue of type int
    {x + 1} -> std::same_as<int>;
 
    // the expression x * 1 must be valid
    // AND its result must be convertible to T
    {x * 1} -> std::convertible_to<T>;
};

[bearbeiten] Verschachtelte Anforderungen

requires constraint-expression ;
constraint-expression - ein Ausdruck, der Constraints darstellt


Eine verschachtelte Anforderung kann verwendet werden, um zusätzliche Constraints in Bezug auf lokale Parameter anzugeben. constraint-expression muss von den substituierten Template-Argumenten (falls vorhanden) erfüllt werden. Die Substitution von Template-Argumenten in eine verschachtelte Anforderung führt nur so weit zur Substitution in constraint-expression, wie zur Bestimmung, ob constraint-expression erfüllt ist, erforderlich ist.

template<class T>
concept Semiregular = DefaultConstructible<T> &&
    CopyConstructible<T> && CopyAssignable<T> && Destructible<T> &&
requires(T a, std::size_t n)
{  
    requires Same<T*, decltype(&a)>; // nested: "Same<...> evaluates to true"
    { a.~T() } noexcept; // compound: "a.~T()" is a valid expression that doesn't throw
    requires Same<T*, decltype(new T)>; // nested: "Same<...> evaluates to true"
    requires Same<T*, decltype(new T[n])>; // nested
    { delete new T }; // compound
    { delete new T[n] }; // compound
};

[bearbeiten] Hinweis

Das Schlüsselwort requires wird auch verwendet, um requires-Klauseln einzuführen.

template<typename T>
concept Addable = requires (T x) { x + x; }; // requires expression
 
template<typename T> requires Addable<T> // requires clause, not requires expression
T add(T a, T b) { return a + b; }
 
template<typename T>
    requires requires (T x) { x + x; } // ad-hoc constraint, note keyword used twice
T add(T a, T b) { return a + b; }

[bearbeiten] Schlüsselwörter

requires

[bearbeiten] Defect reports

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 2560 C++20 Es war unklar, ob Parameter-Typen in requires-Ausdrücken angepasst werden. auch angepasst
CWG 2911 C++20 alle Ausdrücke, die innerhalb von requires vorkommen
Ausdrücke waren nicht ausgewertete Operanden
nur einige
Ausdrücke sind

[bearbeiten] Referenzen

  • C++23 Standard (ISO/IEC 14882:2024)
  • 7.5.7 Requires expressions [expr.prim.req]
  • C++20 Standard (ISO/IEC 14882:2020)
  • 7.5.7 Requires expressions [expr.prim.req]

[bearbeiten] Siehe auch

Constraints und Konzepte(C++20) spezifiziert die Anforderungen an Template-Argumente[bearbeiten]