"if constexpr"与"try in constexpr function"警告的交互

"if constexpr" interaction with "try in constexpr function" warning

本文关键字:constexpr 警告 交互 function try if in      更新时间:2023-10-16

我声称这个程序应该是格式良好的:它声明了S<int>的constexpr成员函数。然而,GCC和Clang都拒绝这一计划。

template<class T>
struct S {
constexpr int foo() {
if constexpr (std::is_same_v<T, int>) {
return 0;
} else {
try {} catch (...) {}
return 1;
}
}
};
int main()
{
S<int> s;
return s.foo();  // expect "return 0"
}

GCC表示:

错误:"constexpr"函数中的"try">

Clang说:

错误:constexpr函数中不允许使用语句

他们似乎都没有注意到"try"语句位于if constexpr语句的丢弃分支中。

如果我将try/catch分解为非constexpr成员函数void trycatch(),那么Clang和GCC都对代码感到满意,尽管它的行为应该相当于不满意的版本。

template<class T>
struct S {
void trycatch() {
try {} catch (...) {}
}
constexpr int foo() {
if constexpr (std::is_same_v<T, int>) {
return 0;
} else {
trycatch();  // This is fine.
return 1;
}
}
};

这是吗

  • GCC和Clang都有错误吗
  • GCC和Clang正在忠实执行的标准中的缺陷
  • 由于foo()的"条件常数"导致的实施质量问题

(无关背景:我正在为any的分配器感知版本实现constexprany::emplace<T>(),该版本的分配器可能是constexpr-per-P0639(即,它可能缺少deallocate成员函数),也可能不是。在前一种情况下,我们不想要或不需要try;在后一种情况下,如果T的构造函数抛出,我们需要try来调用deallocate。)

编译器遵守标准。C++17草案N4659说([dcl.constexpr]/(3.4.4)):

constexpr函数的定义应满足以下要求:

  • 。。。

  • 函数体应为= delete= default或不包含的复合语句

    • 。。。

    • 试块,或

    • 。。。

并且对于";丢弃的语句";例如CCD_ 17中的CCD_。关于丢弃语句,唯一指定的特殊之处是,丢弃语句没有实例化,丢弃语句中的odr使用不会导致需要对所用声明进行定义,并且在确定具有占位符返回类型的函数的真实返回类型时,会忽略丢弃的return语句。

我没有看到任何现有的C++问题在讨论这一点,并且提出if constexpr的论文P0292R1没有涉及与constexpr函数的交互。