Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

constexpr variable not captured

The following code does not compile in clang (it does in GCC):

struct A{
    int a;
};

auto test(){
    constexpr A x{10};
    return []{
        return x; // <-- here x is A: clang doesn't compile
    }();
}

Clang's error is variable 'x' cannot be implicitly captured in a lambda with no capture-default specified, but I thought that constexpr variables were always captured.

If x is an int, the code compiles:

auto test(){
    constexpr int x{10};
    return []{
        return x; // <-- here x is int: clang is ok
    }();
}

Interestingly, the following code also compiles:

auto test(){
    constexpr A x{10};
    return []{
        return x.a;
    }();
}

Is clang right? If so, what is the rationale? I'm using -std=c++17

--EDIT--

The following question: Can I use a constexpr value in a lambda without capturing it? is not related to this one, as with clang11 it is not anymore an issue: in fact, as stated above, if x is an int, clang11 compiles.

Sample code also present in https://godbolt.org/z/rxcYjz

like image 719
Mario Demontis Avatar asked Dec 09 '20 22:12

Mario Demontis


1 Answers

When you return x; in the first example, you have to invoke A’s copy constructor, which involves binding a reference to x and thus odr-uses it. The argument can be made that a trivial copy of a value usable in constant expressions shouldn’t constitute an odr-use any more than return x.a;, but there’s no such exception in that rule, so Clang is correct to reject it.

As a practical matter, you can of course make any constexpr variable static to avoid any need to capture it.

like image 180
Davis Herring Avatar answered Sep 21 '22 12:09

Davis Herring