仍在评估废弃分支中的嵌套constexpr-if语句?

Ber*_*ard 11 c++ nested c++17 if-constexpr

在我看来,在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;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码无法在MSVC中编译,因为std::tuple_element_tI超过元组的边界时,静态断言将失败.这表明,不管怎样,废弃分支中的代码也会被评估,即使它依赖于模板参数I.

根据cppreference,constexpr-if要求"丢弃的语句不能为每个可能的专业化形成错误",但我很难确定这是否是这种情况.

似乎GCC和Clang接受此代码没有问题(在Compiler Explorer上测试).

编译错误是否可以被C++标准接受,或者MSVC在此处不兼容?

(另外,如果标准不能保证我期望代码做什么,是否有另一种方法来完成嵌套的constexpr-if语句?)

Rak*_*111 13

gcc和clang是对的.如果丢弃的分支中唯一未被丢弃的语句是另一个语句,那将是非常反直觉的if constexpr.

[stmt.if] p2没有提及任何相关内容:

如果转换条件的值为,则第一个子语句废弃语句,否则第二个子语句(如果存在)是废弃语句.在封闭模板化实体(第17条)的实例化期间, 如果条件在其实例化之后不依赖于值,则不实例化丢弃的子语句(如果有的话).

强调我的.标准说丢弃的语句没有实例化,在你的情况下是else { /*... * }.该分支中的任何内容都未实例化,因此不允许编译器实例化任何内容,因此实例化MSVC是错误的std::tuple_element<I, std::tuple<int>>.