Namespaces
Variants

assert

From cppreference.net
ヘッダーで定義 <cassert>
無効化されたアサーション
(1)
#define assert(condition) ((void)0)
(C++26まで)
#define assert(...)       ((void)0)
(C++26以降)
有効化されたアサーション
(2)
#define assert(condition) /* unspecified */
(C++26まで)
#define assert(...)       /* unspecified */
(C++26以降)

マクロ assert の定義は、別のマクロ NDEBUG に依存しており、このマクロは標準ライブラリによって定義されていません。

1) ソースコード内で <cassert> または <assert.h> がインクルードされる時点で NDEBUG がマクロ名として定義されている場合、アサーションは無効化されます: assert は何も行いません。
2) それ以外の場合、アサーションは有効になります:

assert はその引数(スカラー型でなければならない)をチェックします:

  • 引数がゼロと比較して等しくない場合、それ以上の効果はありません。
  • それ以外の場合、 assert は標準エラーストリームに診断情報を出力し、 std::abort() を呼び出します。
(C++26まで)

assert はプログラムに診断テストを挿入し、型 void の式に展開されます。 __VA_ARGS__ が評価され、 文脈的に bool へ変換 されます:

  • 評価結果が true の場合、それ以上の効果はありません。
  • それ以外の場合、 assert は標準エラーストリームに診断情報を出力し、 std::abort() を呼び出します。
(C++26以降)

診断情報は実装定義の形式を持ちますが、常に以下の情報を含みます:

  • conditionのテキスト condition
(C++26まで)
  • #__VA_ARGS__
(C++26以降)
  • ソースファイル名(すなわち、 __FILE__
  • ソース行番号(すなわち、 __LINE__
  • 包含関数名(すなわち、 __func__

assert ( E ) は、以下のいずれかの条件が満たされる場合、 定数部分式 であることが保証される:

  • NDEBUG が、 assert が最後に定義または再定義される時点で定義されている場合、または
  • E が、 boolへ文脈的に変換 された際に、 true と評価される定数部分式である場合。
(C++11以降)

目次

パラメータ

条件 - スカラー型の式

注記

assert 関数形式マクロ であるため、引数内の括弧で保護されていないカンマはすべてマクロ引数の区切りとして解釈されます。このようなカンマは、テンプレート引数リストやリスト初期化でよく見られます:

assert(std::is_same_v<int, int>);        // error: assert does not take two arguments
assert((std::is_same_v<int, int>));      // OK: one argument
static_assert(std::is_same_v<int, int>); // OK: not a macro
std::complex<double> c;
assert(c == std::complex<double>{0, 0});   // error
assert((c == std::complex<double>{0, 0})); // OK
(C++26まで)

assert エラーに追加のメッセージを付加する標準化されたインターフェースは存在しません。ポータブルな方法としては、 コンマ演算子 オーバーロード されていない場合にそれを使用するか、文字列リテラルと共に && を使用する方法があります:

assert(("ライトは5つあります", 2 + 2 == 5));
assert(2 + 2 == 5 && "ライトは5つあります");

Microsoft CRT における assert の実装は、その基盤となる関数( _wassert )が __func__ または同等の代替を受け取らないため、C++11以降の規格に準拠していません。

C++20以降、診断メッセージに必要な値は std::source_location::current() からも取得できるようになりました。

C23/C++26における assert の変更は正式には欠陥報告書ではありませんが、C委員会は 推奨しています 実装がこの変更を旧モードにバックポートすることを。

#include <iostream>
// uncomment to disable assert()
// #define NDEBUG
#include <cassert>
// Use (void) to silence unused warnings.
#define assertm(exp, msg) assert((void(msg), exp))
int main()
{
    assert(2 + 2 == 4);
    std::cout << "Checkpoint #1\n";
    assert((void("void helps to avoid 'unused value' warning"), 2 * 2 == 4));
    std::cout << "Checkpoint #2\n";
    assert((010 + 010 == 16) && "Yet another way to add an assert message");
    std::cout << "Checkpoint #3\n";
    assertm((2 + 2) % 3 == 1, "Success");
    std::cout << "Checkpoint #4\n";
    assertm(2 + 2 == 5, "Failed"); // assertion fails
    std::cout << "Execution continues past the last assert\n"; // No output
}

出力例:

Checkpoint #1
Checkpoint #2
Checkpoint #3
Checkpoint #4
main.cpp:23: int main(): Assertion `((void)"Failed", 2 + 2 == 5)' failed.
Aborted

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
LWG 2234 C++11 assert は定数式で使用できなかった 使用可能

関連項目

contract_assert (C++26) 実行時の内部条件を検証
static_assert 宣言 (C++11) コンパイル時アサーション検査を実行
異常プログラム終了を引き起こす(クリーンアップなし)
(関数)