Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::for_each over std::set, C++11

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?

like image 990
eisbaw Avatar asked Nov 14 '11 22:11

eisbaw


People also ask

How to loop over a set in c++?

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().

What is std :: For_each?

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.

What does for_ each do c++?

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.

Is std :: set ordered?

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.


2 Answers

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 to auto&, 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...

like image 151
ildjarn Avatar answered Oct 07 '22 02:10

ildjarn


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.

like image 30
Kerrek SB Avatar answered Oct 07 '22 02:10

Kerrek SB