C++2a(C++20) コンセプト requires式(requires-expression) では、同式を包含するコンテキストのあらゆる宣言を利用できる。
下記コードのrequires式からは関数テンプレートの仮引数x
を参照している。requires式の本体(requirement-body)は評価されず(unevaluated)、型情報(型T
)のみを利用している。
#include <iostream> #include <string> using namespace std::string_literals; template <typename T> T doubling(T x) { if constexpr (requires { x.doubling(); }) { x.doubling(); // #1 return x; } else if constexpr (requires { x * 2; }) { return x * 2; // #2 } else { return x + x; // #3 } } // doublingメンバ関数を持つクラス型 struct X { unsigned m_; void doubling() { m_ <<= 1; } friend std::ostream& operator<<(std::ostream& os, const X& x) { return os << "X{" << x.m_ << "}"; } }; std::cout << doubling(3.14); // 6.28 (#2) std::cout << doubling("abc"s); // abcabc (#3) std::cout << doubling(X{21}); // X{42} (#1)
1番目constexpr if文の条件式記述では下記の選択肢が考えられる:
requires { x.doubling(); }
:関数パラメータ宣言を利用requires (T t) { t.doubling(); }
:ローカルパラメータ導入と利用requires { T{}.doubling(); }
:テンプレートパラメータを利用
N4861 7.5.7/p1-2, 4-5より一部引用(下線部は強調)。
1 A requires-expression provides a concise way to express requirements on template arguments that can be checked by name lookup (6.5) or by checking properties of types and expressions.
requires-expression:
requires
requirement-parameter-listopt requirement-body
requirement-parameter-list:
(
parameter-declaration-clauseopt)
requirement-body:
{
requirement-seq}
(snip)
2 A requires-expression is a prvalue of typebool
whose value is described below. Expressions appearing within a requirement-body are unevaluated operands (7.2).4 A requires-expression may introduce local parameters using a parameter-declaration-clause (9.3.3.5). (snip)
5 The requirement-body contains a sequence of requirements. These requirements may refer to local parameters, template parameters, and any other declarations visible from the enclosing context.
関連URL: