I have the following code snippet, which takes the std::vector<int> list
and writes a zero in all vector elements. This example is working perfectly fine.
#include <vector>
#include <iostream>
#include <algorithm>
int main () {
std::vector<int> list {1, 1, 2};
auto reset = [](int & element){element = 0;};
auto print = [](int element) {std::cout << element << " ";};
std::for_each(list.begin(), list.end(), reset);
std::for_each(list.begin(), list.end(), print);
}
If I take change the type of the vector from int
to bool
, the code will not compile.
#include <vector>
#include <iostream>
#include <algorithm>
int main () {
std::vector<bool> list {true, true, false};
auto reset = [](bool & element){element = false;};
auto print = [](int element) {std::cout << element << " ";};
std::for_each(list.begin(), list.end(), reset);
std::for_each(list.begin(), list.end(), print);
}
https://godbolt.org/g/2EntgX
I don't understand the compiler error message:
/opt/compiler-explorer/gcc-7.2.0/lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/stl_algo.h:3884:2: error: no matching function for call to object of type '(lambda at :7:18)'
__f(*__first); ^~~
:10:10: note: in instantiation of function template specialization 'std::for_each:7:18)>' requested here
std::for_each(list.begin(), list.end(),reset); ^
:7:18: note: candidate function not viable: no known conversion from 'std::_Bit_iterator::reference' (aka 'std::_Bit_reference') to 'bool &' for 1st argument
auto reset = [](bool & element){element = false;}; ^
:7:18: note: conversion candidate of type 'void (*)(bool &)'
Why does std::foreach
work with a std::vector<int>
, but does not work with a std::vector<bool>
?
Is the memory optimisation of an std::vector<bool>
(see here ) part of the answer?
The problem stems from the fact that dereferencing an iterator that came from std::vector<bool>
doesn't return bool&
, but rather a proxy object. Thus, it is not regarded as stl container (thanks to @KillzoneKid).
Use auto element
in the parameter list. In general, if you don't care about the type, use auto&&
in the lambda parameter list.
#include <vector>
#include <iostream>
#include <algorithm>
int main () {
std::vector<bool> list {true, true, false};
auto reset = [](auto && element){element = false;};
auto print = [](int element) {std::cout<< element << " ";};
std::for_each(list.begin(), list.end(),reset);
std::for_each(list.begin(), list.end(),print);
}
Demo.
Trying to use auto&
will trigger compilation error again, as the proxy returned is not lvalue, but rvalue. Thus, auto&&
has even more benefits than usual.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With