From 694a55e2dde8585c822903108657a9a2faa5dafc Mon Sep 17 00:00:00 2001 From: microcai Date: Sun, 20 Oct 2024 09:34:22 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E8=90=83=E5=8F=96=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=B7=BB=E5=8A=A0=E6=9B=B4=E5=A4=9A=E7=9A=84?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E3=80=82=E8=BF=99=E9=83=A8=E5=88=86=E4=B8=9C?= =?UTF-8?q?=E8=A5=BF=E6=B0=B8=E8=BF=9C=E6=98=AF=20c++=20=E9=87=8C=E6=9C=80?= =?UTF-8?q?=E6=99=A6=E6=B6=A9=E9=9A=BE=E6=87=82=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/ucoro/awaitable.hpp | 83 +++++++++++++++++++++++++++++-------- tests/test3/test.cpp | 12 +++--- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/include/ucoro/awaitable.hpp b/include/ucoro/awaitable.hpp index d641709..a18b78b 100644 --- a/include/ucoro/awaitable.hpp +++ b/include/ucoro/awaitable.hpp @@ -75,25 +75,26 @@ namespace ucoro inline constexpr local_storage_t local_storage; ////////////////////////////////////////////////////////////////////////// - namespace detail + namespace concepts { + ////////////////////////////////////////////////////////////////////////// // 用于判定 T 是否是一个 U 的类型 // 比如 // is_instance_of_v,std::vector>; // true // is_instance_of_v,std::list>; // false - template class U> + // + // 首先定义一个接受 is_instance_of_v 这样的一个默认模板萃取 + template typename U> inline constexpr bool is_instance_of_v = std::false_type{}; - template class U, class... Vs> - inline constexpr bool is_instance_of_v,U> = std::true_type{}; - template - struct local_storage_value_type; + // 接着为 is_instance_of_v, class_type> + // 这种定义一个偏特化,于是把符合这个模式的特殊参数给匹配到这个偏特化来了 + template typename class_type, typename... parameters> + inline constexpr bool is_instance_of_v, class_type> = std::true_type{}; - template - struct local_storage_value_type> - { - typedef ValueType value_type; - }; + // 然后把模板偏特化的萃取重新定义为一个 concept + template typename U> + concept is_instance_of = is_instance_of_v::type, U>; template concept is_valid_await_suspend_return_value = @@ -102,12 +103,54 @@ namespace ucoro // 用于判定 T 是否是一个 awaiter 的类型, 即: 拥有 await_ready,await_suspend,await_resume 成员函数的结构或类. template concept is_awaiter_v = requires (T a) { - { a.await_ready() } -> std::convertible_to; + { a.await_ready() } -> std::same_as; { a.await_suspend(std::coroutine_handle<>{}) } -> is_valid_await_suspend_return_value; { a.await_resume() }; }; - } // namespace detail + template + concept has_operator_co_await = requires (T a) + { + { a.operator co_await() } -> is_awaiter_v; + }; + + // 用于判定 T 是可以用在 co_await 后面 + template + concept is_awaitable_v = is_awaiter_v> || has_operator_co_await> || is_instance_of_v, awaitable>; + + } // namespace concepts + + namespace traits + { + ////////////////////////////////////////////////////////////////////////// + // 用于从 A = U 类型里提取 T 参数 + // 比如 + // inner_type_traits, std::vector>; // int + // inner_type_traits, std::list>; // char + // + // 首先定义一个接受 local_storage_value_type_trait 这样的一个默认模板萃取 + template typename U> + struct inner_type_traits; + + // 接着定义一个偏特化,匹配 inner_type_traits, U> + // 这样,这个偏特化的 inner_type_traits 就有了一个 + // 名为 innter_type 的成员类型,其定义的类型就是 T + // 于是就把 T 这个类型给萃取出来了 + template typename U, typename T> + struct inner_type_traits, U> + { + using innter_type = T ; + }; + + // 最后,定义一个简化用法的 using 让用户的地方代码变短点 + template typename U> + using inner_type = typename inner_type_traits, U>::innter_type; + + // 利用 通用工具 inner_type 萃取 local_storage_t 里的 T + template + using local_storage_value_type = inner_type; + + } // namespace traits struct debug_coro_promise { @@ -262,19 +305,23 @@ namespace ucoro template auto await_transform(A&& awaiter) const { - if constexpr ( detail::is_instance_of_v, local_storage_t> ) + if constexpr (concepts::is_instance_of) { - return local_storage_awaiter>::value_type>{this}; + return local_storage_awaiter>{this}; } - else if constexpr ( detail::is_awaiter_v> ) + else if constexpr (concepts::is_awaitable_v) { static_assert(std::is_rvalue_reference_v, "co_await must be used on rvalue"); return std::forward(awaiter); } - else + else if constexpr ( requires { await_transformer::await_transform; } ) { return await_transformer::await_transform(std::move(awaiter)); } + else + { + static_assert(0, "co_await must been used on an awaitable"); + } } std::coroutine_handle<> continuation_; @@ -347,7 +394,7 @@ namespace ucoro template auto await_suspend(std::coroutine_handle continuation) { - if constexpr (detail::is_instance_of_v) + if constexpr (concepts::is_instance_of) { current_coro_handle_.promise().local_ = continuation.promise().local_; } diff --git a/tests/test3/test.cpp b/tests/test3/test.cpp index d151040..7a698fc 100644 --- a/tests/test3/test.cpp +++ b/tests/test3/test.cpp @@ -7,15 +7,15 @@ int main(int argc, char **argv) using CallbackAwaiterType0 = ucoro::CallbackAwaiter; using CallbackAwaiterType1 = ucoro::CallbackAwaiter ; - static_assert(ucoro::detail::is_instance_of_v, ucoro::local_storage_t>, "not a local_storage_t"); + static_assert(ucoro::concepts::is_instance_of_v, ucoro::local_storage_t>, "not a local_storage_t"); - static_assert(ucoro::detail::is_awaiter_v < CallbackAwaiterType0 >, "not a coroutine"); - static_assert(ucoro::detail::is_awaiter_v < CallbackAwaiterType1 >, "not a coroutine"); + static_assert(ucoro::concepts::is_awaiter_v < CallbackAwaiterType0 >, "not a coroutine"); + static_assert(ucoro::concepts::is_awaiter_v < CallbackAwaiterType1 >, "not a coroutine"); - static_assert(ucoro::detail::is_awaiter_v < ucoro::awaitable >, "not a coroutine"); - static_assert(ucoro::detail::is_awaiter_v < ucoro::awaitable >, "not a coroutine"); + static_assert(ucoro::concepts::is_awaiter_v < ucoro::awaitable >, "not a coroutine"); + static_assert(ucoro::concepts::is_awaiter_v < ucoro::awaitable >, "not a coroutine"); - static_assert(!ucoro::detail::is_awaiter_v < int >, "not a coroutine"); + static_assert(!ucoro::concepts::is_awaiter_v < int >, "not a coroutine"); return 0; }