BOOST_STATIC_ASSERT与assert的区别(转)

assert是运行期断言,也就是在编译期出现的错误,它不会提示;
而boost中的BOOST_STATIC_ASSERT是在编译期的断言,也就是说在编译的时候就可以断言出错误。
比如下面的函数:

  1.  
    void expects_ints_to_be_4bytes()
  2.  
    {
  3.  
    BOOST_STATIC_ASSERT(sizeof(int)!=4);
  4.  
    assert(sizeof(int)!=4);
  5.  
    }


编译的时候就会提示
static_assert.cpp: In function 'void expects_ints_to_be_4bytes()':
static_assert.cpp:11: error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>'
也就是BOOST_STATIC_ASSERT的断言。把这行改成BOOST_STATIC_ASSERT(sizeof(int)==4);再编译,不会提示错误。而assert(sizeof(int)!=4)这行在运行的时候 会提示错误。
所以,一个是编译期的断言,一个运行期的断言,两个可以起到很好的互补作用
以下情形下使用 BOOST_STATIC_ASSERT :
当条件可以在编译期进行求值
对类型的要求可以在编译期表示
你需要对两个或以上的整型常量间的关系进行断言

 

 

如果大家用的是VC2010及以上版本的编译器的话,可以直接使用C++ 0x标准中的static_assert,这些编译器都是支持这个新标准的。

而我好奇的是boost是怎么实现这个的,非常简单,就几行代码。

#define BOOST_STATIC_ASSERT( B ) \
   typedef ::boost::static_assert_test<\
      sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST ( B ) >)>\
         BOOST_JOIN(boost_static_assert_typedef_, __COUNTER__)

 

// HP aCC cannot deal with missing names for template value parameters
template <bool x> struct STATIC_ASSERTION_FAILURE;

template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };

// HP aCC cannot deal with missing names for template value parameters
template<int x> struct static_assert_test{};

我们使用的是BOOST_STATIC_ASSERT(expr);这个宏看上去挺长挺吓人的,下面一层层的剥开它。

首先对表达式求值,并将结果转换为bool类型,这是由BOOST_STATIC_ASSERT_BOOL_CAST ( B )完成的。

然后,用求出的结果作为模板参数传给STATIC_ASSERTION_FAILURE类模板,使用sizeof计算结构大小。但是,如果计算出的表达式的结果为false,由于没有特化这个类,所以就会很自然的编译出错。

sizeof的结果又作为static_assert_test的模板参数。

最后又是一层typedef,所以使用BOOST_STATIC_ASSERT链接后不会增加任何汇编代码。

BOOST_JOIN很简单,boost_static_assert_typedef_## __COUNTER__)。

posted on 2020-07-22 21:30  树河田  阅读(236)  评论(0编辑  收藏  举报