c++ - 投入 constexpr 函数 : do we need wrapping condition?

标签 c++ c++17 constexpr

基本思路是这样的:我有一些 constexpr功能,我想使用 throw发出错误信号和延迟编译以避免在正常流程中出现此错误:

template <size_t N>
auto constexpr find_elt(const std::array<int, N>& a, int k) {
  for (size_t i = 0; i < N; ++i)
    if (k == a[i])
      return i;
  throw "not found";
}

进而:
constexpr int result = find_elt(arr, 4);

通常,如果数组中存在 4,我会在编译时取回它的索引。

如果没有,我会失败到throw表明在编译时查找是错误的,编译器会产生一个相当大的错误。

但我注意到奇怪的行为:

Under the latest clang, everything works

Under the latest gcc, everything fails

这个想法合法吗?这段代码对于我想要实现的目标是否正确?哪个编译器在这里告诉我真相?

如果没有,这样做的正确方法是什么?

感谢任何指向 C++ 标准的链接。我通读了与 constexpr 相关的章节,但我对此表示怀疑。

最佳答案

所以:

  • 根据constexpr函数的编译是一个“懒惰”的过程,那么constexpr函数是否符合要求的检查只在表达式替换过程中编译器仍然进入的范围内进行。
  • 一个函数分别是一个作用域——constexpr 的所有规则必须在函数的第一级作用域的整个主体中遵守。
  • 并且由于表达式“throw”不是常量表达式(正如 gcc-10 编译器已经告诉我们的那样),因此未观察到正确性。

  • 在这个意义上,clang 编译器不像 gcc 那样严格。因此,在这场战斗中,在我看来,gcc 获胜。他更致力于标准。
    另一方面,如果这是一个“懒惰”的过程,那么为什么不应该懒惰到最后。好吧,你找到了最终的返回——那么为什么要进一步检查正确性呢?
    从这个意义上说,clang 得到了一个点。
    最后 - C++17 Standard 说什么?
    10.1.5 constexpr 说明符 [dcl.constexpr]
  • "...如果不存在参数值,使得函数或构造函数的调用可以是核心常量表达式 (8.20) 的评估子表达式,...,程序格式错误,无需诊断。

  • 接下来我们看看什么是“核心常量表达式”:
    8.20 常量表达式 [expr.const]
  • 一个表达式是一个评估,遵循抽象机(4.6)的规则,将评估以下表达式之一:

  • 2.22 - throw 表达式 (8.17)
    并注意“不需要诊断”并且编译器不需要提供失败原因的详细解释。

    关于c++ - 投入 constexpr 函数 : do we need wrapping condition?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61420045/

    相关文章:

    c++ - 重新排序位字段神秘地改变了结构的大小

    c++ - 如何在新设计中迁移需要几个额外参数的函数

    c++ - 在 C++-17 中,此构造函数是否有可能的模板推导指南?

    c++ - 模板参数函数是否必须被视为潜在的 constexpr?

    c++ - std::bind 与 lambda 的效率

    c++ - 'for_each_n' 不是 C++17 中 'std' 的成员

    c++ - 如何用 STL 实现替换这个 for 循环?

    c++ - 在 constexpr : what does the standard say? 中使用非常量

    c++ - 为什么编译时浮点计算的结果可能与运行时计算的结果不同?

    c++ - 翻译时,这些方括号会做什么?