Reputation: 484
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
Upvotes: 8
Views: 238
Reputation: 39788
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.
Upvotes: 4