This commit is contained in:
Timur A. Fatkhullin
2026-10-01 00:39:19 +03:00
parent af04681b3c
commit bc8c6b64ec
2 changed files with 43 additions and 17 deletions

View File

@@ -198,15 +198,36 @@ concept ret_expected_type_c = requires {
// result of asynchronous callable // result of asynchronous callable
template <typename, typename = std::void_t<>> template <typename, typename = std::void_t<>>
struct has_co_await_operator : std::false_type {}; struct has_co_await_operator : std::false_type {
};
template <typename T> template <typename T>
struct has_co_await_operator<T, std::void_t<decltype(std::declval<T>().operator co_await())>> : std::true_type {}; struct has_co_await_operator<T, std::void_t<decltype(std::declval<T>().operator co_await())>> : std::true_type {
};
template <typename T> template <typename T>
constexpr bool has_co_await_operator_v = has_co_await_operator<T>::value; constexpr bool has_co_await_operator_v = has_co_await_operator<T>::value;
template <typename T, bool>
struct deduced_awaitable_ret_type;
template <typename T>
struct deduced_awaitable_ret_type<T, true> {
using type = decltype(std::declval<decltype(std::declval<T>().operator co_await())>().await_resume());
};
template <typename T>
struct deduced_awaitable_ret_type<T, false> {
using type = decltype(std::declval<T>().await_resume());
};
template <typename T>
using deduced_awaitable_ret_type_t = typename deduced_awaitable_ret_type<T, has_co_await_operator_v<T>>::type;
template <typename T, typename UT = void> template <typename T, typename UT = void>
concept result_awaiter_c = requires(T t, std::coroutine_handle<> hndl) { concept result_awaiter_c = requires(T t, std::coroutine_handle<> hndl) {
{ t.await_ready() } -> std::convertible_to<bool>; { t.await_ready() } -> std::convertible_to<bool>;
@@ -229,28 +250,33 @@ concept result_awaitable_c = requires(T t) {
// { t.operator co_await() } -> result_awaiter_c<UT>; // { t.operator co_await() } -> result_awaiter_c<UT>;
// }; // };
template <typename T>
concept awaitable_c = (!has_co_await_operator_v<T> || requires {
std::declval<decltype(std::declval<T>().operator co_await())>().await_resume();
}) && (has_co_await_operator_v<T> || requires { std::declval<T>().await_resume(); });
template <typename T, typename RT = void> template <typename T, typename RT = void>
concept awaitable_type_c = concept awaitable_ret_type_c =
(!has_co_await_operator_v<T> || (!has_co_await_operator_v<T> ||
std::same_as<decltype(std::declval<decltype(std::declval<T>().operator co_await())>().await_resume()), RT>) && std::same_as<decltype(std::declval<decltype(std::declval<T>().operator co_await())>().await_resume()), RT>) &&
(has_co_await_operator_v<T> || std::same_as<decltype(std::declval<T>().await_resume()), RT>); (has_co_await_operator_v<T> || std::same_as<decltype(std::declval<T>().await_resume()), RT>);
static_assert(awaitable_type_c<asio::awaitable<void>>, "!!!"); static_assert(awaitable_ret_type_c<asio::awaitable<void>>, "!!!");
static_assert(awaitable_c<asio::awaitable<int>>, "!!!");
template <typename T, typename RT>
concept awaitable_ret_expected_type_c = awaitable_c<T> && ret_expected_type_c<deduced_awaitable_ret_type_t<T>, RT>;
template <typename T, typename UT = void>
concept async_retval_c = result_awaitable_c<decltype(std::declval<T>().operator co_await())> || requires {
[] -> auto {
T t;
co_await t;
}();
};
// template <typename T, typename UT = void> // template <typename T, typename UT = void>
// concept async_retval_c = result_awaiter_c<decltype(std::declval<T>().operator co_await()), UT>; // concept async_retval_c = result_awaiter_c<decltype(std::declval<T>().operator co_await()), UT>;
// template <typename T, typename UT = void> template <typename T, typename UT = void>
// concept async_retval_c = result_awaitable_c<T, UT> && ret_expected_c<UT>; concept async_retval_c = result_awaitable_c<T, UT> && ret_expected_c<UT>;
}; // namespace snplib
@@ -267,4 +293,4 @@ concept logger_c = requires(T t) {
} // namespace snplib }; // namespace snplib

View File

@@ -71,9 +71,9 @@ concept net_connection_c = requires(T t) {
typename T::error_t; typename T::error_t;
// { t.send(std::declval<typename T::message_t>()) } -> async_retval_c<typename T::error_t>; // { t.send(std::declval<typename T::message_t>()) } -> async_retval_c<typename T::error_t>;
{ t.send(std::declval<typename T::message_t>()) } -> awaitable_type_c<typename T::error_t>; { t.send(std::declval<typename T::message_t>()) } -> awaitable_ret_type_c<typename T::error_t>;
// { t.recv() } -> async_retval_c<typename T::message_t>; // { t.recv() } -> async_retval_c<typename T::message_t>;
{ t.recv() } -> awaitable_type_c<typename T::message_t>; { t.recv() } -> awaitable_ret_type_c<typename T::message_t>;
// [] { // [] {
// typename T::message_t msg; // typename T::message_t msg;