【问题标题】:Does GCC have a built-in compile time assert?GCC 有内置的编译时断言吗?
【发布时间】:2010-11-02 12:39:56
【问题描述】:

我们现有的编译时断言实现基于负数组索引,它在 GCC 上提供了较差的诊断输出。 C++0x 的static_assert 是一个非常好的特性,它提供的诊断输出要好得多。我知道 GCC 已经实现了一些 C++0x 特性。有谁知道static_assert 是否在其中,如果它是从哪个 GCC 版本开始的?

【问题讨论】:

标签: c++ gcc static-assert


【解决方案1】:

根据this page,gcc 从 4.3 开始就有static_assert

【讨论】:

    【解决方案2】:

    当使用-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,请将 static_assert 替换为 _Static_assert 以使其正常工作。我刚刚在这里使用 C 在线测试了它:onlinegdb.com。使用static_assert 失败。
    【解决方案3】:

    如果您需要使用不支持static_assertGCC 版本,您可以使用:

    #include <boost/static_assert.hpp>
    
    BOOST_STATIC_ASSERT( /* assertion */ )
    

    基本上,boost 的作用是这样的:

    声明(但不要定义!)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 >
    

    为了计算它的大小,但由于没有定义,所以失败了。

    【讨论】:

    • 我想知道是否有任何方法可以使这样的技巧出现合理的错误消息......
    • 根据文档 (boost.org/doc/libs/1_43_0/doc/html/boost_staticassert.html),这是 Boost.StaticAssert 的目标之一:“BOOST_STATIC_ASSERT 的目标之一是生成可读的错误消息。这些会立即告诉用户正在以不受支持的方式使用库。”
    • ...(Condition) &gt; } 中缺少括号,应该是...(Condition) &gt; ) }。我尝试编辑此内容但被拒绝...
    【解决方案4】:

    这并不能真正回答问题,但我更喜欢基于 switch-case 的编译时断言,例如

    #define COMPILE_TIME_ASSERT(cond) do { switch(0) { case 0: case cond: ; } } while (0)
    

    也可以在 C 中工作,而不仅仅是在 C++ 中。

    【讨论】:

    • 这种技术有两个缺点。首先,这种断言不能在类或命名空间级别使用。其次,当断言成功时,它会生成可执行代码,从而膨胀二进制文件。它留给您的优化编译器来删除它,这并不能保证。 :-(
    【解决方案5】:

    如果您有较旧的 gcc 或使用较旧的 C++ 标准,或使用 C,那么您可以模拟 static_assert,如下所述:http://www.pixelbeat.org/programming/gcc/static_assert.html

    【讨论】:

      【解决方案6】:

      你总是可以玩弄模板和不存在的 通过模板专业化的结构。这是如何提升 据我所知是这样做的。这就是我用作 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
      }
      

      【讨论】:

        【解决方案7】:

        NSPR 会:

        #define PR_STATIC_ASSERT(condition) \
            extern void pr_static_assert(int arg[(condition) ? 1 : -1])
        

        如果 condition 为 false 则失败,因为它声明了一个负长度数组。

        【讨论】:

          【解决方案8】:

          两者

              BOOST_STATIC_ASSERT(x)
              BOOST_STATIC_ASSERT_MSG(x, msg)
          

          如果您的编译器支持,将使用 C++11 static_assert

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多