Переменная constexpr, захваченная внутри лямбды, теряет свою запутанность

Этот код прекрасно компилируется в g++ (coliru), но не в MSVC (godbolt и my 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): ошибка C2131: выражение не оценивается как константа
(6): примечание: сбой был вызван чтением переменной вне ее времени жизни
(6): примечание: см. Использование этого

Какой (g++ или MSVC) не так?
Что this в "увидеть использование" это ""??

Как обойти это, сохраняя при этом гарантию времени компиляции?

В моем реальном случае b (#1) - сложное утверждение, зависящее от нескольких других переменных constexpr.

Ответ 1

ГКК прав. b (как constexpr переменной) не должны быть захвачены на самом деле.

Лямбда-выражение может прочитать значение переменной, не захватывая ее, если переменная

  • является constexpr и не имеет изменяемых членов.

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

А также

Как обойти это, сохраняя при этом гарантию времени компиляции?

Мы не можем сохранить единство для захваченных переменных. Они становятся нестатическими членами данных типа лямбда-замыкания, и нестатические члены данных не могут быть constexpr.

Ответ 2

Как обойти это, сохраняя при этом гарантию времени компиляции?

Маркировка constexpr bool как static служит constexpr bool.

Посмотреть демо

Кроме того, вы можете использовать условие в if constexpr вместо того, чтобы назначать его в bool. Как ниже:

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

Посмотреть демо

Обратите внимание, что для MSVC были обнаружены ошибки, связанные с constexpr отношении лямбда-выражений.
Одним из таких является: проблемы с захватом constexpr в лямбде
и другое: если constexpr в лямбде