c++ - 如果 constexpr 在 lambda 内,则编译器行为不同
问题描述
考虑以下代码。如果我的理解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()
导致错误的实例化 - 它不应该发生。
推荐阅读
- git - Git日志显示奇怪的作者姓名
- javascript - Firestore:引用类型。如何等待每个结果的所有 get() 调用
- ios - 导航控制器在推送到视图控制器之前延迟
- ocaml - OCaml 将抽象类型从一个模块传递到另一个模块
- postgresql - postgres docker以代码1退出并且exec用户进程导致“没有这样的文件或目录”
- c++ - 将结构数组传递给抛出未定义引用c ++的函数的问题
- linux - 如何获取共享内存的物理地址
- ios - 请在 ScrollView 中编码布局
- javascript - Nativescript getElementsByClassName() 错误
- python - 将两个矩阵 (2x1) 和 (2x2(