8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C++20 自作クラスのイテレータをコルーチンで書いてみる

Posted at

はじめに

自作クラスを範囲forにぶちこみたいときに、begin endを定義したりするわけですが
その時に書くイテレータを直感的に書きたいなと思い

C++20コルーチンを使ってみました。

実装

基本的にはgeneratorっぽい実装をイテレータのみに集約した感じです。
※generatorの概念についてはここでは特に触れません。以下などを参考にしてください。
https://qiita.com/yohhoy/items/aeb3c01d02d0f640c067

co_iterator.hpp
# pragma once
# include <coroutine>

struct co_iterator_end {};

template<class Type>
struct co_iterator
{
	struct promise_type
	{
		Type value;
		auto get_return_object() { return co_iterator{ handle::from_promise(*this) }; }
		auto  initial_suspend() { return std::suspend_never{}; }
		auto final_suspend() noexcept { return std::suspend_always{}; }
		auto yield_value(const Type& _value)
		{
			this->value = _value;
			return std::suspend_always{};
		}
		void unhandled_exception() { std::terminate(); }
		void return_void() {}
	};

	using handle = std::coroutine_handle<promise_type>;

public:
	explicit co_iterator(handle h)
		: coro(h)
	{}

	co_iterator(const co_iterator&) = delete;

	co_iterator(co_iterator&& rhs) noexcept
		: coro(std::move(rhs.coro))
	{
		rhs.coro = nullptr;
	}

	~co_iterator()
	{
		if (coro) {
			coro.destroy();
		}
	}
	co_iterator& operator++()
	{
		if (!coro.done()) {
			coro.resume();
		}
		return *this;
	}
	decltype(auto) operator*()
	{
		return coro.promise().value;
	}
	bool operator!=(const co_iterator_end&) const
	{
		return !coro.done();
	}
private:
	handle coro;
};

使い方

main.cpp
struct Vector3
{
    int x, y, z;

    co_iterator<int> begin() const
    {
        // コルーチンで書けるとわかりやすい
        co_yield x;
        co_yield y;
        co_yield z;
    }
    co_iterator_end end() const
    {
        return {};
    }
};

int main()
{
    Vector3 vec{1,2,3};
    for(auto&& elm : vec) {
        std::cout << elm << std::endl;
    }
}
output
1
2
3

まとめ

  • C++20コルーチン楽しい
  • C++20コルーチン便利
  • (generatorでも似たようなことができるよ)
8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?