首页 > 解决方案 > 如果 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{});
}

clanggcc中编译;但对于最新的 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 错误?

标签: c++templatesc++17if-constexpr

解决方案


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

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

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

在实例化的过程中f<Z>,当我们实例化我们得到的条件时true。这不依赖于值,因此z()不实例化丢弃子语句(我们所做的那个)。这只是z()导致错误的实例化 - 它不应该发生。


推荐阅读