Spec-Zone.ru › C++

requires выражение (начиная с C++20)

Даёт выражение категории prvalue типа bool, описывающее ограничения.

Синтаксис

requires { requirement-seq } (1)
requires ( parameter-list (необязательно) ) { requirement-seq } (2)
parameter-list - список параметров
requirement-seq - последовательность требований, каждое из которых является одним из следующих:
  • простое требование
  • требование типа
  • составное требование
  • вложенное требование

Пояснение

Требования могут ссылаться на находящиеся в области видимости параметры шаблона, параметры parameter-list и любые другие объявления, видимые из охватывающего контекста.

Подстановка аргументов шаблона в выражение requires, используемое в объявлении сущности-шаблона, может привести к образованию недопустимых типов или выражений в его требованиях либо к нарушению семантических ограничений этих требований. В таких случаях выражение requires вычисляется в false и не приводит к некорректности программы. Подстановка и проверка семантических ограничений выполняются в лексическом порядке и прекращаются, когда встречается условие, определяющее результат выражения requires. Если подстановка (при наличии) и проверка семантических ограничений завершаются успешно, выражение requires вычисляется в true.

Если подстановка в выражении requires завершается ошибкой для всех возможных аргументов шаблона, программа некорректна, диагностика не требуется:

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

Если выражение requires содержит недопустимые типы или выражения в своих требованиях и не находится в объявлении сущности-шаблона, программа некорректна.

Локальные параметры

Выражение requires может вводить локальные параметры с помощью списка параметров. У этих параметров нет связывания, хранилища или времени жизни; они используются только как обозначения для определения требований.

Тип каждого параметра определяется так же, как при определении фактического типа параметров функции:

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

Если выполняется любое из следующих условий, программа некорректна:

  • У локального параметра есть аргумент по умолчанию.
  • Список параметров завершается многоточием.
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;
};

Простые требования

expression ;
expression - выражение, не начинающееся с requires


Простое требование утверждает, что expression допустимо. expression является невычисляемым операндом.

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));
};

Требование, начинающееся с ключевого слова requires, всегда интерпретируется как вложенное требование. Поэтому простое требование не может начинаться с выражения requires, не заключённого в скобки.

Требования типа

typename type-name ; (1)
typename splice-specifier ; (2) (начиная с C++26)
typename splice-specialization-specifier ; (3) (начиная с C++26)
type-name - (возможно, квалифицированный) идентификатор или простой идентификатор шаблона
splice-specifier - спецификатор splice
splice-specialization-specifier - спецификатор splice, за которым следует, возможно, пустой разделённый запятыми список аргументов шаблона в угловых скобках

Требование типа утверждает, что тип, названный type-name или обозначенный splice-specifier либо splice-specialization-specifier(начиная с C++26), является допустимым: это можно использовать для проверки существования определённого именованного вложенного типа или того, что специализация шаблона класса или псевдонима обозначает тип. Требование типа, именующее специализацию шаблона класса, не требует, чтобы тип был полным.

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)} }; 
};

Составные требования

{ expression }; (1)
{ expression } noexcept ; (2)
{ expression } -> type-constraint ; (3)
{ expression } noexcept -> type-constraint ; (4)
expression - выражение
type-constraint - ограничение


Составное требование утверждает свойства expression . Подстановка и проверка семантических ограничений выполняются в следующем порядке:

1) Аргументы шаблона (если есть) подставляются в expression .
2) Если присутствует noexcept, выражение expression не должно быть потенциально бросающим исключение.
3) Если присутствует type-constraint, то:
a) Аргументы шаблона подставляются в type-constraint .
b) decltype((expression )) должен удовлетворять ограничению, накладываемому type-constraint . В противном случае охватывающее выражение requires становится false.

expression является невычисляемым операндом.

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>;
};

Вложенные требования

requires constraint-expression ;
constraint-expression - выражение, представляющее ограничения


Вложенное требование можно использовать для задания дополнительных ограничений с учётом локальных параметров. constraint-expression должно удовлетворяться подставленными аргументами шаблона, если они есть. Подстановка аргументов шаблона во вложенное требование приводит к подстановке в constraint-expression только в той мере, которая необходима для определения того, удовлетворяется ли constraint-expression.

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
};

Примечание

Ключевое слово requires также используется для введения requires-предложений.

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; }

Ключевые слова

requires

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющие поведение, были ретроактивно применены к ранее опубликованным стандартам C++.

Отчёт об ошибке Применён к Опубликованное поведение Корректное поведение
CWG 2560 C++20 не было ясно, корректируются ли типы параметров в выражениях requires также корректируются
CWG 2911 C++20 все выражения, входящие в выражения requires
, были невычисляемыми операндами
таковыми являются только некоторые
выражения

Ссылки

  • Стандарт C++23 (ISO/IEC 14882:2024):
    • 7.5.7 Выражения requires [expr.prim.req]
  • Стандарт C++20 (ISO/IEC 14882:2020):
    • 7.5.7 Выражения requires [expr.prim.req]

См. также

Ограничения и концепты(C++20) задаёт требования к аргументам шаблона

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/requires

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API