Namespaces
Variants

requires expression (since C++20)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

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

Inhaltsverzeichnis

Syntax

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

Erklärung

Anforderungen können sich auf die Template-Parameter beziehen, die im Gültigkeitsbereich sind, auf die Parameter der parameter-list , und auf alle anderen Deklarationen, die vom umschließenden Kontext aus sichtbar sind.

Die Substitution von Template-Argumenten in einen requires -Ausdruck, der in einer Deklaration einer templated entity verwendet wird, kann zur Bildung ungültiger Typen oder Ausdrücke in seinen Anforderungen oder zur Verletzung semantischer Constraints dieser Anforderungen führen. In solchen Fällen ergibt der requires -Ausdruck false und führt nicht dazu, dass das Programm ill-formed wird. Die Substitution und semantische Constraint-Überprüfung erfolgt in lexikalischer Reihenfolge und stoppt, wenn eine Bedingung angetroffen wird, die das Ergebnis des requires -Ausdrucks bestimmt. Wenn die Substitution (falls vorhanden) und semantische Constraint-Überprüfung erfolgreich sind, ergibt der requires -Ausdruck true .

Wenn für jedes mögliche Template-Argument ein Substitutionsfehler in einem requires -Ausdruck auftreten würde, ist das Programm fehlerhaft, keine Diagnose erforderlich:

template<class T>
concept C = requires
{
    new int[-(int)sizeof(T)]; // ungültig für jedes T: fehlerhaft, keine Diagnose erforderlich
};

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.

Lokale Parameter

Ein requires -Ausdruck kann lokale Parameter mittels einer Parameterliste einführen. Diese Parameter besitzen keine Bindung, Speicherung oder Lebensdauer; sie dienen lediglich als Notation zur Definition von Anforderungen.

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

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

Wenn eine der folgenden Bedingungen erfüllt ist, ist das Programm fehlerhaft:

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

Einfache Anforderungen

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


Eine einfache Anforderung stellt sicher, dass expression gültig ist. expression ist ein unevaluated operand .

template<typename T>
concept Addable = requires (T a, T b)
{
    a + b; // "der Ausdruck „a + b“ ist ein gültiger Ausdruck, der kompiliert wird"
};
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 eine verschachtelte Anforderung interpretiert. Daher kann eine einfache Anforderung nicht mit einem nicht in Klammern gesetzten requires -Ausdruck beginnen.

Typanforderungen

typename Bezeichner ;
identifier - ein (möglicherweise qualifizierter) identifier (einschließlich simple template identifier )


Eine Typanforderung stellt sicher, dass der durch identifier benannte Typ gültig ist: Dies kann verwendet werden, um zu überprüfen, ob ein bestimmter geschachtelter Typ existiert oder ob eine Klassen-/Alias-Templatespezialisierung einen Typ benennt. Eine Typanforderung, die eine Klassentemplatespezialisierung benennt, erfordert nicht, dass der Typ vollständig ist.

template<typename T>
using Ref = T&;
template<typename T>
concept C = requires
{
    typename T::inner; // erforderlicher geschachtelter Member-Name
    typename S<T>;     // erforderliche Klassentemplate-Spezialisierung
    typename Ref<T>;   // erforderliche 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> ist gültig und benennt einen Typ
    { CommonType<T, U>{std::forward<T>(t)} }; 
    { CommonType<T, U>{std::forward<U>(u)} }; 
};

Zusammengesetzte Anforderungen

{ Ausdruck }; (1)
{ Ausdruck } noexcept ; (2)
{ Ausdruck } -> Typ-Einschränkung ; (3)
{ Ausdruck } noexcept -> Typ-Einschränkung ; (4)
expression - ein Ausdruck
type-constraint - eine constraint


Eine zusammengesetzte Anforderung behauptet Eigenschaften eines expression . Substitution und semantische Einschränkungsüberprüfung erfolgen in folgender Reihenfolge:

1) Template-Argumente (falls vorhanden) werden in den Ausdruck eingesetzt.
2) Wenn noexcept vorhanden ist, Ausdruck darf nicht potenziell werfend sein.
3) Wenn type-constraint vorhanden ist, dann:
a) Template-Argumente werden in type-constraint  eingesetzt.
b) decltype ( ( expression  ) ) muss die durch type-constraint  auferlegte Bedingung erfüllen. Andernfalls ist der umschließende requires -Ausdruck false .

expression ist ein unevaluated operand .

template<typename T>
concept C2 = requires(T x)
{
    // Der Ausdruck *x muss gültig sein
    // UND der Typ T::inner muss gültig sein
    // UND das Ergebnis von *x muss in T::inner konvertierbar sein
    {*x} -> std::convertible_to<typename T::inner>;
    // Der Ausdruck x + 1 muss gültig sein
    // UND std::same_as<decltype((x + 1)), int> muss erfüllt sein
    // d.h. (x + 1) muss ein Prvalue vom Typ int sein
    {x + 1} -> std::same_as<int>;
    // Der Ausdruck x * 1 muss gültig sein
    // UND sein Ergebnis muss in T konvertierbar sein
    {x * 1} -> std::convertible_to<T>;
};

Verschachtelte Anforderungen

requires Constraint-Ausdruck ;
constraint-expression - ein Ausdruck, der constraints repräsentiert


Eine geschachtelte Anforderung kann verwendet werden, um zusätzliche Einschränkungen in Bezug auf lokale Parameter zu spezifizieren. constraint-expression muss durch die substituierten Template-Argumente erfüllt werden, falls vorhanden. Die Substitution von Template-Argumenten in eine geschachtelte Anforderung führt nur in dem Umfang zur Substitution in constraint-expression , der notwendig ist, um zu bestimmen, ob constraint-expression erfüllt 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)>; // verschachtelt: "Same<...> ergibt true"
    { a.~T() } noexcept; // zusammengesetzt: "a.~T()" ist ein gültiger Ausdruck, der keine Ausnahme wirft
    requires Same<T*, decltype(new T)>; // verschachtelt: "Same<...> ergibt true"
    requires Same<T*, decltype(new T[n])>; // verschachtelt
    { delete new T }; // zusammengesetzt
    { delete new T[n] }; // zusammengesetzt
};

Hinweis

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

template<typename T>
concept Addable = requires (T x) { x + x; }; // Requires-Ausdruck
template<typename T> requires Addable<T> // Requires-Klausel, kein Requires-Ausdruck
T add(T a, T b) { return a + b; }
template<typename T>
    requires requires (T x) { x + x; } // Ad-hoc-Einschränkung, beachte doppelte Verwendung des Schlüsselworts
T add(T a, T b) { return a + b; }

Schlüsselwörter

requires

Fehlerberichte

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

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
CWG 2560 C++20 es war unklar, ob Parametertypen in requires Ausdrücken angepasst werden ebenfalls angepasst
CWG 2911 C++20 alle Ausdrücke innerhalb von requires
Ausdrücken waren nicht ausgewertete Operanden
nur einige
Ausdrücke sind

Referenzen

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

Siehe auch

Constraints and concepts (C++20) spezifiziert die Anforderungen an Template-Argumente