在 lambda 中捕获的 Constexpr 变量失去了它的 constexpr-ness

Constexpr variable captured inside lambda loses its constexpr-ness

此代码在 g++(coliru), but not MSVC (godbolt 和我的 VS2017)中编译良好。

#include <type_traits>
#include <iostream>
template<class T> void f(){
    constexpr bool b=std::is_same_v<T,int>; //#1
    auto func_x=[&](){
        if constexpr(b){ //#error
        }else{
        }
    };
    func_x();
}
int main(){
    f<int>();
}

(6): error C2131: expression did not evaluate to a constant
(6): note: failure was caused by a read of a variable outside its lifetime
(6): note: see usage of 'this'

哪一个(g++ 或 MSVC)是错误的?
查看 'this' 的用法”中的 this 是什么??

如何在保持编译时保证的情况下解决这个问题?

在我的真实案例中,b (#1) 是一个复杂的语句,取决于其他几个 constexpr 变量。

Gcc 是对的。 b(作为 constexpr 变量)实际上不需要 captured

A lambda expression can read the value of a variable without capturing it if the variable

  • is constexpr and has no mutable members.

GCC LIVE

似乎如果制作 b static 那么 MSVC 可以访问 b 而无需捕获。

template<class T> void f(){
    constexpr static bool b=std::is_same_v<T,int>;
    auto func_x=[](){
        if constexpr(b){
        }else{
        }
    };
    func_x();
}

MSVC LIVE

How to work around it while keep the compile-time guarantee?

我们不能保持捕获变量的constexpr-ness。它们成为 lambda 闭包类型和 non-static data members can't be constexpr.

的非静态数据成员

How to work around it while keep the compile-time guarantee?

constexpr bool 标记为 static 是一种解决方法。

Demo

或者,您可以使用 if constexpr 中的条件,而不是将其分配给 bool。如下所示:

if constexpr(std::is_same_v<T,int>)

Demo

请注意,关于 lambda 表达式,constexpr MSVC 出现了错误。
其中之一是:problems with capturing constexpr in lambda
另一个是:if constexpr in lambda