名前空間
変種
操作

assert

From cppreference.com
< cpp‎ | error
 
 
 
ヘッダ <cassert> で定義
アサーション無効時
(1)
#define assert(condition) ((void)0)
(C++26まで)
#define assert(...)       ((void)0)
(C++26以降)
アサーション有効時
(2)
#define assert(condition) /* 未指定 */
(C++26まで)
#define assert(...)       /* 未指定 */
(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 のテキスト
(C++26まで)
  • #__VA_ARGS__
(C++26以降)
  • ソースファイル名 (つまり、__FILE__)
  • ソース行番号 (つまり、__LINE__)
  • 囲んでいる関数の名前 (つまり、__func__)

assert(E) は、以下のいずれかの場合に 定数部分式 であることが保証されます。

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

目次

[編集] パラメーター

condition - スカラー型の式

[編集] 備考

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(("There are five lights", 2 + 2 == 5));
assert(2 + 2 == 5 && "There are five lights");

Microsoft CRTassert の実装は C++11 以降の改訂に準拠していません。これは、その基盤となる関数 (_wassert) が __func__ もその同等な代替も受け付けないためです。

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) コンパイル時アサーションチェックを実行する[編集]
(クリーンアップせずに)異常なプログラム終了を引き起こす
(関数) [編集]
assert のための C ドキュメント
English 日本語 中文(简体) 中文(繁體)