C++20:使用协程实现简易生成器

学习C++协程:

C++协程TS已并入C++20,VS2017或2019暂不完全支持协程,使用头文件experimental/coroutine及命名空间std::experimental。支持协程则替换为使用头文件coroutine及命名空间std即可。

注意,VS2017或2019需添加命令行选项/await,不然会出现类似message : Please use '/await' command-line option to enable relevant extensions的东西。

#include <experimental/coroutine>
#include <iostream>

template <typename Ty>
class generator {
public:
    template <typename Ty>
    struct promise_type_;

    using promise_type = promise_type_<Ty>;
    using handle_type  = std::experimental::coroutine_handle<promise_type>;

    template <typename Ty>
    struct promise_type_ {
        generator get_return_object() {
            return generator{handle_type::from_promise(*this)};
        }

        static generator get_return_object_on_allocation_failure() {
            return generator{nullptr};
        }

        auto initial_suspend() {
            return std::experimental::suspend_always{};
        }

        auto final_suspend() noexcept {
            return std::experimental::suspend_always{};
        }

        auto yield_value(Ty value) {
            current_value = value;

            return std::experimental::suspend_always{};
        }

        void return_void() {}

        void unhandled_exception() {
            std::terminate();
        }

        Ty current_value;
    };

    struct iterator_end {};

    template <typename Ty>
    struct iterator {
        iterator(handle_type handle_) : handle(handle_) {}

        void operator++() {
            handle.resume();
        }

        Ty operator*() {
            return std::move(handle.promise().current_value);
        }

        bool operator==(iterator_end) {
            return handle.done();
        }

        bool operator!=(iterator_end) {
            return !handle.done();
        }

        handle_type handle;
    };

    generator(handle_type handle_) : handle(handle_) {}
    generator(const generator& other) = delete;
    generator(generator&& other) noexcept : handle(other.handle) {
        other.handle = nullptr;
    }
    ~generator() {
        if (handle) {
            handle.destroy();
        }
    }

    bool has_next() {
        if (handle) {
            handle.resume();

            return !handle.done();
        }

        return false;
    }

    Ty get_value() {
        return std::move(handle.promise().current_value);
    }

    iterator<Ty> begin() {
        handle.resume();
        return iterator<Ty>{handle};
    }

    iterator_end end() {
        return iterator_end{};
    }

private:
    handle_type handle;
};

generator<int> gen() {
    co_yield 1;
    co_yield 2;
}

generator<int> ints(int count) {
    for (int i = 0; i != count; i++) {
        co_yield i;
    }
}

generator<int> ints(int begin, int end) {
    for (; begin != end; begin++) {
        co_yield begin;
    }
}

int main() {
    generator<int> g1 = gen();

    while (g1.has_next()) {
        std::cout << g1.get_value() << " ";
    }

    std::cout << "\n";

    for (auto i : ints(5)) {
        std::cout << i << " ";
    }

    std::cout << "\n";

    for (auto i : ints(3, 7)) {
        std::cout << i << " ";
    }

    std::cout << "\n";
}

执行结果

执行结果

相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页