COMPILE_ASSERT

最近在看chrome的代碼,發現了有個叫COMPILE_ASSERT的宏,用於編譯時做判斷。COMPILE_ASSERT宏的實現在D:/project/chrome/src/src/base/basictypes.h ,註釋部分有其原理的介紹,如下:

// The COMPILE_ASSERT macro can be used to verify that a compile time
// expression is true. For example, you could use it to verify the
// size of a static array:
//
//   COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES,
//                  content_type_names_incorrect_size);
//
// or to make sure a struct is smaller than a certain size:
//
//   COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
//
// The second argument to the macro is the name of the variable. If
// the expression is false, most compilers will issue a warning/error
// containing the name of the variable.

template <bool>
struct CompileAssert {
};

#undef COMPILE_ASSERT
#define COMPILE_ASSERT(expr, msg) /
  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]

// Implementation details of COMPILE_ASSERT:
//
// - COMPILE_ASSERT works by defining an array type that has -1
//   elements (and thus is invalid) when the expression is false.
//
// - The simpler definition
//
//     #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
//
//   does not work, as gcc supports variable-length arrays whose sizes
//   are determined at run-time (this is gcc's extension and not part
//   of the C++ standard).  As a result, gcc fails to reject the
//   following code with the simple definition:
//
//     int foo;
//     COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
//                               // not a compile-time constant.
//
// - By using the type CompileAssert<(bool(expr))>, we ensures that
//   expr is a compile-time constant.  (Template arguments must be
//   determined at compile-time.)
//
// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
//
//     CompileAssert
//
//   instead, these compilers will refuse to compile
//
//     COMPILE_ASSERT(5 > 0, some_message);
//
//   (They seem to think the ">" in "5 > 0" marks the end of the
//   template argument list.)
//
// - The array size is (bool(expr) ? 1 : -1), instead of simply
//
//     ((expr) ? 1 : -1).
//
//   This is to avoid running into a bug in MS VC 7.1, which
//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.

主要是用了數組的長度不能小於0的特性,例如int a[-1]會在編譯時會報錯。爲了兼容各個編譯器,使用了模板技術。

在msdn上,也有一篇文章來介紹COMPILE_ASSERT:http://blogs.msdn.com/b/abhinaba/archive/2008/10/27/c-c-compile-time-asserts.aspx

在boost裏面,與COMPILE_ASSERT相似有BOOST_STATIC_ASSERT,實現可以參考:http://www.boost.org/doc/libs/1_36_0/boost/static_assert.hpp

在搜索代碼時,發現了一個庫milihttp://code.google.com/p/mili/),這裏面也有一個compile_assert的實現(http://code.google.com/p/mili/source/browse/trunk/include/compile_assert.h)。這個庫還有其他一些實用的類和特性,例如Properties(http://code.google.com/p/mili/wiki/Properties)。Properties的實現原理可以參考http://xiaolingyao.spaces.live.com/blog/cns!6A8F02D95D2DDE46!201.entry?sa=991256254

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章