8

組み込みの を持たないバージョンの C++ では、広く使用されている static assert の実装が 2 つありますstatic_assert

最初のものはBoostで使用され、テンプレートとそのテンプレートの特殊化を使用します:

template <bool> struct static_assert;
template <> struct static_assert<true> {}; // only true is defined
#define  STATIC_ASSERT(x) static_assert<(x)>()

ここで、チェックする条件が false になると、コンパイラはテンプレートの汎用バージョンを見つけることができず、コンパイルは失敗します。

2番目は次を使用しますtypedef

#define STATIC_ASSERT( x ) typedef char __STATIC_ASSERT__[( x )?1:-1]

ここで、チェックする条件に違反すると、コンパイラtypedefはサイズ -1 の配列を試みますが、これは違法であるため、コンパイル時エラーが発生します。

コードを発行しないことが保証されており、次のように使用できるため、後者の方が優れています(ここから):

template<int Shift> class BinaryFlag {
    STATIC_ASSERT( 0 <= Shift && Shift < sizeof( DWORD) * CHAR_BIT );
    public:
    static const DWORD FlagValue = static_cast<DWORD>( 1 << Shift );
};
#define BINARY_FLAG( n ) CBinaryFlag<n>::FlagValue

前者はそのようには使用できません。

後者よりも静的アサートの前者の実装を好む理由はありますか?

4

2 に答える 2

4

2 番目のバージョンのSTATIC_ASSERTあなたは、同じブロック内で連続して使用することはできません。

template<int N, int M>
void foo ()
{
  STATIC_ASSERT(N<M), STATIC_ASSERT(M<0);  // error
};

デモ

一方、投稿いただいた例では、初版は使えません(仮設を扱っているため)。したがって、両方のバージョンに独自の聴衆がいます。私が言える最初のバージョンは、コンパイルとランタイムの一種です。ただし、2 番目のバージョンは純粋にコンパイル時です。

編集: 読みやすくするために、すべてのアサートをコマンド演算子を使用して 1 行に入れたい場合があります (この場合、最後の命令のみが有効になります)。それらも一緒に置くことができることを私は知ってい;ます。ただし、例を示すためだけに、これは 1 つのユース ケースです。

同様に、オブジェクトの構築は問題typedefなくても、a を配置すると構文的に問題が発生する場合があります。したがって、それらはすべて同じ場所に分類されます。

于 2011-08-05T10:06:13.617 に答える
2

私は通常、自分のコードで 2 番目またはその変形を使用しました。実際には、Boost バリアントには、ステートメント レベルだけでなく、式が現れる可能性のある場所ならどこでも使用できるという利点があります。式が出現する可能性がある場所でしか使用できないため、名前空間のスコープでは使用できないという欠点があります。

于 2011-08-05T10:09:33.380 に答える