5

メンバー関数の結果に対してアサーションを実行する必要がある一般的なコードがいくつかあります。このメンバー関数は である場合もあればconstexpr、そうでない場合もあります。

template<typename T>
void foo(T t) {
  assert(t.member_function() == 10);
}

t.member_function() は定数式かもしれないので、そのような場合はとして扱うことができるかどうか疑問に思っていstatic_assertますが、それ以外の場合は通常の にデフォルト設定されていますassert。これは可能ですか?

4

1 に答える 1

2

これは少しクレイジーな解決策です。

行のコメントを外すConst c; foo(c);と、コンパイルされないことがわかります。これはコンパイル時のアサートです。

可変長配列が必要で、おそらく他のコンパイラ固有のものも必要です。私は g++-4.6 を使用しています。

配列のサイズは、メンバー関数が 10 を返すかどうかに応じて、0 または -1 のいずれかになります。したがって、これがコンパイル時に計算できる場合、コンパイルはそれが非可変長配列であり、負のサイズを持つことを認識します。 . 負のサイズにより、文句を言うことができます。それ以外の場合は、従来のアサートにフォールスルーします。

注意: ランタイム アサーションが失敗した直後に、ランタイム バージョンでコア ダンプを取得しています。freeたぶん、負のサイズの配列を試みるのは好きではありません。更新: アサーションの失敗でコア ダンプを取得していint main() {assert (1==2);}ます。これは正常ですか?

#include <iostream>
#include <cassert>
using namespace std;

struct Const {
        constexpr int member_function() { return 9; }
};
struct Runtime {
                  int member_function() { return 9; }
};

template<typename T>
void foo(T t) {
        if(0) {  // so it doesn't actually run any code to malloc/free the vla
            int z[(t.member_function()==10)-1]; // fails at compile-time if necessary
        }
        assert(t.member_function()==10);
}


int main() {
        //Const c; foo(c);
        Runtime r; foo(r);
}
于 2013-10-04T20:41:41.687 に答える