How are Lambda Identifiers Captured?

Viewed 174

I have posted this answer, which contains the code:

template <typename T>
auto vertex_triangle(const size_t index, const vector<pair<T, T>>& polygon) {
    const auto& first = index == 0U ? polygon.back() : polygon[index - 1U];
    const auto& second = polygon[index];
    const auto& third = index == size(polygon) - 1U ? polygon.front() : polygon[index + 1U];

    return [&](auto& output){ output.push_back(first);
                              output.push_back(second);
                              output.push_back(third); };
}

I was thinking that first, second, and third could really be used as lambda identifiers like this:

[first = index == 0U ? polygon.back() : polygon[index - 1U],
 second = polygon[index],
 third = index == size(polygon) - 1U ? polygon.front() : polygon[index + 1U]](auto& output){ output.push_back(first);
                                                                                             output.push_back(second);
                                                                                             output.push_back(third); };

But I only want to capture by constant reference. Without specifying a type in the identifier how can I do this?

1 Answers

You can't1. There is no place to put a cv-qualifier in a lambda capture list. You can have a look at the relevant grammar:

init-capture:
    identifier initializer
    & identifier initializer

You also can't specify the type in a capture list (see grammar above).

What you can do however is capture by non-const reference by putting a & before the names:

[&first = index == 0U ? polygon.back() : polygon[index - 1U],
 &second = polygon[index],
 &third = index == size(polygon) - 1U ? polygon.front() : polygon[index + 1U]](auto& output){ output.push_back(first);
                                                                                             output.push_back(second);
                                                                                             output.push_back(third); };

Or just stick to your first snippet, which is way more readable too IMO.


1 polygon is const, so in your case, first, second and third will actually be const if you capture them by reference in the capture list! But if it weren't, then no, for the reasons stated above.

Related