New paper: N3587, For Loop Exit Strategies -- Alan Talbot

A new WG21 paper is available. A copy is linked below, and the paper will also appear in the next normal WG21 mailing. If you are not a committee member, please use the comments section below or the std-proposals forum for public discussion.

Document number: N3587

Date: 2013-03-17

For Loop Exit Strategies

by Alan Talbot

Excerpt:

This proposal suggests an enhancement to for iteration statements to allow the programmer to specify separate blocks of code that execute on completion of a for loop; one for normal termi-nation (when the loop condition is no longer met) and the other for early termination (when the loop is exited with a break). This feature would be especially useful in range-based for statements.

Add a Comment

Comments are closed.

Comments (5)

2 0

mmocny said on Mar 19, 2013 12:05 PM:

I would love to see a comparison to library based solutions to this problem:

forEach(range, body, onsuccess, onerror) // onerror called on early exit

where body has a signature like "bool(T element, size_t index)" // return means "should_break"

This type of library solution could also be written to support a "between" callable (called between loop bodies, but not before first/after last element) etc. I'm not sure I see sufficient evidence of langage solution, especially given the amazing stuff happening with lambdas becoming easier to use.
0 0

bkuhns said on Mar 19, 2013 12:45 PM:

And this (considering mmocny's comments) is exactly why the range-base for syntax should have never been accepted in favor of making for_each(v, [](auto el) do_something(el)); possible.
1 0

Greg Marr said on Mar 20, 2013 11:17 AM:

bkuhns, that wouldn't help here. There's still a need for a way to exit early. What you ask is actually possible though, as long as you don't need the std:: on the front of it:

[div class="codeblock"] template<typename Ctypename FF for_each(&collF pFunc)
    
{
    using std
::begin;
    
using std::end;
    return(
std::for_each(begin(coll), end(coll), pFunc));
    
[/div]

"I would love to see a comparison to library based solutions to this problem:"

This is just off the top of my head, I haven't actually used this, and I'm on the fence whether this should be considered an abuse of find_if:

[div class="codeblock"] template<typename Ctypename F>
auto find_if(&collF pFunc) -> decltype(std::begin(coll))
    
{
    
return(std::find_if(std::begin(coll), std::end(coll), pFunc));
    
}

    auto last 
find_if(c[&](Foo const &v) -> bool
        {
        
if(some_condition(v))
            return(
true);
        
do_something(v);
        return(
false);
        
});

    if(
last == std::end(c))
        
something();
    else
        
do_something_else(last); 
[/div]

or if you want it all in a single function:

[div class="codeblock"] template<typename Ctypename Ptypename Ntypename E>
void for_each_extended(&collP predN normalE early)
    
{
    auto i 
find_if(collpred);
    if(
== std::end(coll))
        
normal();
    else
        
early(*i);
    
}

    for_each_extended
(c[&](Foo const &v) -> bool
        {
        
if(some_condition(v))
            return(
true);
        
do_something(v);
        return(
false);
        
},
    
[&]() { something(); },
    
[&](Foo const &v{ something_else(v); }); 
[/div]

"especially given the amazing stuff happening with lambdas becoming easier to use."

If I understand the proposed lambda changes correctly, that would give us this:

[div class="codeblock"] for_each_extended(c[](auto v)
        
{
        
if(some_condition(v))
            return(
true);
        
do_something(v);
        return(
false);
        
},
    
[] something(),
    
[](auto vsomething_else(v)); 
[/div]
0 0

mmocny said on Mar 20, 2013 12:08 PM:

@Greg Marr I love what you've provided, and is entirely along the lines of what I was thinking. This would be a great addition to the standard library, especially if ranges are accepted.
0 0

bkuhns said on Mar 20, 2013 07:02 PM:

@Greg Marr, nice implementation. Notice your final example using the proposed lambda syntax could be a parameter overload to the small example I gave. Had we focused on making lambdas and the std algorithms more terse for C++11 rather than going with range-based for, the OP proposal would be very different. It would be asking for a library extension rather than a language one.

I believe Herb Sutter mentions in his talk, "Lambdas, Lambdas Everywhere", that he would have preferred a concise std::for_each() syntax over range-based for. No idea if he still feels that way, but this proposal seems to be a good example of the consequences.