Namespaces
Variants

assert

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

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

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

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

  • 引数がゼロと等しくないと比較された場合、それ以上の効果はありません。
  • そうでなければ、assert は標準エラーストリームに診断メッセージを生成し、std::abort() を呼び出します。
(C++26まで)

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

  • 評価結果が true の場合、それ以上の効果はありません。
  • そうでなければ、assert は標準エラーストリームに診断メッセージを生成し、std::abort() を呼び出します。
(C++26から)

診断情報は処理系定義の形式ですが、常に以下の情報を含みます:

  • 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) コンパイル時アサーション検査を実行
異常プログラム終了を引き起こす(クリーンアップなし)
(関数)