如何在constexpr函数中执行运行时断言?

时间:2015-09-04 15:06:12

标签: c++11 assert constexpr assertions

据我所知,constexpr函数可以在编译时和运行时执行,具体取决于整个评估是否可以在编译时完成。

但是,您不能重载此函数以使其具有运行时和编译时对应。

所以我的问题是,我如何设置运行时断言以确保运行时函数的执行与我的static_assert一起传递有效参数?

2 个答案:

答案 0 :(得分:5)

Eric Niebler在Assert and Constexpr in C++11中很好地介绍了这个问题,他指出在C ++ 11中不允许在constexpr函数中使用assert但是在C ++ 14中允许使用assert( {{3 }} )并提供以下代码段:

constexpr bool in_range(int val, int min, int max)
{
    assert(min <= max); // OOPS, not constexpr
    return min <= val && val <= max;
}

如果我们必须支持C ++ 11,那么有一些替代方案。显而易见的是使用throw,但是当他指出这会将应该是一个不可恢复的错误变成可恢复的错误,因为你可以捕获异常。

他建议了一些替代方案:

  1. 将throw与As part of the Relaxing constraints on constexpr functions proposal

    一起使用
    constexpr bool in_range(int val, int min, int max) noexcept 
    {
      return (min <= max)
        ? min <= val && val <= max
        : throw std::logic_error("Assertion failed!");
    }
    

    如果异常离开函数std :: terminate将被调用。

  2. 从异常类型的构造函数中调用noexcept specifier

    struct assert_failure
    {
        explicit assert_failure(const char *sz)
        {
            std::fprintf(stderr, "Assertion failure: %s\n", sz);
            std::quick_exit(EXIT_FAILURE);
        }
    };
    
    constexpr bool in_range(int val, int min, int max)
    {
        return (min <= max)
          ? min <= val && val <= max
          : throw assert_failure("min > max!");
    }
    
  3. 将断言的lambda表达式传递给异常类型的构造函数:

    constexpr bool in_range(int val, int min, int max)
    {
        return (min <= max)
          ? min <= val && val <= max
          : throw assert_failure(
              []{assert(!"input not in range");}
            );
    }
    

答案 1 :(得分:1)

您可以抛出异常。如果在编译时从constexpr函数抛出异常,它基本上算作失败的静态断言。如果它在运行时发生,它将像往常一样例外。

此问题显示了发生这种情况的代码示例:Passing constexpr objects around

还相关:What happens when an exception is thrown while computing a constexpr?