diff options
Diffstat (limited to 'src/mongo/util/future_impl.h')
-rw-r--r-- | src/mongo/util/future_impl.h | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/src/mongo/util/future_impl.h b/src/mongo/util/future_impl.h index bb9a467710d..19adb0aa928 100644 --- a/src/mongo/util/future_impl.h +++ b/src/mongo/util/future_impl.h @@ -50,7 +50,6 @@ #include "mongo/util/scopeguard.h" namespace mongo { - template <typename T> class Promise; @@ -70,6 +69,7 @@ template <typename T> class SharedSemiFuture; namespace future_details { + template <typename T> class FutureImpl; template <> @@ -188,6 +188,45 @@ using VoidToFakeVoid = std::conditional_t<std::is_void_v<T>, FakeVoid, T>; template <typename T> using FakeVoidToVoid = std::conditional_t<std::is_same_v<T, FakeVoid>, void, T>; +struct InvalidCallSentinal; // Nothing actually returns this. +template <typename Func, typename Arg, typename = void> +struct FriendlyInvokeResultImpl { + using type = InvalidCallSentinal; +}; +template <typename Func, typename Arg> +struct FriendlyInvokeResultImpl< + Func, + Arg, + std::enable_if_t<std::is_invocable_v<Func, std::enable_if_t<!std::is_void_v<Arg>, Arg>>>> { + using type = std::invoke_result_t<Func, Arg>; +}; +template <typename Func> +struct FriendlyInvokeResultImpl<Func, void, std::enable_if_t<std::is_invocable_v<Func>>> { + using type = std::invoke_result_t<Func>; +}; +template <typename Func> +struct FriendlyInvokeResultImpl<Func, const void, std::enable_if_t<std::is_invocable_v<Func>>> { + using type = std::invoke_result_t<Func>; +}; + +template <typename Func, typename Arg> +using FriendlyInvokeResult = typename FriendlyInvokeResultImpl<Func, Arg>::type; + +// Like is_invocable_v<Func, Args>, but handles Args == void correctly. +template <typename Func, typename Arg> +inline constexpr bool isCallable = + !std::is_same_v<FriendlyInvokeResult<Func, Arg>, InvalidCallSentinal>; + +// Like is_invocable_r_v<Func, Args>, but handles Args == void correctly and unwraps the return. +template <typename Ret, typename Func, typename Arg> +inline constexpr bool isCallableR = + (isCallable<Func, Arg> && std::is_same_v<UnwrappedType<FriendlyInvokeResult<Func, Arg>>, Ret>); + +// Like isCallableR, but doesn't unwrap the result type. +template <typename Ret, typename Func, typename Arg> +inline constexpr bool isCallableExactR = (isCallable<Func, Arg> && + std::is_same_v<FriendlyInvokeResult<Func, Arg>, Ret>); + /** * call() normalizes arguments to hide the FakeVoid shenanigans from users of Futures. * In the future it may also expand tuples to argument lists. |