+
+#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE
+template <typename ReturnType, typename... Args>
+Function<ReturnType(Args...) const noexcept> constCastFunction(
+ Function<ReturnType(Args...) noexcept>&& that) noexcept {
+ return Function<ReturnType(Args...) const noexcept>{
+ std::move(that), detail::function::CoerceTag{}};
+}
+
+template <typename ReturnType, typename... Args>
+Function<ReturnType(Args...) const noexcept> constCastFunction(
+ Function<ReturnType(Args...) const noexcept>&& that) noexcept {
+ return std::move(that);
+}
+#endif
+
+namespace detail {
+namespace function {
+template <typename Fun, typename FunctionType, typename = void>
+struct IsCallableAsImpl : std::false_type {};
+
+template <typename Fun, typename ReturnType, typename... Args>
+struct IsCallableAsImpl<
+ Fun,
+ ReturnType(Args...),
+ void_t<typename std::result_of<Fun && (Args && ...)>::type>>
+ : std::is_convertible<
+ typename std::result_of<Fun && (Args && ...)>::type,
+ ReturnType> {};
+
+template <typename Fun, typename FunctionType>
+struct IsCallableAs : IsCallableAsImpl<Fun, FunctionType> {};
+} // namespace function
+} // namespace detail
+
+/**
+ * @class FunctionRef
+ *
+ * @brief A reference wrapper for callable objects
+ *
+ * FunctionRef is similar to std::reference_wrapper, but the template parameter
+ * is the function signature type rather than the type of the referenced object.
+ * A folly::FunctionRef is cheap to construct as it contains only a pointer to
+ * the referenced callable and a pointer to a function which invokes the
+ * callable.
+ *
+ * The user of FunctionRef must be aware of the reference semantics: storing a
+ * copy of a FunctionRef is potentially dangerous and should be avoided unless
+ * the referenced object definitely outlives the FunctionRef object. Thus any
+ * function that accepts a FunctionRef parameter should only use it to invoke
+ * the referenced function and not store a copy of it. Knowing that FunctionRef
+ * itself has reference semantics, it is generally okay to use it to reference
+ * lambdas that capture by reference.
+ */
+
+template <typename FunctionType>
+class FunctionRef;
+
+template <typename ReturnType, typename... Args>
+class FunctionRef<ReturnType(Args...)> final {
+ using Call = ReturnType (*)(void*, Args&&...);
+
+ static ReturnType uninitCall(void*, Args&&...) {
+ throw std::bad_function_call();
+ }
+
+ template <typename Fun>
+ static ReturnType call(void* object, Args&&... args) {
+ using Pointer = _t<std::add_pointer<Fun>>;
+ return static_cast<ReturnType>(invoke(
+ static_cast<Fun&&>(*static_cast<Pointer>(object)),
+ static_cast<Args&&>(args)...));
+ }
+
+ void* object_{nullptr};
+ Call call_{&FunctionRef::uninitCall};
+
+ public:
+ /**
+ * Default constructor. Constructs an empty FunctionRef.
+ *
+ * Invoking it will throw std::bad_function_call.
+ */
+ FunctionRef() = default;
+
+ /**
+ * Construct a FunctionRef from a reference to a callable object.
+ */
+ template <
+ typename Fun,
+ typename std::enable_if<
+ Conjunction<
+ Negation<std::is_same<FunctionRef, _t<std::decay<Fun>>>>,
+ detail::function::IsCallableAs<Fun, ReturnType(Args...)>>::value,
+ int>::type = 0>
+ constexpr /* implicit */ FunctionRef(Fun&& fun) noexcept
+ // `Fun` may be a const type, in which case we have to do a const_cast
+ // to store the address in a `void*`. This is safe because the `void*`
+ // will be cast back to `Fun*` (which is a const pointer whenever `Fun`
+ // is a const type) inside `FunctionRef::call`
+ : object_(
+ const_cast<void*>(static_cast<void const*>(std::addressof(fun)))),
+ call_(&FunctionRef::call<Fun>) {}
+
+ ReturnType operator()(Args... args) const {
+ return call_(object_, static_cast<Args&&>(args)...);
+ }
+
+ constexpr explicit operator bool() const {
+ return object_;
+ }
+};
+