26

Take the following code:

#include <array>

int main() {
    auto [a, unused] = [] {
        return std::array<int, 2>{42, 24};
    }();

    [&] {
        return a * 15;
    }();

    (void) unused;
}

Do not worry about the unused variable, I just want to destructure the array.

The code compiles fine with the latest GCC and MSVC, but Clang refuses to compile. Changing the capture list of the lambda does not change anything. Funny enough, setting explicitly a in the capture list raise the error that a is not a variable.

I am quite sure this is a bug, but I wanted to ask, mainly because AFAIK a is a reference to the first element of the array (with the lifetime extended to the main scope in this case), not just an int, correct me if I am wrong.

Edit

As you can see from the other question, the problem is that a and unused are not variables (yes, Clang is right!), but reference names, which cannot be captured by lambdas. Nevertheless, if you really need something like this, you can use a local variable for the lambda, like this:

#include <array>

int main() {
    auto [a, unused] = [] {
        return std::array<int, 2>{42, 24};
    }();

    [&, a = a] {
        return a * 15;
    }();

    (void) unused;
}

In this case the object is copied, which is fine with trivially copiable objects. In other case you could use something like

[&, r = std::ref(uncopiable_obj)] {
    return r.get().do_something();
}();

Said that, I do not like these workaround, because they are very unclear and lower the expressiveness of the code. IHMO it is better to use other, cleaner, solutions.

Barry
  • 286,269
  • 29
  • 621
  • 977
dodomorandi
  • 1,143
  • 1
  • 11
  • 18

0 Answers0