既存のコンパイル時アサートの実装は、負の配列インデックスに基づいており、GCC での診断出力が不十分です。C++0x のstatic_assert
機能は非常に優れており、提供される診断出力ははるかに優れています。GCC が既にいくつかの C++0x 機能を実装していることは知っています。static_assert
それらの中にあるかどうか、そしてそれがどのGCCバージョン以降であるかを知っている人はいますか?
8 に答える
このページによると、gcc はstatic_assert
4.3.
GCC
サポートしていないバージョンを使用する必要がある場合は、static_assert
次を使用できます。
#include <boost/static_assert.hpp>
BOOST_STATIC_ASSERT( /* assertion */ )
基本的に、ブーストはこれです:
a を宣言します (ただし、定義しないでください!)
template< bool Condition > struct STATIC_ASSERTION_FAILURE;
アサーションが保持するケースの特殊化を定義します。
template <> struct STATIC_ASSERTION_FAILURE< true > {};
次に、次のように STATIC_ASSERT を定義できます。
#define STATIC_ASSERT(Condition) \
enum { dummy = sizeof(STATIC_ASSERTION_FAILURE< (bool)(Condition) > ) }
秘訣は、Condition が false の場合、コンパイラは構造体をインスタンス化する必要があることです。
STATIC_ASSERTION_FAILURE< false >
そのサイズを計算するために、これは定義されていないため失敗します。
-std=c++0x
次のコードは、フラグを指定してコンパイルすると、g++4.4.0で期待どおりに機能します。
int main() {
static_assert( false, "that was false" );
}
表示されます:
x.cpp: In function 'int main()':
x.cpp:2: error: static assertion failed: "that was false"
古い gcc を使用している、古い C++ 標準を使用している、または C を使用している場合は、http ://www.pixelbeat.org/programming/gcc/static_assert.html で説明されているように static_assert をエミュレートできます。
NSPRは次のことを行います。
#define PR_STATIC_ASSERT(condition) \
extern void pr_static_assert(int arg[(condition) ? 1 : -1])
condition
負の長さの配列を宣言しているため、falseの場合は失敗します。
これは実際には質問に答えませんが、スイッチケースに基づくコンパイル時のアサートが好きです。
#define COMPILE_TIME_ASSERT(cond) do { switch(0) { case 0: case cond: ; } } while (0)
C++ だけでなく、C でも機能します。
テンプレートの特殊化を介して、いつでもテンプレートや存在しない構造をいじることができます。これは、私が知る限り、ブーストがそれを行う方法です。これは私が static_assert として使用するもので、非常に簡単です。
namespace Internal
{
template<bool x> struct SASSERT_F;
template< > struct SASSERT_F <true> {};
template<int x> struct SASSERT_P {};
#define STATIC_ASSERT(B) \
typedef Internal::SASSERT_P <( \
sizeof (Internal::SASSERT_F <( \
((B)? true : false)) >) \
)> \
StaticAssert##__LINE__ ()
}
使用例
int main(int argc, char **argv)
{
static_assert(sizeof(int) == 1) // Error
static_assert(sizeof(int) == sizeof(int)) // OK
}