ð TOP / ã¢ãã³C++ M12ãC++20ãïŒã³ã«ãŒãã³
ã¢ãã³ç¬¬12ç« ïŒãC++20ãã³ã«ãŒãã³ïŒCoroutinesïŒã«ããéåæã²ãŒã ã«ãŒã
co_await / co_yield ã§ã¹ããŒããã·ã³å°çãè§£æ¶ãã
ã²ãŒã ããã°ã©ãã³ã°ã«ãããŠãæµãã¹ã®å€æ®µè¡åãã¿ãŒã³ãã«ããã·ãŒã³ã®äŒè©±ã€ãã³ãããã¥ãŒããªã¢ã«ã®é²è¡ç®¡çãªã©ã¯ãåžžã«ãæéçµéããããã¬ã€ã€ãŒã®ç¹å®ã¢ã¯ã·ã§ã³åŸ
ã¡ãã䌎ããŸããå€å
žçãªèšèšã§ã¯ããããã管çããããã«å€§éã®ãã©ã°å€æ°ãã¿ã€ããŒã巚倧㪠switch-case ã¹ããŒããã·ã³ãäœæããããåŸããããžãã¯ã忣ããŠæ·±å»ãªãã°ã®æž©åºãšãªã£ãŠããŸãããC++20 ã§èšèªæ©èœãšããŠå°å
¥ããããã³ã«ãŒãã³ïŒCoroutinesïŒãã¯ã颿°ã®å®è¡ãéäžã§äžæïŒSuspendïŒããåŸããä»»æã®äœçœ®ã§åéïŒResumeïŒã§ããç»æçãªãã©ãã€ã ã§ããæ¬ç« ã§ã¯ã`co_await` ã«ããæç³»åã·ãŒã±ã³ã¹ã®çŽç·çèšè¿°ã`co_yield` ã«ããé
å»¶è©äŸ¡åŒŸå¹ãžã§ãã¬ãŒã¿ããã㊠C++20 ã³ã«ãŒãã³ã®å
éšã¡ã«ããºã ïŒPromiseåãCoroutineHandleãAwaiterïŒãå®å
šè§£åããŸãã
M5.1 ç¶æ
ççºã®ã¹ããŒããã·ã³å°ç vs çŽç·çã«æžããã³ã«ãŒãã³
ãã¹ã®ãåºçŸæŒåº â 3ç§åŸ
æ© â ããŒã ç
§å° â 2ç§åŸ
æ© â æ¡æ£åŒŸä¹±å°ããšããäžé£ã®ã·ãŒã±ã³ã¹ãããã©ã°ãŸã¿ãã®å·šå€§ switch æããè§£æŸããŸãã
ð§ ãã³ã®ã³å
茩
ãã³å
çïŒã¹ããŒãž2ã®ãã¹ã®æ»æãã¿ãŒã³ãäœã£ãã®ã§ãããã³ãŒããå°çã®æ§çžãåããŠããŸãâŠâŠïŒãåºçŸäžããããŒã æºåäžããçºå°äžããã¯ãŒã«ããŠã³äžãã®ãã©ã°ãšã¿ã€ããŒå€æ°ã10å以äžä¹±ç«ããUpdate() ã® switch æã200è¡ãè¶
ããŠãã©ãã§äœãèµ·ããŠããã®ãäœè
ã®ç§ã§ãã远ããªããªããŸããïŒ
ð»ââïž ã·ãã¯ãå
ç
ãµãã£ãµãã£ãµãïŒãããããå
šã²ãŒã éçºè
ãäžåºŠã¯èœã¡ããã¹ããŒããã·ã³å°çïŒState Machine ExplosionïŒãããïŒæ¬æ¥ã¯ãäžããäžãžæµããçŽç·çãªã¹ããŒãªãŒããªã®ã«ãæ¯ãã¬ãŒã åŒã°ãã Update() 颿°ã®æ çµã¿ã«æŒã蟌ããããã«ãæéãç¡çããç¶æ
ã§èŒªåãã«ããŠããã®ãåå ãªã®ããã
ð§ ãã³ã®ã³å
茩
ã3ç§åŸ
ã€ããšããåŠçããæ®éã®é¢æ°åŒã³åºãã®ããã« while ã«ãŒãã§åŸ
ã€ãšãã²ãŒã å
šäœã®ç»é¢ã3ç§éããªãŒãºãã¡ãããŸãããâŠâŠïŒ
ð»ââïž ã·ãã¯ãå
ç
ãŸãã«ããããïŒã¡ã€ã³ã¹ã¬ãããäžåæ¢ããã«ãããã®é¢æ°ã®å®è¡ã ããäžæåæ¢ããŠåŒã³åºãå
ã«å¶åŸ¡ãè¿ãã3ç§åŸã«ãã®è¡ããåéããããšããéæ³ãå®çŸããã®ããC++20 ã®æ°æ©èœãã³ã«ãŒãã³ïŒCoroutinesïŒããªããããïŒ
ð CoroutineWaitExample.cpp
#include <iostream>
#include <coroutine>
// æå°éã®ã³ã«ãŒãã³æ»ãå€åïŒTaskïŒ
struct SimpleTask {
struct promise_type {
SimpleTask get_return_object() {
return SimpleTask{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_never initial_suspend() noexcept { return {}; } // åŒã³åºãæã«å³éå§
std::suspend_always final_suspend() noexcept { return {}; } // çµäºæã«äžæä¿æ
void return_void() noexcept {}
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle<promise_type> handle;
~SimpleTask() {
if (handle) handle.destroy();
}
};
// äžæåæ¢ïŒSuspendïŒãæç€ºçã«èŠæ±ããã«ã¹ã¿ã Awaiter
struct SuspendPoint {
bool await_ready() const noexcept { return false; } // åžžã«äžæ
void await_suspend(std::coroutine_handle<>) const noexcept {}
void await_resume() const noexcept {}
};
// ã³ã«ãŒãã³é¢æ°ïŒå
éšã« co_await ãããããèªåçã«ã³ã«ãŒãã³ãšããŠã³ã³ãã€ã«ãããïŒ
SimpleTask bossSequence(std::coroutine_handle<>& outHandle) {
std::cout << "[Step 1] ãã¹åºçŸïŒèŠåã¢ã©ãŒãå¹é³ŽïŒ\n";
co_await SuspendPoint{}; // ããã§äžæããŠåŒã³åºãå
ã«æ»ãïŒ
std::cout << "[Step 2] ãã£ãŒãžå®äºïŒãã€ããŒã¡ã¬ç²åç ²çºå°ïŒ\n";
co_await SuspendPoint{}; // åã³äžæ
std::cout << "[Step 3] ã·ãŒã«ãå±éïŒç¬¬2ãã§ãŒãºçªå
¥ïŒ\n";
}
int main() {
std::cout << "--- ã¡ã€ã³ã«ãŒãéå§ ---\n";
std::coroutine_handle<> handle;
// ã³ã«ãŒãã³ãèµ·å
bossSequence(handle);
std::cout << "--- ã¡ã€ã³ã«ãŒãïŒèªæ©ç§»åã»æç»ãªã©ã®éåžžãã¬ãŒã å®è¡äž ---\n";
// å€åŽã®ã²ãŒã ã«ãŒãããä»»æã®ã¿ã€ãã³ã°ã§åéïŒresumeïŒå¯èœïŒ
return 0;
}
M5.2 ã³ã«ãŒãã³ã®å
éšæ§é ïŒPromiseåã»Handleã»Awaiterã®3å€§æ§æèŠçŽ
C++20 ã³ã«ãŒãã³ãè£ã§ã©ã®ããã«åäœããŠããã®ãããã©ãã¯ããã¯ã¹ãéããŠå
éšã®é
ç·ã¡ã«ããºã ãè§£ãæãããŸãã
ð§ ãã³ã®ã³å
茩
ãã³å
çãæ®éã®é¢æ°ãšã³ã«ãŒãã³ã¯äœãéããã§ããïŒæ»ãå€ã®åã« `struct promise_type` ãå®çŸ©ããããèãæ
£ããªãåãããããåºãŠããŠé ãæ··ä¹±ããŠããŸãâŠâŠïŒ
ð»ââïž ã·ãã¯ãå
ç
è¯ãçåããïŒC++20 ã³ã«ãŒãã³ã¯ãäœã§ãããã®äŸ¿å©ã©ã€ãã©ãªãã§ã¯ãªãããèšèªä»æ§ãšããŠæäŸãããäœã¬ã€ã€ãã¬ãŒã ã¯ãŒã¯ããªããããæ¬¡ã®ã3å€§æ§æèŠçŽ ãããçè§£ããã°ãå®å
šã«èªåã®æè¶³ãšããŠæããããã«ãªããïŒ
ð GameCoroutineTask.cpp
#include <iostream>
#include <coroutine>
#include <vector>
#include <memory>
// 1. ã²ãŒã çšã³ã«ãŒãã³ã¿ã¹ã¯ïŒæææš©ç®¡çãšåéã€ã³ã¿ãŒãã§ãŒã¹ïŒ
class GameTask {
public:
struct promise_type {
GameTask get_return_object() {
return GameTask{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_always initial_suspend() noexcept { return {}; } // çææã¯åŸ
æ©
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() noexcept {}
void unhandled_exception() { std::terminate(); }
};
using Handle = std::coroutine_handle<promise_type>;
explicit GameTask(Handle h) : handle_(h) {}
~GameTask() {
if (handle_) handle_.destroy();
}
GameTask(GameTask&& other) noexcept : handle_(other.handle_) {
other.handle_ = nullptr;
}
GameTask& operator=(GameTask&& other) noexcept {
if (this != &other) {
if (handle_) handle_.destroy();
handle_ = other.handle_;
other.handle_ = nullptr;
}
return *this;
}
bool isDone() const { return !handle_ || handle_.done(); }
void resume() {
if (handle_ && !handle_.done()) {
handle_.resume();
}
}
private:
Handle handle_;
};
// 2. æå®ç§æ°ã ãäžæãã Awaiter
struct WaitForSeconds {
float duration;
float elapsed = 0.0f;
explicit WaitForSeconds(float sec) : duration(sec) {}
// await_ready: true ãè¿ããšäžæããã«å³åº§ã«å®è¡ãç¶ç¶ãã
bool await_ready() const noexcept { return duration <= 0.0f; }
// await_suspend: äžæãããçŽåã«åŒã°ããïŒã³ã«ãŒãã³ãã³ãã«ã®ä¿æãªã©ãè¡ãïŒ
void await_suspend(std::coroutine_handle<> h) noexcept {
// ããã§ã¿ã€ããŒãããŒãžã£çã«ãã³ãã«ãç»é²ã§ãã
}
// await_resume: åéãããç¬éã«åŒã°ããco_await åŒã®è©äŸ¡å€ãè¿ã
void await_resume() const noexcept {}
};
// 宿Šã³ã«ãŒãã³ïŒãã¹è¡åãã¿ãŒã³
GameTask bossRoutine() {
std::cout << " [ãã¹AI] ç»é¢äžéšãããã£ããäžéäž...\n";
co_await WaitForSeconds(1.0f);
std::cout << " [ãã¹AI] èªæ©ãç
§æºããã¯ãªã³ïŒ\n";
co_await WaitForSeconds(1.0f);
std::cout << " [ãã¹AI] ããŒãã³ã°ããµã€ã«äžæçºå°ïŒ\n";
}
int main() {
std::cout << "=== ã²ãŒã ã¿ã¹ã¯å®è¡ãããŒãžã£ãŒ ===\n";
GameTask boss = bossRoutine();
int frame = 0;
while (!boss.isDone()) {
std::cout << "Frame " << ++frame << ": ã²ãŒã ã«ãŒãæŽæ°äž\n";
boss.resume();
}
std::cout << "=== ãã¹è¡åã·ãŒã±ã³ã¹å®äº ===\n";
return 0;
}
M5.3 co_yield ã«ãã匟å¹åº§æšãžã§ãã¬ãŒã¿ïŒé
å»¶è©äŸ¡ïŒ
æ°åçºã®åŒŸäžžåº§æšã巚倧㪠vector ã«äžæ¬çæããŠã¡ã¢ãªã浪費ããã®ããããå¿
èŠãªæã«1çºãã€çæããé
å»¶è©äŸ¡ãžã§ãã¬ãŒã¿ãäœããŸãã
ð§ ãã³ã®ã³å
茩
å
çãå
šæ¹äœ360床ã«åŒŸãæã¡åºã匟å¹ãã¿ãŒã³ãäœããšããäºåã« `std::vector<BulletData>` ã§å
šåº§æšãèšç®ããŠè¿ããŠãããã§ãããéäžã§ãã¹ãæç Žããããæ®ãã®èšç®ãç¡é§ã«ãªã£ãŠããŸããŸãâŠâŠã
ð»ââïž ã·ãã¯ãå
ç
ããã§ç»å Žããã®ããco_yieldãããïŒãå€ãåŒã³åºãå
ã«1ã€æž¡ããŠãèªåã¯ããã§äžæåæ¢ããããšããããžã§ãã¬ãŒã¿ïŒGeneratorïŒããäœãã°ãå¿
èŠãªåŒŸã®åã ããªã³ããã³ãã§çæã§ããã®ããïŒ
ð BulletGenerator.cpp
#include <iostream>
#include <coroutine>
#include <cmath>
struct Vec2 {
float x, y;
};
// åäžã®å€ã次ã
ãšç£ã¿åºã Generator å
template <typename T>
class Generator {
public:
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() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
// co_yield value; ãåŒã°ãããšãã®åŠç
std::suspend_always yield_value(T value) noexcept {
current_value = value;
return {}; // å€ãã»ããããŠäžæäžæïŒ
}
void return_void() noexcept {}
void unhandled_exception() { std::terminate(); }
};
using Handle = std::coroutine_handle<promise_type>;
explicit Generator(Handle h) : handle_(h) {}
~Generator() { if (handle_) handle_.destroy(); }
// 次ã®å€ãåãåºãïŒã³ã«ãŒãã³ãåéïŒ
bool next() {
if (handle_ && !handle_.done()) {
handle_.resume();
return !handle_.done();
}
return false;
}
T getValue() const {
return handle_.promise().current_value;
}
private:
Handle handle_;
};
// èºæåŒŸå¹ã®å°åºãã¯ãã«ãçæãããžã§ãã¬ãŒã¿
Generator<Vec2> makeSpiralBarrage(int bulletCount, float baseAngle) {
const float PI = 3.14159265f;
for (int i = 0; i < bulletCount; ++i) {
float angle = baseAngle + (i * (2.0f * PI / bulletCount));
Vec2 dir = { std::cos(angle), std::sin(angle) };
// 1çºåã®æ¹åãã¯ãã«ãåŒã³åºãåŽã«æž¡ããŠäžæåæ¢ïŒ
co_yield dir;
}
}
int main() {
std::cout << "--- èºæåŒŸå¹çæéå§ (8çºãªã³ããã³ãçæ) ---\n";
auto barrage = makeSpiralBarrage(8, 0.0f);
int count = 0;
while (barrage.next()) {
Vec2 dir = barrage.getValue();
std::cout << "匟 #" << ++count << " çºå°ãã¯ãã«: ("
<< dir.x << ", " << dir.y << ")\n";
// ããéäžã§ãã¬ã€ã€ãŒããã ã䜿ã£ãããå³åº§ã«ã«ãŒããæããŠçµäºå¯èœïŒ
if (count >= 4) {
std::cout << "ãã çºåïŒæ®ãã®åŒŸäžžèšç®ã¯ãã£ã³ã»ã«ãããŸããïŒãŒããªãŒããŒãããïŒ\n";
break;
}
}
return 0;
}
M5.4 ã€ã³ããŒããŒçµ±åïŒãã¹è¡åAIã®ã³ã«ãŒãã³ãªãŒã±ã¹ãã¬ãŒã·ã§ã³
第7ç« ã®ECSãåç« ã®åå®å
šã·ã¹ãã ãšã³ã«ãŒãã³ãèåãããå®å
šéåæã®æµãã¹è¡åAIã宿ãããŸãã
ð»ââïž ã·ãã¯ãå
ç
ããä»äžãããïŒã€ã³ããŒããŒã®æ¯èŠãã¹ã«ãã³ã«ãŒãã³ã«ãããæéå·®çªæïŒæŽè·ãããå°åºã·ãŒã±ã³ã¹ããçµã¿èŸŒããïŒ
ð§ ãã³ã®ã³å
茩
ã¯ãïŒæ¯ãã¬ãŒã ã® switch æãšã¯å®å
šã«æ±ºå¥ããŠãçŸéºãªçŽç·ã³ãŒãã§ãã¹ãæã£ãŠã¿ããŸãïŒ
ð BossCoroutineIntegration.cpp
#include <iostream>
#include <vector>
#include <coroutine>
struct CoroutineTask {
struct promise_type {
CoroutineTask get_return_object() {
return CoroutineTask{std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_always initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() noexcept {}
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle<promise_type> h;
bool tick() {
if (h && !h.done()) { h.resume(); return !h.done(); }
return false;
}
~CoroutineTask() { if (h) h.destroy(); }
};
struct YieldFrame {
bool await_ready() const noexcept { return false; }
void await_suspend(std::coroutine_handle<>) const noexcept {}
void await_resume() const noexcept {}
};
// 1ãã¬ãŒã åŸ
æ©ãããã«ããŒé¢æ°
auto waitFrames(int frames) -> CoroutineTask {
for (int i = 0; i < frames; ++i) {
co_await YieldFrame{};
}
}
// ãã¹è¡åAIïŒå®å
šãªçŽç·ã³ãŒãã§æéå·®æ»æãèšè¿°
CoroutineTask bossAI() {
std::cout << "[Boss] ãã§ãŒãº1ïŒå·Šå³ãžã®åšåç§»åéå§\n";
for (int f = 0; f < 3; ++f) {
std::cout << " ãã¹äœçœ®ç§»å...\n";
co_await YieldFrame{};
}
std::cout << "[Boss] ãã§ãŒãº2ïŒäžå€®ãžãã¬ããŒãïŒèŠåçºä»€ïŒ\n";
co_await YieldFrame{};
std::cout << "[Boss] ãã§ãŒãº3ïŒ3WAYå
šæ¹äœåŒŸå¹äžæå°æïŒ\n";
co_await YieldFrame{};
std::cout << "[Boss] è¡åã·ãŒã±ã³ã¹å®äºãã«ãŒãåŸ
æ©ãž\n";
}
int main() {
std::cout << "=== ã€ã³ããŒããŒã»ãã¹ ã³ã«ãŒãã³AI皌å ===\n";
CoroutineTask boss = bossAI();
int frameCount = 0;
while (boss.tick()) {
std::cout << "--- ãã¬ãŒã " << ++frameCount << " æç»ã»ç©çæŒç®åæå®äº ---\n";
}
std::cout << "=== ãã¹è¡åçµäº ===\n";
return 0;
}
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
èœãšã穎1ïŒã³ã«ãŒãã³åŒæ°ã®ãåç
§æž¡ãïŒ&ïŒãã«ãããã³ã°ãªã³ã°åç
§ : ã³ã«ãŒãã³ã«åç
§ïŒconst std::string& ãªã©ïŒãæž¡ããšãåŒã³åºãå
ã®ããŒã«ã«å€æ°ãã¹ã³ãŒããæããŠæ¶æ»
ããåŸã«ã³ã«ãŒãã³ãåéãããæªå®çŸ©åäœãã¯ã©ãã·ã¥ãåŒãèµ·ãããŸããã³ã«ãŒãã³ã®åŒæ°ã¯å¿
ãã倿ž¡ãïŒValue copyïŒããŸãã¯ã¹ããŒããã€ã³ã¿ã§æž¡ãã®ãéåã§ããèœãšã穎2ïŒã³ã«ãŒãã³ãã³ãã«ã®äºéç Žæ£ã»è§£æŸæŒã : std::coroutine_handle ã¯çãã€ã³ã¿ãšåçã§ããRAII ã¯ã©ã¹ïŒTask ã¯ã©ã¹ã®ãã¹ãã©ã¯ã¿ã§ handle.destroy() ãåŒã¶ïŒãäœæããå¿
ãæææš©ãäžå
管çããŠãã ãããèœãšã穎3ïŒfinal_suspend ã§ suspend_never ãè¿ãããšãã®æªå®çŸ©åäœ : final_suspend ã§ suspend_never ãè¿ããšãã³ã«ãŒãã³çµäºæã«ãã¬ãŒã ãèªåæ¶æ»
ããŸãããã®åŸã«å€åŽãã handle.done() ã handle.destroy() ãåŒã¶ãšè§£æŸæžã¿ã¡ã¢ãªãžã®ã¢ã¯ã»ã¹ïŒUse-After-FreeïŒã«ãªããŸããå€åŽã§ãã³ãã«ã管çããå Žåã¯å¿
ã suspend_always ãè¿ããŸãã
ð ç解床ãã§ãã¯ã¯ã€ãº
Q1. C++20 ã³ã«ãŒãã³ã«ãããŠã颿°ã®å®è¡ãäžæåæ¢ïŒäžæïŒããåŒã³åºãå
ã«å¶åŸ¡ãæ»ãããŒã¯ãŒãã¯ã©ãã§ããïŒ
1. co_await 2. std::yield 3. goto_pause 4. suspend_now
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒco_await
æ£è§£ã¯ co_await ã§ãïŒco_await åŒã¯ãªãã©ã³ãã® Awaiter ãªããžã§ã¯ããè©äŸ¡ããå¿
èŠã«å¿ããŠé¢æ°ã®å®è¡ãäžæããŠåŒã³åºãå
ã«å¶åŸ¡ãè¿ããŸããå€ãçæããŠäžæããå Žå㯠co_yield ã䜿çšããŸãã
Q2. C++20 ã³ã«ãŒãã³ã®èšèšã«ãããŠã颿°ã®åŒæ°ã«ããŒã«ã«å€æ°ã®åç
§ïŒT&ïŒãæž¡ãããšãå±éºãšãããæå€§ã®çç±ã¯äœã§ããïŒ
1. ã³ã³ãã€ã©ãåç
§æž¡ããçŠæ¢ããæ§æãšã©ãŒãåºããã 2. co_await ã§äžæããŠããéã«åŒã³åºãå
ã®å®äœãã¹ã³ãŒããæããŠç Žæ£ãããåéæã«ãã³ã°ãªã³ã°åç
§ïŒæªå®çŸ©åäœïŒã«ãªããã 3. åç
§æž¡ãã䜿ããšèªåçã«ãã«ãã¹ã¬ããå®è¡ã«ãªã£ãŠãããããã¯ãããã 4. åç
§æž¡ãã䜿ããšã³ã«ãŒãã³ã® vtable ãè¥å€§åãããã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒco_await ã§äžæããŠããéã«åŒã³åºãå
ã®å®äœãã¹ã³ãŒããæããŠç Žæ£ãããåéæã«ãã³ã°ãªã³ã°åç
§ïŒæªå®çŸ©åäœïŒã«ãªããã
æ£è§£ã¯ãco_await ã§äžæããŠããéã«åŒã³åºãå
ã®å®äœãã¹ã³ãŒããæããŠç Žæ£ãããåéæã«ãã³ã°ãªã³ã°åç
§ïŒæªå®çŸ©åäœïŒã«ãªããããã§ãïŒã³ã«ãŒãã³ã¯åŒã³åºãå
ã®é¢æ°ãããé·ãçåããããšãæ¥åžžè¶é£¯äºã§ãããããåŒæ°ã¯ååãšããŠå€æž¡ãïŒã³ããŒãŸãã¯ã ãŒãïŒã§å®å
šã«ã³ã«ãŒãã³ãã¬ãŒã å
ã«ä¿æããå¿
èŠããããŸãã
Q3. C++20 ã³ã«ãŒãã³ã®ã3å€§æ§æèŠçŽ ããšããŠæ£ããçµã¿åããã¯ã©ãã§ããïŒ
1. promise_typeãstd::coroutine_handleãAwaiter 2. std::threadãstd::mutexãstd::condition_variable 3. unique_ptrãshared_ptrãweak_ptr 4. vectorãlistãunordered_map
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒpromise_typeãstd::coroutine_handleãAwaiter
æ£è§£ã¯ãpromise_typeãstd::coroutine_handleãAwaiterãã§ãïŒpromise_type ã¯ã³ã«ãŒãã³ã®çæã»çµæäŒéãstd::coroutine_handle ã¯å€åŽããã®åéã»ç Žæ£å¶åŸ¡ãAwaiter ã¯äžæå¯åŠãšå鿡件ã®å€å®ãæ
åœããŸãã
ð»ââïž ã·ãã¯ãC++ã©ã ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ã·ã¹ãã
ãã©ãŠã¶ã§JavaScriptãæå¹ã«ãããšããã©ãŠã¶å
ã€ã³ããŒããŒã²ãŒã ãšãã¥ã¬ãŒã¿ãã¡ã¢ãªãããå¯èŠåãUMLã¯ã©ã¹å³ã察話å解説ãç解床ã¯ã€ãºãèµ·åããŸãã
ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ãéå§ãã â