summaryrefslogtreecommitdiff
path: root/src/mongo/util/future_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/future_impl.h')
-rw-r--r--src/mongo/util/future_impl.h41
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.