シンプルなジェネレーターの実装
値を遅延的に生成するジェネレーターコルーチンを構築します。
「シンプルなジェネレーターの実装」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
コルーチンとしてのジェネレーター
ジェネレーターは、値を一度に1つずつ返すコルーチンです。ジェネレーターを呼び出すたびに次の値が生成され、処理が中断されます。
ジェネレーター型
入れ子になったpromise_typeを持つクラスを定義します。コンパイラーはこれを使用してコルーチンの状態を管理します。
template <typename T>
struct Generator {
struct promise_type {
T current_value;
Generator get_return_object() {
return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() {}
std::suspend_always yield_value(T value) {
current_value = value;
return {};
}
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle<promise_type> h;
// ... constructors, destructor, next() ...
};ジェネレーターの使用
一度定義すれば、ジェネレーターはPythonのyieldのように扱えます。
Generator<int> counting() {
int n = 0;
while (true) co_yield n++;
}
auto g = counting();
for (int i = 0; i < 5; ++i) {
std::cout << g.next() << " ";
}
// 0 1 2 3 4coroutine_handle
コンパイラーはstd::coroutine_handleを返します。これは中断されたコルーチンを表し、resume()やdestroy()を呼び出したり、done()を確認したりできます。
中断ポイント
各co_yieldで処理が中断されます。呼び出し側がresume()を呼び出すと、次の中断ポイントまたはコルーチンの終了まで処理が続行されます。
initial_suspendとfinal_suspend
2つのカスタマイズポイントがあります。
initial_suspend— 遅延開始にはsuspend_alwaysを、即時開始にはsuspend_neverを返しますfinal_suspend— クリーンアップを制御します。適切に破棄するため、通常はsuspend_alwaysを使用します
C++23のstd::generator
C++23では<generator>にstd::generatorが追加されました。一般的な用途であれば、型を自分で実装する必要はなくなりました。
#include <generator>
std::generator<int> counting() {
int n = 0;
while (true) co_yield n++;
}範囲ベースのfor
ジェネレーター型がbegin/endをサポートしていれば、範囲ベースのforがそのまま使えます。
for (int x : counting()) {
if (x >= 10) break;
std::cout << x;
}PullとPushのセマンティクス
ジェネレーターはpullベースです。呼び出し側が反復処理を進めます。Pushベースのコルーチンは非同期タスクです。
使用例
ジェネレーターは次の用途に適しています。
- 遅延シーケンス(フィボナッチ数列、素数、1行ずつ読み取るファイルリーダー)
- データをすべてメモリに展開しないストリーミング処理
- 木構造の反復処理
メモリに関する考慮事項
コルーチンフレームは、デフォルトではヒープに割り当てられます。インライン化が可能な場合、コンパイラーが割り当てを省略することもあります。性能が重要な場合は計測してください。
調べてみたいライブラリ
学習には、Lewis Bakerによるcppcoroがおすすめです。ドキュメントが充実したジェネレーター型とタスク型を提供しています。Boost.Asioはコルーチンに対応したI/Oを提供します。C++23以降では標準ライブラリのサポートも追加されています。
確認問題
ジェネレーターコルーチンで使用するC++23標準ライブラリの型は何ですか?
まとめ
ジェネレーターコルーチンは、co_yieldを使って値を遅延的に生成します。promise_typeを含むクラスとして実装します。C++23ではstd::generatorが標準化されました。ジェネレーターは遅延シーケンスやストリーミングに適しています。
よくある質問
「シンプルなジェネレーターの実装」レッスンは無料ですか?
はい。「シンプルなジェネレーターの実装」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「シンプルなジェネレーターの実装」で何を学びますか?
値を遅延的に生成するジェネレーターコルーチンを構築します。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「シンプルなジェネレーターの実装」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。