consteval 指定子 (C++20以降)
From cppreference.com
consteval- 関数が「即時関数」であることを指定します。つまり、その関数へのすべての呼び出しはコンパイル時定数を生成しなければなりません。
目次 |
[編集] 解説
consteval 指定子は、関数または関数テンプレートを「即時関数」として宣言します。つまり、その関数へのすべての潜在的に評価される呼び出しは、(直接的または間接的に)コンパイル時定数式を生成しなければなりません。
即時関数はconstexpr 関数であり、場合によってはその要件に従います。constexpr と同様に、consteval 指定子は inline を含意します。ただし、デストラクタ、アロケーション関数、またはデロケーション関数には適用できません。
consteval を指定する関数または関数テンプレートの宣言は、constexpr を同時に指定することはできません。また、その関数または関数テンプレートの再宣言も consteval を指定しなければなりません。
即時関数の潜在的に評価される呼び出しで、その最も内側の非ブロックスコープが即時関数の関数パラメータスコープまたはconsteval if ステートメントのtrue分岐(C++23以降)ではない場合、定数式を生成しなければなりません。このような呼び出しは「即時呼び出し」として知られています。
consteval int sqr(int n) { return n*n; } constexpr int r = sqr(100); // OK int x = 100; int r2 = sqr(x); // Error: Call does not produce a constant consteval int sqrsqr(int n) { return sqr(sqr(n)); // Not a constant expression at this point, but OK } constexpr int dblsqr(int n) { return 2 * sqr(n); // Error: Enclosing function is not consteval // and sqr(n) is not a constant }
即時関数を示す識別子式は、即時呼び出しのサブ式内、または「即時関数コンテキスト」(上記で述べたコンテキスト、即時関数への呼び出しが定数式である必要がないコンテキスト)内でのみ出現できます。即時関数へのポインタまたは参照を取得できますが、定数式評価からエスケープすることはできません。
consteval int f() { return 42; } consteval auto g() { return &f; } consteval int h(int (*p)() = g()) { return p(); } constexpr int r = h(); // OK constexpr auto e = g(); // ill-formed: a pointer to an immediate function is // not a permitted result of a constant expression
[編集] 注釈
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_consteval |
201811L |
(C++20) | 即時関数 |
202211L |
(C++23) (DR20) |
consteval を上位に伝播させる |
[編集] キーワード
[編集] 例
このコードを実行
#include <iostream> // This function might be evaluated at compile-time, if the input // is known at compile-time. Otherwise, it is executed at run-time. constexpr unsigned factorial(unsigned n) { return n < 2 ? 1 : n * factorial(n - 1); } // With consteval we enforce that the function will be evaluated at compile-time. consteval unsigned combination(unsigned m, unsigned n) { return factorial(n) / factorial(m) / factorial(n - m); } static_assert(factorial(6) == 720); static_assert(combination(4, 8) == 70); int main(int argc, const char*[]) { constexpr unsigned x{factorial(4)}; std::cout << x << '\n'; [[maybe_unused]] unsigned y = factorial(argc); // OK // unsigned z = combination(argc, 7); // error: 'argc' is not a constant expression }
出力
24
[編集] 関連項目
constexpr 指定子(C++11) |
変数または関数の値をコンパイル時に計算できることを指定する |
constinit 指定子(C++20) |
変数が静的初期化、すなわちゼロ初期化と定数初期化を持つことを表明する。 |
| ない | コンパイル時に評価可能な式を定義する |