when() loop

1,093 views
Skip to first unread message

Sophie Schmidt

unread,
Mar 12, 2019, 6:05:57 AM3/12/19
to ISO C++ Standard - Future Proposals
Hello,

I've been writing some code to process vectors of classes by using for and for_each loops. Instead of having long checks in the loop definition and/or the body section of a loop, I was thinking of a kind of loop that only jumps into its body, when the condition is true.


normal:

when(def; con; amount; iter)
{}

def: value definition
con: condition when the body is to be executed
amount: loop is executed until n true conditions have occurred. if amount = 0, then execute the loop until it hits break
ite: iterator

Example: jumps into the body part once the condition is true
when(int i = 0; vectorList[i].get_pid() == myPid; 3; i++)
{
    cout << "occurrence found at: " << i;
}



for each of vector/array:

when_each(vectorList.begin().get_pid() == myPid)
{
    cout << "occurrence found";
}
Message has been deleted
Message has been deleted

Magnus Fromreide

unread,
Mar 13, 2019, 2:23:50 PM3/13/19
to std-pr...@isocpp.org
On Tue, Mar 12, 2019 at 03:05:57AM -0700, Sophie Schmidt wrote:
> Hello,
>
> I've been writing some code to process vectors of classes by using for and
> for_each loops. Instead of having long checks in the loop definition and/or
> the body section of a loop, I was thinking of a kind of loop that only
> jumps into its body, when the condition is true.
>
>
> normal:
>
> when(def; con; amount; iter)
> {}
>
> def: value definition
> con: condition when the body is to be executed
> amount: loop is executed until n true conditions have occurred. if amount =
> 0, then execute the loop until it hits break
> ite: iterator
>
> Example: jumps into the body part once the condition is true
> when(int i = 0; vectorList[i].get_pid() == myPid; 3; i++)
> {
> cout << "occurrence found at: " << i;
> }
>

Could you please express your idea using current C++.

when (def; con; amount; iter)
statement;

is a simplification, it is equivalent to what?

Remember that all of for, while, do-while and so on can be written using
goto (or while) so this is not an academic question but a way to find bugs
in your proposal.

One example of a bug is that you say nothing about what the purpose of
iter is.

/MF

Jake Arkinstall

unread,
Mar 13, 2019, 3:03:31 PM3/13/19
to std-pr...@isocpp.org
Hi Sophie,

With Ranges being accepted into C++20, we will effectively have this: https://en.cppreference.com/w/cpp/ranges

It's more verbose (you're explicitly piping the container through a filter and iterating over the values that pass through it), but it's also incredibly powerful and makes more complex loops much easier to work with. I think it will be a long time before we see much work in the direction of loop helpers that don't involve Ranges.

So what are your options if you want this functionality now?

One thing that you can do is use std::find (or std::find_if) for initialising the iterator, and for incrementing it. You can then either have that in a for loop (though it would be ugly, but see below) or define a set of iterators that increment in a custom way, provide the begin and end functions, and loop through it in a range based for. The downside is that these iterators need to carry a reference to the container to be able to know where container.end() is (otherwise the last matching value will keep trying to find the next match, far beyond the bounds of the container). Or you can do as many others before you have done and use a macro.

#define when(variable, container, condition) \
    for( \
         auto variable = std::find_if(container.begin(), container.end(), condition); \
         variable != container.end(); \
         variable = std::find_if(variable + 1, container.end(), condition) \
    )

usage:

#include<algorithm>
#include<vector>
#include<iostream>
int main() {
    std::vector<int> test{1,2,3,4,5,6,7,8,9};
    when(it, test, [](int const& x){ return (x % 2 == 1)){
        std::cout << *it << '\n';
    }
}

But all of this is inflexible and doesn't give you the option of using it as a view for something else to use. For that you either want to write your own view over the container, or wait for C++20.


Theres also a trick you can use that's already in the language. It doesn't require all that silly messing around with iterators or std algorithms either.

for(int const& x : test) if(x % 2 == 1){
    std::cout << x << '\n';
}

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4fd6b5bd-f2af-4e8a-9259-6e6aafc6e173%40isocpp.org.

Cleiton Santoia

unread,
Mar 13, 2019, 3:05:30 PM3/13/19
to ISO C++ Standard - Future Proposals

1 Another algorithm "std::for_each_if" with an extra parameter for the condition ?

2 range::view ?
Reply all
Reply to author
Forward
0 new messages