7

静的アサートは、コンパイル時に物事をチェックするのに非常に便利です。単純な静的アサート イディオムは次のようになります。

template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};

#define STATIC_ASSERT(condition) do { StaticAssert<(condition)>(); } while(0)

これは次のようなものに適しています

STATIC_ASSERT(sizeof(float) == 4)

と:

#define THIS_LIMIT (1000)
...
STATIC_ASSERT(THIS_LIMIT > OTHER_LIMIT);

しかし、使用#defineは定数を定義する「C++」の方法ではありません。C++ では、匿名の名前空間を使用する必要があります。

namespace {
    const int THIS_LIMIT = 1000;
}

あるいは:

static const int THIS_LIMIT = 1000;

これに関する問題は、 をconst int使用することができずSTATIC_ASSERT()、ばかげた実行時チェックに頼らなければならないことです。

現在の C++ でこれを適切に解決する方法はありますか?
C++0xにはこれを行うための機能があると読んだと思います...


編集

よし、これで

static const int THIS_LIMIT = 1000;
...
STATIC_ASSERT(THIS_LIMIT > 0);

正常にコンパイルされます
が、これは:

static const float THIS_LIMIT = 1000.0f;
...
STATIC_ASSERT(THIS_LIMIT > 0.0f);

ではない。
(Visual Studio 2008 の場合)

どうして?

4

6 に答える 6

11

なぜ、const int を使用して静的アサートを行うことができますか。

#define static_assert(e) extern char (*ct_assert(void)) [sizeof(char[1 - 2*!(e)])]
static_assert( THIS_LIMIT > OTHER_LIMIT )

また、ブーストを使用してください!

BOOST_STATIC_ASSERT( THIS_LIMIT > OTHER_LIMIT )

...より良いエラーメッセージが表示されます...

于 2010-05-25T08:00:46.877 に答える
5

static_assertは C++0x のコンパイラ機能であるため、比較的最新のコンパイラがあればそれを使用できます。#define static_assert(x) ...これは C++0x の実際のキーワードであるため、コンパイラ機能を永久に隠してしまうため、注意してください。また、C++0xstatic_assertは 2 つのパラメーター (例: static_assert(sizeof(int) == 4, "Expecting int to be 4 bytes")) を受け取るため、その #define を使用すると、将来切り替えようとすると問題が発生する可能性があります。

于 2010-05-25T08:35:49.790 に答える
2

以下が当てはまる理由を本当に尋ねているようです(GCC 4.3.4 と Visual C++ 2008 Express の両方で確認できます)。

template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};

#define STATIC_ASSERT(condition) do { StaticAssert<(condition)>(); } while(0)


static const int   AN_INT  = 1000;
static const float A_FLOAT = 1000.0f;

int main()
{
   STATIC_ASSERT(AN_INT > 0);     // OK
   STATIC_ASSERT(A_FLOAT > 0.0f); // Error: A_FLOAT may not appear in a constant expression
}

浮動小数点値を静的に使用する場合、多くの制限があります。たとえば、これらをテンプレート引数として渡すことはできないことに注意してください。その理由は次のとおりです。

[C++11: 5.19/2]: conditional-expressionは、評価される可能性のある部分式 (3.2) として次のいずれかが含まれていない限り、コア定数式ですが、評価されない論理 AND (5.14)、論理 OR (5.15)、および条件付き (5.16) 演算の部分式は含まれません。は考慮されません [注:オーバーロードされた演算子は関数を呼び出します。—終わりのメモ] :

  • [..]
  • 適用されない限り、左辺値から右辺値への変換 (4.1)
    • 定数式で初期化された、前に初期化された不揮発性 const オブジェクトを参照する整数型または列挙型の glvalue 、または
    • constexpr で定義された不揮発性オブジェクトを参照する、またはそのようなオブジェクトのサブオブジェクトを参照するリテラル型の glvalue、または
    • 定数式で初期化された、存続期間が終了していない不揮発性の一時オブジェクトを参照するリテラル型の glvalue。
  • [..]

(つまり、整数型と列挙型のみが許可され、浮動小数点型は許可されません。)

このルールの理由については、完全にはわかりませんが、次のような理論的根拠が関係している可能性があります。

[C++11: 5.19/4]:[..] この国際規格は浮動小数点演算の精度に制限を課していないため、変換中の浮動小数点式の評価が同じ式(または同じ演算)の評価と同じ結果をもたらすかどうかは規定されていません。プログラムの実行中。[..]

于 2012-01-21T22:10:56.367 に答える
1

これ:

namespace {
    const int THIS_LIMIT = 1000;
}

template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};

#define STATIC_ASSERT(condition) do { StaticAssert<(condition)>(); } while(0)

int main()
{
    STATIC_ASSERT(THIS_LIMIT > 5);

    return (0);
}

VCとComeauで正常にコンパイルされます。

于 2010-05-25T08:15:48.397 に答える
1

おそらく、C++ の動作を C と混同しているのではないでしょうか。ここで、const intは実際のコンパイル時の定数を表していません。または、C++ コンパイラが壊れている可能性があります。本当に後者の場合は、enum代わりに使用してください。

于 2010-05-25T08:12:32.473 に答える
0

enum{THIS_LIMIT = 1000};

于 2010-05-25T08:19:27.143 に答える