I have the following snippet which has an object with a compile-time value:
template <int V>
struct Value
{
constexpr Value() = default;
constexpr int value() const { return V; }
};
int main()
{
Value<1> v;
static_assert(v.value(), ""); // OK
auto l = [=]()
{
static_assert(v.value(), ""); // Error
};
(void)l;
}
The problem is in the static_assert within the lambda. It passes on gcc 6.4, 10.1 but fails on 7.1 and 8.1. The first assert (outside of the lamda) passes on all of them. If changed to constexpr Value<1> v;, it starts passing on 7.1 but not 8.1. I was wondering why this is happening.
Demo: https://godbolt.org/z/4z7vdKGMq
gcc 8.1 contained a compiler bug that prevented lambda captures from being constexpr:
Bug 86429 - [8 Regression] lambda capture breaks constexpr-ness
It was fixed in 8.4, but not backported to previous versions. So gcc versions 8.1 - 8.3 still contain this bug, preventing the captured v from being treated as constexpr.
For 7.1 i'm not 100% sure since i didn't manage to find a bug for it; but given that it rejects some constructs even with constexpr my guess would be that it is a precursor-bug to the 8.1 one that just happend to remain unnoticed.
It fails with exactly the same error message - '__closure' is not a constant expression - if an explicit capture clause is used:
godbolt
constexpr Value<1> v;
static_assert(v.value(),""); // OK
auto l = [v]() {
static_assert(v.value(),""); // OK (Error in 7.1)
};
auto l2 = [&v]() {
static_assert(v.value(),""); // OK (Error in 7.1)
};
auto l3 = [=]() {
static_assert(v.value(),""); // OK
};
auto l4 = [&]() {
static_assert(v.value(),""); // OK
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With