Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a reasonably well working generator class template in C++20?

I'm just a simple coder who used Python a lot and got addicted to its generators. As far as I understand the current situation, they can be cleanly implemented in C++20 with coroutines, however, at least until C++23, it's not a trivial task since one needs to write a generator class (template). How do I get one that

  1. Runs reasonably fast (at least not slower than the good old generators hack with macros)
  2. I can use ranged-based for, the ranges library and some equivalent of Python's next on it. It would also be great if there was a method to test whether the generator is exhausted.
  3. When (if?) an equivalent is added to the standard library, I (with high probability) won't need to change my code too much

Is this possible at all?

like image 853
acupoftea Avatar asked Oct 27 '22 18:10

acupoftea


1 Answers

As mentioned in the comment, libcoro provides a higher level of abstraction and might solve some of your issues.

For point2, if you really need a public method that tells you the generator is exhausted, I guess enhancing libcoro generator would make it somehow easy. Here is a (not tested) possible sample. But is checking against generator.end() a problem for you?

namespace libcoro {
    template<typename T>
    class [[nodiscard]] generator
    {
    public:

    using reference_type = std::conditional_t<std::is_reference_v<T>, T, T&>;

    //.. libcoro stuff

    // ADDED
    bool done() const {
      m_coroutine.done();
    }

    reference_type value() const {
      return m_coroutine.promise().value();
    }

    void resume() {
      m_coroutine.resume();
    }

    // ...
};

}

Then you can do:

while (true) {
        gen.resume();
        if(gen.done()) {
            std::cout << "this is the end!" << std::endl;
            break;
        }
        std::cout << "new value: " << gen.value() << std::endl;
}
like image 85
nop666 Avatar answered Oct 31 '22 05:10

nop666