Kai
Kai

Reputation: 5910

C++20 Coroutines and iostream

I am playing around with C++ 20's Coroutines. The sample is compiled with clang++.

The compiler error I am facing is

error: invalid operands to binary expression ('std::ostream' (aka 'basic_ostream') and 'cppcoro::generator')

which is about the following line

std::cout << numbers << " ";  

the full code snipped looks like this:

#include <thread>
#include <iostream>
#include <vector>
#include <cppcoro/generator.hpp>

using namespace std;

// coroutine
cppcoro::generator<int> generatorForNumbers(int begin, int inc = 1) 
{
  // for Schleife ohne Abbruchbedingung
  for (int i = begin;; i += inc) 
  {
    co_yield i;
  }  
}

int main() 
{

    auto numbers = generatorForNumbers(-10);                 
  
    for (int i= 1; i <= 20; ++i)
    {
        std::cout << numbers << " ";       
    }
  
    std::cout << "\n\n";
        
    // inline works
    for (auto n: generatorForNumbers(0, 5))
    {
        std::cout << n << " ";  
    }

    std::cout << std::endl;
}

Executable code snipped can be found here: https://godbolt.org/z/4cxhqxPP7

Upvotes: 2

Views: 297

Answers (1)

Kevin
Kevin

Reputation: 7324

From the documentation of cppcoro::generator, the only "meaningful" operations you can do to a generator is get begin and end iterators via begin() and end(). This is precisely why your second use for (auto n : generatorForNumbers(0, 5)) works. It iterates over the generator. Though you technically hit undefined behavior since there's no stopping condition for the generator so it overflows an int.

You can't print the generator directly. You have to iterate over it. So you could do this instead:

auto numbers = generatorForNumbers(-10);

auto it = numbers.begin();
for (int i= 1; i <= 20; ++i)
{
    std::cout << *it << " ";
    ++it;
}

or better (in my opinion):

int i = 0;
for (auto n : generatorForNumbers(-10))
{
    if (++i > 20)
        break;
    std::cout << n << " ";
}

or even better using ranges (thanks to @cigien in the comments):

for (auto n : generatorForNumbers(-10) | std::views::take(20))
{
    std::cout << n << " ";
}

Upvotes: 3

Related Questions