Hooked Hooked - 1 year ago 60
C++ Question

Can range-based for loops be aware of the end?

Given the minimal C++11 STL example:

set<int> S = {1,2,3,4};
for(auto &x: S) {
cout << x;
cout << ",";

Is there a way to check if
is the one right before the end? The goal in this example is to output
and not the final comma at the end. Currently I use a standard for loop with two iterators,

set<int>::const_iterator itr;
set<int>::const_iterator penultimate_end_itr = --S.end();
for(itr=S.begin(); itr!=penultimate_end_itr;++itr)
cout << (*itr) << ',';
cout << (*penultimate_end_itr);

Which works, but is terribly cumbersome. Is there a way to do the check within the range-based for loop?

EDIT: The point of the question is not to print out a comma separated list. I want to know if a range-based for loop has any knowledge of the penultimate element in the list (i.e. is it one before the end). The minimal example was presented so we all have a common code block to talk about.

Answer Source

The very purpose of range-based for loops is to forget the iterator. As such, they only allow you access to the current value and not the iterator. Would the following code do it for you?

set<int> S = {1,2,3,4};

std::string output;
for(auto &x: S) {    
   if (!output.empty())
       output += ",";
    output += to_string(x);

cout << output;


Another solution: Instead of comparing iterators (as one would do with "normal" for loops), you could compare the addresses of the values:

set<int> S = {1,2,3,4};
auto &last = *(--S.end());
for (auto &x : S)
    cout << x;
    if (&x != &last)
        cout << ",";