static_assertの比較値をエラーメッセージに表示する

C++static_assert(A == B);は表明失敗時にfalseということしかわからない場合があります。

GCC 12以上、Clang 16以上であれば、比較値をエラーメッセージに表示してくれます。

int main()
{
    constexpr int a = 1;
    constexpr int b = 2;
    static_assert(a == b);
}

GCC :

prog.cc: In function 'int main()':
prog.cc:5:21: error: static assertion failed
    5 |     static_assert(a == b);
      |                   ~~^~~~
prog.cc:5:21: note: the comparison reduces to '(1 == 2)'

Clang :

prog.cc:5:5: error: static assertion failed due to requirement 'a == b'
    static_assert(a == b);
    ^             ~~~~~~
prog.cc:5:21: note: expression evaluates to '1 == 2'
    static_assert(a == b);
                  ~~^~~~
1 error generated.

それより古いコンパイラの場合は、クラスの非型テンプレートパラメータとして左辺、右辺の値をとり、そのなかでstatic_assertすることで、エラーメッセージにテンプレートパラメータを含むクラス名が表示されるので比較値がわかるようにできます。

template <auto A, auto B>
struct static_assert_eq {
    static constexpr bool value = true;
    static_assert(A == B);
};

int main()
{
    constexpr int a = 1;
    constexpr int b = 2;
    static_assert(static_assert_eq<a, b>::value);
}

メンバ変数宣言の文脈で使うような場合に、このような2段階のstatic_assertが必要になります。

struct X {
    static constexpr int a = 1;
    static constexpr int b = 2;
    static_assert(static_assert_eq<a, b>::value); // 文脈的にstatic_assert_eq<a, b>{};はできない
};