名前空間
変種
操作

requires(C++20 以降)

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 
 
 

制約を記述する型 bool の prvalue 式を生成します。

目次

[編集] 構文

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 のプロパティを表明します。置換と意味的制約のチェックは次の順序で進みます。

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

[編集] キーワード

要求するようになった

[編集] 欠陥レポート

以下の動作変更を伴う欠陥報告が、以前に公開された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 standard (ISO/IEC 14882:2020)
  • 7.5.7 Requires 式 [expr.prim.req]

[編集] 関連項目

制約とコンセプト(C++20) テンプレート引数に関する要件を指定します[編集]
English 日本語 中文(简体) 中文(繁體)