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

제약 조건을 설명하는 bool 타입의 prvalue 표현식을 생성합니다.

목차

구문

requires { requirement-seq } (1)
requires ( parameter-list  (선택 사항) ) { requirement-seq } (2)
parameter-list - a parameter list
requirement-seq - sequence of requirements , each requirement is one of the following:

설명

요구 사항은 현재 범위 내에 있는 템플릿 매개변수, parameter-list 의 매개변수, 그리고 둘러싸는 컨텍스트에서 보이는 다른 선언들을 참조할 수 있습니다.

템플릿 인수를 템플릿화된 엔티티 의 선언에서 사용된 requires 표현식에 대입할 경우, 해당 요구 사항에서 유효하지 않은 타입이나 표현식이 생성되거나 해당 요구 사항의 의미론적 제약 조건을 위반할 수 있습니다. 이러한 경우 requires 표현식은 false 로 평가되며 프로그램이 비정형이 되지 않습니다. 대입 및 의미론적 제약 조건 검사는 어휘 순서로 진행되며 requires 표현식의 결과를 결정하는 조건이 발견되면 중단됩니다. 대입(있는 경우)과 의미론적 제약 조건 검사가 성공하면 requires 표현식은 true 로 평가됩니다.

모든 가능한 템플릿 인자에 대해 requires 표현식에서 치환 실패가 발생한다면, 프로그램은 형식 오류이며 진단이 필요하지 않습니다:

template<class T>
concept C = requires
{
    new int[-(int)sizeof(T)]; // 모든 T에 대해 유효하지 않음: 형식이 잘못됨, 진단이 필요하지 않음
};

만약 requires 표현식이 해당 요구 사항에 유효하지 않은 타입이나 표현식을 포함하고, 템플릿화된 엔티티 의 선언 내에 나타나지 않는 경우, 프로그램은 형식에 맞지 않습니다.

로컬 매개변수

A requires 표현식은 매개변수 목록 을 사용하여 지역 매개변수를 도입할 수 있습니다. 이러한 매개변수는 연결성, 저장 공간, 수명을 가지지 않으며 요구 사항을 정의하기 위한 표기법으로만 사용됩니다.

각 매개변수의 타입은 함수 매개변수의 실제 타입을 결정하는 방식과 동일하게 결정됩니다:

template<typename T>
concept C = requires(T p[2])
{
    (decltype(p))nullptr; // OK, p는 T* 타입을 가짐
};

다음 조건 중 하나라도 충족되면 프로그램의 형식이 잘못되었습니다:

  • 로컬 매개변수가 default argument 를 갖습니다.
  • 매개변수 목록이 생략부호로 종료됩니다.
template<typename T>
concept C1 = requires(T t = 0)  // 오류: t에 기본 인수가 있음
{
    t;
};
template<typename T>
concept C2 = requires(T t, ...) // 오류: 생략부호로 종료됨
{
    t;
};

단순 요구사항

표현식 ;
expression - requires 로 시작하지 않는 표현식


단순 요구 사항은 expression 이 유효함을 주장합니다. expression unevaluated operand 입니다.

template<typename T>
concept Addable = requires (T a, T b)
{
    a + b; // "표현식 'a + b'가 컴파일될 수 있는 유효한 표현식이다"
};
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 키워드로 시작하는 요구사항은 항상 중첩 요구사항(nested requirement)으로 해석됩니다. 따라서 단순 요구사항(simple requirement)은 괄호로 묶이지 않은 requires 표현식으로 시작할 수 없습니다.

타입 요구사항

typename identifier ;
identifier - (가능성 있는 한정된) identifier ( 단순 템플릿 식별자 포함)


타입 요구사항은 identifier 로 명명된 타입이 유효함을 주장합니다: 이는 특정 이름의 중첩 타입이 존재하는지 확인하거나, 클래스/별칭 템플릿 특수화가 타입을 명명하는지 검증하는 데 사용될 수 있습니다. 클래스 템플릿 특수화를 명명하는 타입 요구사항은 타입이 완전할 것을 요구하지 않습니다.

template<typename T>
using Ref = T&;
template<typename T>
concept C = requires
{
    typename T::inner; // 요구되는 중첩 멤버 이름
    typename S<T>;     // 요구되는 클래스 템플릿 특수화
    typename Ref<T>;   // 요구되는 별칭 템플릿 치환
};
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>가 유효하고 타입을 명명함
    { 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 - constraint


복합 요구사항은 expression 의 속성을 주장합니다. 치환과 의미론적 제약 조건 검사는 다음 순서로 진행됩니다:

1) 템플릿 인자(있는 경우)가 expression 에 대입됩니다.
2) noexcept 가 존재하는 경우, expression potentially throwing 이어서는 안 됩니다.
3) 만약 type-constraint 가 존재한다면:
a) 템플릿 인수들이 type-constraint 에 대입됩니다.
b) decltype ( ( expression  ) ) type-constraint 이 부과하는 제약 조건을 만족해야 합니다. 그렇지 않으면, 이를 포함하는 requires 표현식은 false 입니다.

expression 평가되지 않는 피연산자 입니다.

template<typename T>
concept C2 = requires(T x)
{
    // *x 표현식이 유효해야 함
    // AND T::inner 타입이 유효해야 함
    // AND *x의 결과가 T::inner로 변환 가능해야 함
    {*x} -> std::convertible_to<typename T::inner>;
    // x + 1 표현식이 유효해야 함
    // AND std::same_as<decltype((x + 1)), int>가 만족되어야 함
    // 즉, (x + 1)은 int 타입의 prvalue여야 함
    {x + 1} -> std::same_as<int>;
    // x * 1 표현식이 유효해야 함
    // AND 그 결과가 T로 변환 가능해야 함
    {x * 1} -> std::convertible_to<T>;
};

중첩 요구사항

requires 제약-식 ;
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)>; // 중첩: "Same<...>가 true로 평가됨"
    { a.~T() } noexcept; // 복합: "a.~T()"는 예외를 던지지 않는 유효한 표현식
    requires Same<T*, decltype(new T)>; // 중첩: "Same<...>가 true로 평가됨"
    requires Same<T*, decltype(new T[n])>; // 중첩
    { delete new T }; // 복합
    { delete new T[n] }; // 복합
};

참고

키워드 requires 는 또한 requires clauses 를 도입하는 데에도 사용됩니다.

template<typename T>
concept Addable = requires (T x) { x + x; }; // requires 표현식
template<typename T> requires Addable<T> // requires 절, requires 표현식이 아님
T add(T a, T b) { return a + b; }
template<typename T>
    requires requires (T x) { x + x; } // ad-hoc 제약 조건, 키워드가 두 번 사용됨에 유의
T add(T a, T b) { return a + b; }

키워드

requires

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
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 요구 표현식 [expr.prim.req]

참고 항목

제약 조건과 개념 (C++20) 템플릿 인수에 대한 요구 사항을 지정함