I'm using C++20, and I'm trying to implement a custom generator. I'm reusing an implementation of the Generator
from here: https://en.cppreference.com/w/cpp/coroutine/coroutine_handle
This example works well, but this generator doesn't work with std::ranges::views
:
// This loop works:
for (const char i : range(65, 91))
std::cout << i << ' ';
// This loop produces compiler error: no match for ‘operator|’ (operand types are ‘Generator’ and ‘std::ranges::views::__adaptor::_Partial’)
for (const char i : range(65, 91) | std::views::take(3))
std::cout << i << ' ';
So, as I understand the error message, I need to define the Generator<T>::operator|
as a template method for all possible ranges::views. I'm looking for a reference implementation of this method. Or a more generic question: what shall I do to pipe the result of the generator to any view, like that: range(65, 91) | std::views::take(3)
?
Update The cppreference link I'm providing above has an implementation of a Generator
and provides the following example of usage:
template<std::integral T>
Generator<T> range(T first, const T last)
{
while (first < last)
co_yield first++;
}
In my real code I'm using another function that defines an algorithm that produces values (and not necessarily integers). My goal is to improve the Generator
to make it possible to pipeline the output to a view.
Your Generator
's Iter
class does not satisfy the C++20 input_iterator
concept, which requires member types of value_type
/difference_type
as well as a postfix++
, which in turn makes the Generator
not satisfy the range
concept, so the range adaptor cannot be applied.
Adding these missing pieces allows compilation
class Iter
{
public:
using value_type = T;
using difference_type = std::ptrdiff_t;
Iter& operator++()
{
m_coroutine.resume();
return *this;
}
void operator++(int)
{
m_coroutine.resume();
}
// ...
};