【问题标题】:if constexpr inside lambda, differing compiler behavior如果 constexpr 在 lambda 内,则编译器行为不同
【发布时间】:2018-05-16 13:23:48
【问题描述】:

考虑以下代码。如果我对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 错误?

【问题讨论】:

  • 众所周知,MSVC 对 C++ 特性的支持很差。多年来一直如此,永远不会改变。您可能需要定义重载 void f(Z z); 作为解决方法。
  • 如果 gcc 和 clang 同意而 MSVC 不同意,那么它有 99% 的可能性是 MSVC 中的一个错误 :)
  • @bipll 实际上,最近几个月它变得更加符合标准:)
  • 您使用的是什么版本的 MSVS?如果 constexpr 是最近才添加的并且一开始就有问题
  • 我不想费心分析这个,因为现在是星期三下午,但我只想说上面的那些人可能是对的。毕竟,这就是if constexpr 的全部意义所在。

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


【解决方案1】:

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

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

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

f&lt;Z&gt;的实例化过程中,当我们实例化条件时,我们得到true。这不依赖于值,因此不实例化丢弃子语句(我们在其中执行 z() 的语句)。只有z() 的实例化会导致错误——而且它不应该发生。

【讨论】:

    猜你喜欢
    • 2021-05-03
    • 1970-01-01
    • 2016-11-01
    • 2017-07-03
    • 1970-01-01
    • 2020-05-21
    • 2021-01-30
    • 2019-10-14
    • 2023-04-10
    相关资源
    最近更新 更多