如果 Constexpr 在 lambda 中,则编译器行为不同
if constexpr inside lambda, differing compiler behavior
请考虑以下代码。如果我对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()
的实例化才会导致错误 - 它不应该发生。
相关文章:
- 编译器生成的默认构造函数具有 constexpr 混淆行为
- 如果在 lambda 中使用 Constexpr static_assert,哪个编译器是正确的?
- G++ 编译器是否在未使用返回值的情况下将 constexpr 函数视为常规函数?
- 编译器如何知道C++constexpr计算不会触发未定义的行为
- 没有编译器支持Constexpr Memcpy的bit_cast可能吗?
- 为什么编译器无法弄清楚构造函数实际上是 constexpr?
- 静态 constexpr 的编译器优化
- 如何让编译器忽略这个计算结果为 false 的 if-constexpr?
- 如果 Constexpr 在 lambda 中,则编译器行为不同
- 如果递归通用 lambda 中的 constexpr:不同的编译器行为
- "如果 constexpr",在 lambda 内部,在包扩展内部 - 编译器错误?
- 表达式未评估为常数两个级别的constexpr函数(编译器错误?)
- 使用constexpr c-string作为编译器错误消息
- 为什么我的编译器显示有关我的 constexpr 函数的此错误?
- 跨编译器的 constexpr 成员函数的重载解析不一致
- 如何使我的C 编译器发出constexpr值(例如警告?)
- 将默认赋值运算符声明为 constexpr:哪个编译器是正确的?
- 引用基类的 constexpr 构造函数因编译器而异
- 从编译器优化和代码性能的角度来看,"if constexpr"与"if"
- 编译器之间在丢弃的 if constexpr(false) 语句中实例化模板的行为不一致