As for what you are currently asking; I do not believe anything exists yet. Now as for iterating over a container by some integer N
we can do the following; we can write our own for_each
type of function. I've written one below and it works like a gem! You may also want to look into the std::advance
function as well for it can be another possible implementation. I was checking that out myself as I was writing this function. However; as for c arrays I'm not sure there is much one can do without a bunch of extra code such as class templates, wrappers, etc. Here is my function.
#include <array>
#include <vector>
#include <iterator>
template<typename Container, typename Function>
void for_each_by_n( Container&& cont, Function f, unsigned increment_by = 1) {
if ( increment_by == 0 ) return; // must check this for no op
using std::begin;
auto it = begin(cont);
using std::end;
auto end_it = end(cont);
while( it != end_it ) {
f(*it);
for ( unsigned n = 0; n < increment_by; ++n ) {
if ( it == end_it ) return;
++it;
}
}
}
int main() {
std::array<int,8> arr{ 0,1,2,3,4,5,6,7 };
std::vector<double> vec{ 1.2, 1.5, 1.9, 2.5, 3.3, 3.7, 4.2, 4.8 };
auto l = [](auto& v) { std::cout << v << ' '; };
for_each_by_n(arr, l); std::cout << '\n';
for_each_by_n(vec, l); std::cout << '\n';
for_each_by_n(arr, l, 2); std::cout << '\n';
for_each_by_n(arr, l, 4); std::cout << '\n';
for_each_by_n(vec, l, 3); std::cout << '\n';
for_each_by_n(vec, l, 5); std::cout << '\n';
for_each_by_n(arr, l, 8); std::cout << '\n';
for_each_by_n(vec, l, 8); std::cout << '\n';
// sanity check to see if it doesn't go past end.
for_each_by_n(arr, l, 9); std::cout << '\n';
for_each_by_n(vec, l, 9); std::cout << '\n';
return 0;
}
-Output-
0 1 2 3 4 5 6 7
1.2 1.5 1.9 2.5 3.3 3.7 4.2 4.8
0 2 4 6
0 4
1.2 2.5 4.2
1.2 3.7
0
1.2
0
1.2
What I like about this example above is that not only can you increment through a loop by some integer N
; the above function also takes a function pointer
, function object
, functor
, or lambda
and it will perform the required action.
In your case you was trying to loop through your container by 2 for ever odd or every even index and within the loop you were printing the results. Here in my example; I'm printing the results in the form of a lambda that is being passed to this function.
However the only caveat with this particular implementation is that it will always start from index 0. You could easily expand on this by introducing another integer
parameter as to an offset of where the iteration will begin; but I'll leave that up to you to do as an exercise.
For the time being we have to settle for what C++11 through C++17 has to offer. In the near future we should have many new and powerful features with the release of C++20.
view::stride
might be what you're looking for (although I'm not sure how that works with plain arrays -std::array
should be fine though). – Tyebool isEven = false /* isOdd = true */; for(...) { if((isEven = !isEven)) { ... }; }
. I personally would rather just retain the original loop, though... – Cari<
. Iterators don't always have a<
, and more problematically, creation of iterators past the end is usually undefined behavior, so the only alternative is to singly step and compare every single iterator to the end (but only process the corresponding data on every other iteration). Therefore there will be iteration-skipping, even if it is hidden from you. If you don't like iteration-skipping, you can't use iterators. – Chanteuseif(distance(b, e) < n) advance(b, n); else b = e;
- sure, as is it would be possible to do so for non-RA, too, but both distance and advance would need to iterate over, thus inefficient... – Caridistance(it, e) < n
(ore - it < n
) could be done with no undefined behavior, just not a direct translation of the index for loop. Probably there should be someadvance_not_past(it, n, e)
function that is efficient for random access iterators and still optimal (single-pass) for others. – Chanteuse