【问题标题】:C++11 - static_assert within constexpr function?C ++ 11 - constexpr函数中的static_assert?
【发布时间】:2011-12-24 18:00:40
【问题描述】:

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

constexpr int do_something(int x)
{
  static_assert(x > 0, "x must be > 0");
  return x + 5;
}

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

【问题讨论】:

    标签: c++ c++11 static-assert constexpr


    【解决方案1】:

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

    这是不正确的。 constexpr 函数中的 static_assert 很好。 not 很好的是在常量表达式中使用函数参数,就像你做的那样。

    x <= 0 可以抛出。在需要常量表达式的上下文中调用函数将无法编译

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

    【讨论】:

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

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

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

    我遇到了与 C++ 中的常量表达式相同的问题。目前几乎没有关于 constexprs 的明确文档。请注意,在 gcc 的问题跟踪器中存在一些已知的错误,但您的问题似乎不是错误。

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

    编辑:根据标准允许这样做:7.1.3 states

    ... 或仅包含

    的复合语句
    • 空语句,
    • static_assert-声明
    • typedef 声明和别名声明不
      定义类或枚举,
    • 使用声明,
    • 使用指令,
    • 只有一个返回语句

    【讨论】:

    • 没有。 constexpr 必须只有一个 return 语句。
    • 我阅读了标准。你是对的,这很好。我编辑了你的答案以添加它。
    • 谢谢。这种方式对我很有效。我不能使用异常,因为它们在我的构建(小型嵌入式系统)中被禁用。
    • 这个函数怎么调用?
    猜你喜欢
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 2016-11-13
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    相关资源
    最近更新 更多