Переменная constexpr, захваченная внутри лямбды, теряет свою запутанность - PullRequest
19 голосов
/ 13 марта 2019

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

Какой из них (g ++ или MSVC) неправильный?
Что такое this в ", см. Использование" this " "??

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

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

Ответы [ 2 ]

14 голосов
/ 13 марта 2019

Gcc это правильно.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-ness для захваченных переменных.Они становятся нестатическими элементами данных типа лямбда-замыкания, и нестатические элементы данных не могут быть constexpr.

7 голосов
/ 13 марта 2019

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

Обозначение constexpr bool как static служит обходным решением.

См. Демо

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

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

См. Демо

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

...