Elegantly exclude part of an operation for the last iteration in a loop I'm afraid just about everybody who read this question has misunderstood it. I'm not trying to find the best way of printing a vector. I'm trying to find the best way of excluding part of an operation from the last iteration in a loop. I'm seeking advice about a pattern that is repeated is many different contexts. For this reason, I cannot provide a concrete example.

This question is off-topic



A well-formed comma-separated list has commas after all but the last element. This means that when dealing with these lists, the comma has to be dealt with on all but the last iteration. This is how I do things currently:

for (auto e = vec.cbegin(); e != vec.cend(); ++e) {
  // code that has to be executed for every element
  std::cout &lt;&lt; *e;
  if (e != vec.cend() - 1) {
    // code that must not be executed for the last element
    std::cout &lt;&lt; ", ";
  }
}


There are five instances of the above pattern in the project that I'm working on. I feel like there might be a more elegant way of doing this. An alternative that I've come up with is this:

// infinite loop if vec is empty
if (!vec.empty()) {
  for (auto e = vec.cbegin(); e != vec.cend() - 1; ++e) {
    // code that has to be executed for every element
    std::cout &lt;&lt; *e;
    // code that must not be executed for the last element
    std::cout &lt;&lt; ", ";
  }
  // code that has to be executed for every element
  std::cout &lt;&lt; vec.back();
}


This alternative is slightly faster because there isn't an if in the body but that's not a big deal. The if is true for all but the last iteration so the branch predictor will probably only miss on the last iteration. I also have to repeat code that has to be executed for every element which means that I need to hoist that into a function. 

The first snippet is the best that I can come up with but I feel like this could be done better. Note that writing to std::cout is just an example.
If you are just doing a single-shot printing of a container, just print the first element and then print delim-value pairs.  This reduces the iterator requirements to being equality comparable, dereferenceable, and incrementable.

if (!vec.empty()) {  // invert to return immediately if this is a function
    auto first = vec.cbegin();
    std::cout &lt;&lt; *first;

    while (vec.cend() != ++first) {
        std::cout &lt;&lt; ", " &lt;&lt; *first;
    }
}


There is also a stateful approach that reduces the operation strength from branching on whether to print the delimiter to a pointer assignment.

auto actual_delim = ", ";
auto delim = "";

for (const auto&amp; elem : vec) {
    std::cout &lt;&lt; delim &lt;&lt; elem;
    delim = actual_delim;
}


See infix_iterator where this stateful approach is used.