提问人:Bernard 提问时间:6/14/2018 更新时间:6/14/2018 访问量:1137
丢弃分支中的嵌套 constexpr-if 语句仍在计算?
Nested constexpr-if statement in discarded branch is still evaluated?
问:
在我看来,在 MSVC(版本 15.7.3)中评估另一个 constexpr-if 语句的丢弃分支内的 constexpr-if 语句。
请考虑以下代码:
#include <tuple>
#include <type_traits>
template <size_t I>
int test() {
if constexpr(I != 0) {
return 0;
}
else { // This branch is discarded, but it seems that the constexpr-if below is still evaulated?
if constexpr(std::is_same_v<int, std::tuple_element_t<I, std::tuple<int>>>) { // some constexpr check that is valid only when I == 0
return 1;
}
else {
return 2;
}
}
}
int main() {
test<1>();
return 0;
}
上面的代码无法在 MSVC 中编译,因为当超过元组的边界时,静态断言将失败。这表明以某种方式也评估了丢弃分支中的代码,即使它依赖于 template 参数。std::tuple_element_t
I
I
根据 cppreference,constexpr-if 要求“对于每个可能的专业化,丢弃的语句不能格式错误”,但我很难确定这里是否是这种情况。
GCC 和 Clang 似乎也毫无问题地接受此代码(在 Compiler Explorer 上测试)。
编译错误是否符合 C++ 标准,还是此处不符合 MSVC?
(另外,如果我期望代码做的事情不是标准保证的,那么是否有另一种方法可以完成嵌套的 constexpr-if 语句?
答:
GCC 和 Clang 是对的。如果丢弃的分支中唯一没有被丢弃的语句是另一个语句,那将是非常违反直觉的。if constexpr
[stmt.if]p2 没有提到任何关于这一点的内容:
如果转换条件的值为 false,则第一个子语句是丢弃的语句,否则第二个子语句,如果 present,是被丢弃的语句。在封闭的模板化实体(第 17 条)的实例化过程中,如果条件在实例化后不依赖于值,则丢弃的子语句(如果有)不是 实例。
强调我的。该标准表示不实例化丢弃的语句,在您的情况下是 .该分支中的任何内容都不会实例化,因此不允许编译器实例化任何内容,因此 MSVC 实例化是错误的。else { /*... * }
std::tuple_element<I, std::tuple<int>>
评论
I == 0