在C++裏,一個函數若是其函數體實現中包含co_await、co_yield、co_return中任何一個關鍵字,那麼這個函數就是一個coroutine。其中:promise
一個coroutine要能被編譯期識別並經過編譯,在某些狀況下要本身去特化coroutine_traits。下面就一個簡單的coroutine來講一說C++編譯器是如何修改這個coroutine的。函數
1 // 咱們假定這個模板函數是一個coroutine 2 template <typename TRet, typename … TArgs> 3 TRet func(TArgs args…) 4 { 5 body; // body裏至少包含了co_await、co_yield、co_return三者之一。 6 }
那麼這個函數會被編譯器改爲以下形式:spa
1 // 它會被編譯期展開成以下形式 2 template <typename TRet, typename ... TArgs> 3 TRet func(TArgs args...) 4 { 5 using promise_t = typename coroutine_traits<TRet, TArgs...>::promise_type; 6 7 promise_t promise; 8 auto __return__ = promise.get_return_object(); // 這個__return__會被編譯器特殊處理 9 10 co_await promise.initial_suspend(); 11 12 try 13 { // co_return expr; => promise.return_value(expr); goto final_suspend; 14 body; // co_return; => promise.return_void(); goto final_suspend; 15 } // co_yield expr; => co_await promise.yield_value(expr); 16 catch (...) 17 { 18 promise.set_exception(std::current_exception()); 19 } 20 21 final_suspend: 22 co_await promise.final_suspend(); 23 }
以上是一個coroutine的基本形式。事實上看完以後會發現,一個coroutine的關鍵主要仍是和其關聯的promise。
和coroutine promise關聯的另一個概念,叫awaitable。Awaitable能夠稱爲一個可等待對象。一個awaitable對象須要實現3個相關函數:線程
因此要讓一個類型可以awaitable,有三種手段:代理
--完code
N4663對象