requires
表示式 (C++20 起)
生成一個描述約束的 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 ; |
|||||||||
表示式 | - | 一個不以 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 identifier ; |
|||||||||
identifier | - | 一個(可能帶限定的)識別符號(包括簡單模板識別符號) |
型別需求斷言由 identifier 命名的型別是有效的:這可以用於驗證某個命名的巢狀型別是否存在,或者類/別名模板特化是否命名了一個型別。命名類模板特化的型別需求不要求型別是完整的。
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) | ||||||||
表示式 | - | 一個表示式 |
type-constraint | - | 一個約束 |
複合需求斷言 expression 的屬性。替換和語義約束檢查按以下順序進行:
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; }
[編輯] 關鍵詞
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 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) | 指定對模板實參的要求 |