我声称this program应该是格式良好的:它声明了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"
}
海湾合作委员会说:
错误:&#39;尝试&#39; in&#39; constexpr&#39;功能
Clang说:
错误:constexpr函数中不允许使用语句
他们似乎都没有注意到&#34;尝试&#34; statement位于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;
}
}
};
这是
foo()
的{{3}}而导致的实施质量问题?(不相关的背景:我正在为分配器感知版本any::emplace<T>()
实施constexpr any
,其分配器可能是constexpr-per - "conditional constexprness"(即它可能缺少deallocate
会员功能)或者可能没有。在前一种情况下,我们不想要或不需要try
;在后一种情况下,我们需要try
才能调用{deallocate
1}}如果T
的构造函数抛出。)
答案 0 :(得分:11)
编制者遵守标准。 C ++ 17草案N4659说([dcl.constexpr] /(3.4.4)):
constexpr函数的定义应满足以下要求:
...
function-body 应为
= delete
,= default
或复合语句,不包含
...
try-block 或
...
else
中S<int>::foo
语句中的“废弃语句”的规则都没有覆盖此规则。关于废弃语句的唯一特殊事项是废弃语句没有实例化,废弃语句中的odr-uses不会导致需要使用声明的定义,并且在确定真实返回时忽略丢弃的return
语句具有占位符返回类型的函数的类型。
我没有看到任何现有的C ++问题讨论这个问题,提出if constexpr
的论文P0292R1没有解决与constexpr函数的交互问题。