Namespaces
Variants

setjmp

From cppreference.net
Utilities library
ヘッダーで定義 <csetjmp>
#define setjmp(env) /* implementation-defined */

現在の実行コンテキストを変数 env に保存します。この変数は std::jmp_buf 型です。この変数は後で std::longjmp 関数を使用して現在の実行コンテキストを復元するために使用できます。つまり、 std::longjmp 関数が呼び出されると、実行は std::jmp_buf 変数を構築した特定の呼び出し元で継続されます。この場合、 setjmp std::longjmp に渡された値を返します。

setjmp の呼び出しは、以下のいずれかのコンテキストでのみ行わなければなりません:

  1. if switch while do-while for の制御式全体。
    switch (setjmp(env)) { // ...
  2. 関係演算子または等価演算子の一方のオペランドが整数定数式であり、結果の式が if switch while do-while for の制御式全体となる場合。
    if (setjmp(env) > 0) { // ...
  3. 単項 ! 演算子のオペランドであり、結果の式が if switch while do-while for の制御式全体となる場合。
    while (!setjmp(env)) { // ...
  4. 式文 の式全体( void へのキャストを含む)。
    setjmp(env);

If setjmp が他のコンテキストで現れた場合、動作は未定義です。

さらに、 コルーチン 内で co_await 演算子が使用される可能性のある場所で setjmp が呼び出された場合、動作は未定義である。

(C++20以降)

setjmp のスコープに戻った際:

  • アクセス可能なすべてのオブジェクト、浮動小数点ステータスフラグ、および抽象機械の他の構成要素は、 std::longjmp が実行された時点と同じ値を持ちます。
  • ただし、 volatile 修飾されていないローカル変数は例外で、 setjmp の呼び出しを含む関数内のこれらの変数は、 setjmp 呼び出し以降に変更されている場合、その値は不定となります。

目次

パラメータ

env - プログラムの実行状態を保存する変数

戻り値

0 マクロが元のコードによって呼び出され、実行コンテキストが env に保存された場合。

非ローカルジャンプが実行された場合はゼロ以外の値。戻り値は std::longjmp に渡された値と同じです。

注記

上記の要件では、 setjmp の戻り値をデータフローで使用すること(例えば、オブジェクトの初期化や代入に使用すること)を禁止しています。戻り値は制御フローでのみ使用するか、破棄する必要があります。

#include <array>
#include <cmath>
#include <csetjmp>
#include <cstdlib>
#include <format>
#include <iostream>
std::jmp_buf solver_error_handler;
std::array<double, 2> solve_quadratic_equation(double a, double b, double c)
{
    const double discriminant = b * b - 4.0 * a * c;
    if (discriminant < 0)
        std::longjmp(solver_error_handler, true); // エラーハンドラへジャンプ
    const double delta = std::sqrt(discriminant) / (2.0 * a);
    const double argmin = -b / (2.0 * a);
    return {argmin - delta, argmin + delta};
}
void show_quadratic_equation_solution(double a, double b, double c)
{
    std::cout << std::format("{}x² + {}x + {} = 0 を解いています...\n", a, b, c);
    auto [x_0, x_1] = solve_quadratic_equation(a, b, c);
    std::cout << std::format("x₁ = {}, x₂ = {}\n\n", x_0, x_1);
}
int main()
{
    if (setjmp(solver_error_handler))
    {
        // ソルバーのエラーハンドラ
        std::cout << "実数解なし\n";
        return EXIT_FAILURE;
    }
    for (auto [a, b, c] : {std::array{1, -3, 2}, {2, -3, -2}, {1, 2, 3}})
        show_quadratic_equation_solution(a, b, c);
    return EXIT_SUCCESS;
}

出力:

1x² + -3x + 2 = 0 を解いています...
x₁ = 1, x₂ = 2
2x² + -3x + -2 = 0 を解いています...
x₁ = -0.5, x₂ = 2
1x² + 2x + 3 = 0 を解いています...
実数解なし

関連項目

指定された場所にジャンプする
(関数)