如果 Constexpr 在 lambda 中,则编译器行为不同

if constexpr inside lambda, differing compiler behavior

本文关键字:编译器 Constexpr lambda 如果      更新时间:2023-10-16

请考虑以下代码。如果我对if constexpr的理解是正确的,则不应编译else分支,因此不应将z()视为错误。

#include <type_traits>
struct Z{};
template<typename T>
void f(T z) {
auto lam = [z]() {
if constexpr(std::is_same<T, Z>::value) {
} else {
z();
}
};
}
int main() {
f(Z{});
}

在 clang 和 gcc 中,这是编译的; 但对于最新的 MSVC,它不会。 不幸的是,Goldbolt 的 MSVC 太旧了,但在我完全更新的 VS 2017 机器上,cl /std:c++17产生:

Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26428.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.
if_constexpr.cpp
if_constexpr.cpp(10): error C2064: term does not evaluate to a function taking 0 arguments
if_constexpr.cpp(16): note: see reference to function template instantiation 'void f<Z>(T)' being compiled
with
[
T=Z
]

如果删除封闭的 lambda,代码将在所有三个编译器上进行编译。

我是否做错了什么或不受支持,或者只是一个 MSVC 错误?

这是一个MSVC错误。请提交错误报告。

来自 [stmt.if]/2 的规则是:

在封闭模板化实体的实例化期间,如果条件在其实例化后不依赖于值,则不会实例化丢弃的子语句(如果有(。

f<Z>的实例化过程中,当我们实例化条件时,我们得到true。这不是与值相关的,因此丢弃子语句(我们z()的子语句(不会被实例化。只有z()的实例化才会导致错误 - 它不应该发生。