Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Deducing-This lambda require `this` to be a reference or capturing variables by reference?

Why does this code output garbage on GCC, like there is UB?

auto data = std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto output = [data](this auto self, size_t i) {
    if (i >= 10) {
        return;
    }
    std::print("{}, ", data[i]);
    self(i + 1);
};
output(0);

Changing to capture data by reference or self as a reference makes it look fine.

Compiler Explorer snippet

like image 520
Sprite Avatar asked Feb 14 '26 00:02

Sprite


1 Answers

I can narrow it down: It's a GCC bug, featured at least in version 15.2, where for an object created by a lambda expression with deduced this by value, the initialization code isn't produced if any of the captures by value is a type with not-defaulted copy or move constructors. A simplest test case here returns 1, whenever at least one constructor of the two is user-defined as not-default:

struct A {
  A() {};
  A(const A&) {}
  //A(const A&) = default;
  A(A&&) {}
  //A(A&&) = default;
  int n = 42;
};

int main() {
   auto l = [data = A()](this auto) {
     return data.n != 42;
   };
  return l();
}

If the lambda expression would have other captures, they would not be initialized either, and capture-by-reference turns into capture-by-value, having a unique address, but uninitialized.

The default constructor don’t have any effect on this behaviour.

like image 55
Swift - Friday Pie Avatar answered Feb 16 '26 12:02

Swift - Friday Pie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!