Alex S.
Alex S.

Reputation: 1214

Lambda expression in list.erase

I'm learning lambdas and am trying various examples, and I'm not sure I see why this doesn't work:

std::list<int> listIntegers;
listIntegers.push_back(40);

listIntegers.erase([listIntegers]() {
return std::find(listIntegers.begin(), listIntegers.end(), 40);
});

I also tried to write explicitely:

listIntegers.erase([listIntegers]()->std::list<int>::const_iterator {
    return std::find(listIntegers.begin(), listIntegers.end(), 40);
    });

However this of course works:

auto found40Iterator = std::find(listIntegers.begin(), listIntegers.end(), 40)

listIntegers.erase(found40Iterator);

Upvotes: 1

Views: 60

Answers (1)

Fran&#231;ois Andrieux
Fran&#231;ois Andrieux

Reputation: 29022

Consider the case of

listIntegers.erase([listIntegers]()->std::list<int>::const_iterator {
    return std::find(listIntegers.begin(), listIntegers.end(), 40);
});

The capture list [listIntegers] is taking listInteger by value, a copy is stored with the lambda. Since the listIntegers used in std::find(listIntegers.begin(), listIntegers.end(), 40) is a copy of the original, it will find element 40 within that copy. The returned iterator is therefore an iterator to the element in the copy and not in the original. Iterators can only be used with other iterators from the same container and with their original container. The problem you are seeing is that your lambda's return value is being used with listIntegers but it actually refers to an element in a different range (the copy of listIntegers).

The solution is to change your capture list to take listIntegers by reference, so that it will operate on the original listIntegers. There is also the problem that you are not calling the lambda, you are instead passing it as an argument to erase. By adding a pair of parentheses we can instead call the lambda to and pass it's return value to erase.

listIntegers.erase([&listIntegers]() {
    // Added & here ^
    return std::find(listIntegers.begin(), listIntegers.end(), 40);
}());
//^ Call the lambda

Upvotes: 2

Related Questions