Hi Sophie,
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';
}