C++ 11 - constexpr函数中的static_assert?

Rét*_*roX 53 c++ static-assert constexpr c++11

如何static_assert在一个constexpr函数中正确执行?例如:

constexpr int do_something(int x)
{
  static_assert(x > 0, "x must be > 0");
  return x + 5;
}
Run Code Online (Sandbox Code Playgroud)

这不是有效的C++ 11代码,因为constexpr函数必须只包含return语句.我不认为该标准有例外,但GCC 4.7不允许我编译这段代码.

Joh*_*itb 59

这不是有效的C++ 11代码,因为constexpr函数必须只包含return语句.

这是不正确的.static_assert在一个constexpr功能是好的.什么是不好的是在常量表达式中使用函数参数,就像你这样做.

你可以扔掉x <= 0.在需要常量表达式的上下文中调用该函数将无法编译

constexpr int do_something(int x) {
  return x > 0 ? (x + 5) : (throw std::logic_error("x must be > 0"));
}
Run Code Online (Sandbox Code Playgroud)

  • @Xeo在*的另一边做*任何事情*非同情?:将完成这项工作.:) (16认同)
  • 很酷,我不知道在constexpr上下文中调用的`constexpr`函数中的`throw`会导致编译失败! (9认同)
  • 我很困惑为什么"在常量表达式中使用函数参数"是"不好".如果'x'是常量表达式,则(x + 5)也是常量表达式,可以在编译时进行求值.如果'x'不是常量表达式,那么函数本身就失去了它的constexpr-ness(对于那个特定的调用),并且只是在运行时进行评估.有人可以澄清吗? (5认同)
  • @ monkey_05_06:因为'x'是函数参数,因此**不是**constexpr.请记住,constexpr函数也必须适合作为运行时函数(使用非constexpr args),因此它的args不适用于static_assert(...)声明.这与您是否实际上从非constexpr上下文调用该函数无关,这就是为什么constexpr函数也必须是运行时可调用的要求与它是"特性"一样多的限制. (5认同)
  • @gnzlbg:请参阅上面关于使用任何不是“constexpr”的内容的评论。我所做的(作为通用解决方案)是声明一个 **non-**constexpr 函数模板,如下所示... `template&lt;typename RT&gt; RT non_constexpr() { return RT{}; }` ...像这样使用... `return (x &gt; 0) ? (x + 5) : non_constexpr&lt;int&gt;();` ...在 g++ 和 clang++ 中测试。 (2认同)

cpp*_*ist 23

这是有效的C++ 11代码,因为模板参数只是编译时间:

template <int x>
constexpr int do_something() {
    static_assert(x > 0, "x must be > 0");
    return x + 5;
}
Run Code Online (Sandbox Code Playgroud)

我遇到了与C++中常量表达式相同的问题.目前关于constexprs的文档很少.请注意,在gcc的问题跟踪器中有一些已知的错误,但你的问题似乎不是一个错误.

请注意,如果在类中声明constexpr函数,则无法在类中使用它们.这似乎也不是一个错误.

编辑:根据标准允许这样:7.1.3状态

...或仅包含的复合语句

  • 空语句,
  • static_assert -declarations
  • typedef声明和不
    定义类或枚举的别名声明,
  • 使用申述,
  • using指令,
  • 而且只有一个退货声明