[Bug libstdc++/81482] New: by-value lambda capture in remove_if
fabian-gcc at kloetzl dot info
gcc-bugzilla@gcc.gnu.org
Wed Jul 19 09:28:00 GMT 2017
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81482
Bug ID: 81482
Summary: by-value lambda capture in remove_if
Product: gcc
Version: unknown
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: fabian-gcc at kloetzl dot info
Target Milestone: ---
Hi all,
There is a little quirks with `remove_if` and lambdas that mutably capture by
value. As a contrived example let's print all the odd numbers from a list and
also count how many elements were removed already.
----
#include <vector>
#include <algorithm>
#include <cstdio>
int main(int argc, char *argv[])
{
auto numbers = std::vector<int>{0,1,2,3,4,5,6,7,8,9};
auto count = 0;
auto odd = [=] (int n) mutable {
if (n & 1) {
printf("%i %i\n", n, count);
count++;
return true;
}
return false;
};
std::remove_if(std::begin(numbers), std::end(numbers), odd);
return 0;
}
----
Note that the use of `printf` is to avoid a libc++ bug [1].
The expected output is as follows.
----
1 0
3 1
5 2
7 3
9 4
----
However, with GCC 7.1.1 and libstdc++ 3.3.6 (current arch) the output is
different.
----
1 0
3 0
5 1
7 2
9 3
----
Clang with libc++ produces the desired output. As far as I can tell, both
behaviours are correct, according to the standard. But I guess the second is
unexpected.
A possible fix would be to pass the lambda by reference to `find_if`, instead
of by-value which makes an implicit copy [2]. That is how libc++ does it [3].
Some other standard algorithms might also be affected by this, didn't check. ☺
Best,
Fabian
[1]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=808086
[2]:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_algo.h#L863
[3]:
https://github.com/llvm-mirror/libcxx/blob/master/include/algorithm#L2218-L2219
More information about the Gcc-bugs
mailing list