Iterating over a vector works:
std::vector<int> collection = {2, 3, 4, 5435345, 2};
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;});
but not over a set (compile error):
std::set<int> collection = {2, 3, 4, 5435345, 2};
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;});
Why can't I iterate over a std::set
with std::for_each
?
Bonus question:
Also, I would like to change the int&
in the lambda's argument to auto&
, why can't this be automatically deduced?
Iterating over a Set using Iterators set::begin() returns an iterator pointing to the first element in set. Whereas, set::end() returns an iterator past the end of set. Now to iterate a set in forward direction, we need to create an iterator and initialise it with set::begin().
std::for_each is an STL algorithm that takes a collection of elements (in the form of a begin and end iterator) and a function (or function object), and applies the function on each element of the collection. It has been there since C++98.
for_each loop in C++ This loop accepts a function which executes over each of the container elements. This loop is defined in the header file “algorithm”: #include<algorithm>, and hence has to be included for successful operation of this loop. It is versatile, i.e. Can work with any container.
Per the C++ standard, iteration over the elements in an std::set proceeds in sorted order as determined by std::less or by the optional comparison predicate template argument.
std::set<T>::value_type
is T const
, not T
; consequently, the argument to your lambda must be a value type (i.e., copy) or int const&
(and technically, or int const volatile&
), not int&
. I.e., this works:
std::set<int> collection{2, 3, 4, 5435345, 2};
std::for_each(
collection.begin(),
collection.end(),
[](int const& i) { std::cout << i << std::endl; }
);
Bonus question: Also, I would like to change the
int&
in the lambda's argument toauto&
, why can't this be automatically deduced?
Because the standard says it can't; historically, I believe this was due to overly-complicated interactions between lambdas and concepts (before concepts were removed from the draft). However, I hear rumors that the first defect reports to the new (C++11) standard will address exactly this, so it's possible that you'll see support for this added to your compiler of choice within the next year or two. EDIT: Oh, look, C++14 now has polymorphic lambdas...
Concerning the bonus question: An "auto" function argument isn't specific to lambdas. You might as well ask why we don't allow all functions to be declared as f(auto x, auto y)
. But that just means that you essentially want to replace all functions by function templates. That was considered not to work well with the existing C++ language and the type system in particular. If you want a function template, there's already an existing syntax and mechanism, and declaring "auto" arguments is not the way to go.
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