Reputation: 6425
This code compiles fine in g++ (coliru), but not MSVC (godbolt and 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): 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'
Which one (g++ or MSVC) is wrong?
What is this
in "see usage of 'this'"??
How to work around it while keep the compile-time guarantee?
In my real case, b (#1)
is a complex statement depends on a few other constexpr variables.
Upvotes: 22
Views: 2505
Reputation: 172894
Gcc is right. b
(as constexpr
variable) doesn't need to be captured in fact.
A lambda expression can read the value of a variable without capturing it if the variable
- is constexpr and has no mutable members.
It seems if making b
static
then MSVC could access b
without capturing.
template<class T> void f(){
constexpr static bool b=std::is_same_v<T,int>;
auto func_x=[](){
if constexpr(b){
}else{
}
};
func_x();
}
And
How to work around it while keep the compile-time guarantee?
We can't keep the constexpr-ness for the captured variables. They become non-static data members of the lambda closure type and non-static data members can't be constexpr
.
Upvotes: 18
Reputation: 26800
How to work around it while keep the compile-time guarantee?
Marking the constexpr bool
as static
serves as a work around.
See Demo
Alternately, you can use the condition in the if constexpr
instead of assigning it to a bool
. Like below:
if constexpr(std::is_same_v<T,int>)
See Demo
Note that there have been bugs raised for MSVC regarding constexpr
with respect to lambda expressions.
One such is: problems with capturing constexpr in lambda
and another is: if constexpr in lambda
Upvotes: 11