mp-coro main
Coroutine support tools
concepts.h
Go to the documentation of this file.
1// The MIT License (MIT)
2//
3// Copyright (c) 2021 Mateusz Pusz
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23#pragma once
24
27#include <concepts>
28#include <coroutine>
29
30namespace mp_coro {
31
32namespace detail {
33
34template <typename Ret, typename Handle>
35Handle func_arg(Ret (*)(Handle));
36
37template <typename Ret, typename T, typename Handle>
38Handle func_arg(Ret (T::*)(Handle));
39
40template <typename Ret, typename T, typename Handle>
41Handle func_arg(Ret (T::*)(Handle) &);
42
43template <typename Ret, typename T, typename Handle>
44Handle func_arg(Ret (T::*)(Handle) &&);
45
46template <typename Ret, typename T, typename Handle>
47Handle func_arg(Ret (T::*)(Handle) const);
48
49template <typename Ret, typename T, typename Handle>
50Handle func_arg(Ret (T::*)(Handle) const &);
51
52template <typename Ret, typename T, typename Handle>
53Handle func_arg(Ret (T::*)(Handle) const &&);
54
55template <typename T>
56concept suspend_return_type = std::is_void_v<T> //
57 || std::is_same_v<T, bool> //
59
60} // namespace detail
61
62template <typename T>
63concept awaiter = requires(
64 T &&t, decltype(detail::func_arg(&std::remove_reference_t<T>::await_suspend)) suspend_arg) {
65 { std::forward<T>(t).await_ready() } -> std::convertible_to<bool>;
66 { suspend_arg } -> std::convertible_to<std::coroutine_handle<>>;
67 // TODO Why gcc does not inherit from `std::coroutine_handle<>`?
68 { std::forward<T>(t).await_suspend(suspend_arg) } -> detail::suspend_return_type;
69 std::forward<T>(t).await_resume();
70};
71
72template <typename T, typename Value>
73concept awaiter_of = awaiter<T> &&requires(T &&t) {
74 { std::forward<T>(t).await_resume() } -> std::same_as<Value>;
75};
76
77template <typename T>
78concept awaitable = requires(T &&t) {
79 { detail::get_awaiter(std::forward<T>(t)) } -> awaiter;
80};
81
82template <typename T, typename Value>
83concept awaitable_of = awaitable<T> &&requires(T &&t) {
84 { detail::get_awaiter(std::forward<T>(t)) } -> awaiter_of<Value>;
85};
86
87template <typename T>
88concept task_value_type = std::move_constructible<T> || std::is_reference_v<T> || std::is_void_v<T>;
89
90/// Type that supports the `notify_awaitable_completed()` member function used
91/// by @ref mp_coro::detail::synchronized_task.
92template <typename Sync>
93concept sync_notification_type = requires(Sync s) {
94 s.notify_awaitable_completed();
95};
96
97} // namespace mp_coro
Type that supports the notify_awaitable_completed() member function used by mp_coro::detail::synchron...
Definition: concepts.h:93
decltype(auto) get_awaiter(T &&awaitable)
Apply member operator co_await if it exists, otherwise, apply global operator co_await if it exists,...
Definition: get_awaiter.h:32
Handle func_arg(Ret(*)(Handle))
Definition: async.h:31