Переменная 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 в лямбде