Reputation: 30028
I am trying to implement repeat n times using C++20 ranges.
It works, but all approaches I can think of need a dummy variable (one for the for
loop variable, other for arity of lambda).
static constexpr int kIterations = 3;
void f1(){
auto c = '.';
for (const auto _ :std::views::iota(0)| std::views::take(kIterations) ) {
std::cout << c;
}
std::cout << std::endl;
}
void f2(){
auto c = '.';
std::ranges::for_each(std::views::iota(0)| std::views::take(kIterations), [&c](const auto _) {
std::cout << c;
});
std::cout << std::endl;
}
Is there a way to do this with C++20 ranges without the need for dummy variable (_
in my case, but even unnamed requires const? auto).
notes:
repeat_n
iota
has version that takes 2 integers, it might be more readable, but still does not fix the problem with dummy variables.Upvotes: 2
Views: 1304
Reputation: 28406
If you could use both C++20 <ranges>
and repeat_n
from Range-v3, then this could be an approach?
#include <algorithm>
#include <functional>
#include <iostream>
#include <boost/hof/lift.hpp>
#include <range/v3/view/repeat_n.hpp>
#include <ranges>
using ranges::views::repeat_n;
using namespace std::ranges::views;
using namespace std::ranges;
auto constexpr invoke = BOOST_HOF_LIFT(std::invoke); // what a pity we need this
static constexpr int kIterations = 3;
void f() {
char c = '.';
for_each(repeat_n([c]{ std::cout << c << std::endl; },
kIterations),
invoke);
}
int main()
{
f();
}
The lambda [c]{ std::cout << c << std::endl; }
is nullary as it isn't passed any value, and there's no for
loop with a dummy variable.
Upvotes: 2
Reputation: 473407
A range is a means of iterating over a set of values. You can manufacture those values on demand rather than accessing them from storage, as iota
does. But ranges are about iterating over a sequence of values.
So any range-based iteration mechanism is going to involve an object representing, at least, the current position in the range. That's just the nature of the beast.
Yes, you could write your own version of ranges::for_each
which "iterates" over a range but doesn't actually pass those values to the functor:
template<std::ranges::input_range Rng, std::invocable Func>
decltype(auto) iterate_no_element(Rng &&rng, Func func)
{
return std::ranges::for_each(std::forward<Rng>(rng), [func](auto const&){func();})
}
But the standard has no such function.
Upvotes: 4