【问题标题】:Any reason to use a run-time assert instead of compile-time assert?有什么理由使用运行时断言而不是编译时断言?
【发布时间】:2010-09-07 13:59:56
【问题描述】:

在查看 Visual C++ 代码库时,我发现了以下奇怪的事情。运行时断言(检查条件并在违反条件时抛出异常)用于可以在编译时评估条件的情况:

assert( sizeof( SomeType ) == sizeof( SomeOtherType ) );

很明显,编译器将评估条件并替换有效的代码

assert( true );

什么都不做或

assert( false );

每次控制通过该行时都会引发异常。

IMO 应该使用编译时断言,原因如下:

  • 它将在编译时更早地暴露条件违规 - 并且
  • 它将发出更清晰(因此更快更小)的机器代码

看起来编译时断言是唯一正确的事情。是否有任何可能的理由在这里更喜欢运行时断言?

【问题讨论】:

  • assert 通常不会抛出异常而是中止程序。
  • 到目前为止,还没有标准的编译时断言。这一事实非常重要,尤其是在较旧的代码库中。
  • 具体来说,VC6 在整个 Boost 库中都有各种特殊情况代码。如果您的代码现在或曾经是由 VC6 编译的(人们可能会认为这对于许多 MS 自己的源代码都是正确的),至少 BOOST_STATIC_ASSERT 可能是不可能的。
  • 大多数 asserts() 在发布时编译为空操作。它们仅在 Debug(即测试代码)中有效。

标签: c++ visual-c++ assert error-checking


【解决方案1】:

这里没有理由更喜欢运行时断言。您应该更喜欢编译时错误而不是运行时错误,因此,考虑到两者之间的选择,永远没有理由选择运行时断言。

但是,如果静态断言不是一个选项(不知道静态断言的概念,不知道如何制作并且没有可用的,或者知道如何制作但没有'没有时间),运行时断言是下一个最好的东西。

对于 C++0x,内置的 static_assert 特性应该结束所有使用运行时断言的理由,而编译时断言将起作用。

【讨论】:

    【解决方案2】:

    没有上下文我们无法判断。在模板代码中,某些分支对于某些实例化可能是不可访问的。编译时断言是不合适的,因为这会使整个函数格式错误。 assert(<type-dependent expression>) 没有。

    例如

    template <typename T> void foo(T t)
    {
      if (t < 0) {
        assert(std::numeric_limits<T>::min() < 0);
        T u = t - std::numeric_limits<T>::min();
      }
    }
    

    即使运行时断言永远不会失败,断言也无法转换为静态断言。

    【讨论】:

    • 为什么不能设为static_assert
    • assert(std::numeric_limits&lt;T&gt;::min &lt; 0); 总是失败,不管 T.
    • @usta:您是在评论缺少函数调用吗? @MSalters:我想你想要min()
    • @Dennis Zickefoose 是的,我评论的是 () 的缺失。添加后,该断言仍然无法转换为静态断言,因为 std::numeric_limits::min() (还)不是编译时表达式。
    • 修复了缺失的 ()。 @Gman:因为 static_assert 会阻止 foo&lt;unsigned int&gt; 编译。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多