javaLover
javaLover

Reputation: 6425

Constexpr variable captured inside lambda loses its constexpr-ness

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

Answers (2)

songyuanyao
songyuanyao

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.

GCC LIVE

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();
}

MSVC LIVE

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

P.W
P.W

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

Related Questions