Add prepareSkipTo() method to EliasFanoReader
[folly.git] / folly / Function.h
index 6c64647ddb95a69744cc20d858b3d95b0a092cd0..b91de9ca16e4679b705e64f8259de9755a27a423 100644 (file)
@@ -410,13 +410,13 @@ bool execBig(Op o, Data* src, Data* dst) {
 
 // Invoke helper
 template <typename F, typename... Args>
-inline auto invoke(F&& f, Args&&... args)
+inline constexpr auto invoke(F&& f, Args&&... args)
     -> decltype(std::forward<F>(f)(std::forward<Args>(args)...)) {
   return std::forward<F>(f)(std::forward<Args>(args)...);
 }
 
 template <typename M, typename C, typename... Args>
-inline auto invoke(M(C::*d), Args&&... args)
+inline constexpr auto invoke(M(C::*d), Args&&... args)
     -> decltype(std::mem_fn(d)(std::forward<Args>(args)...)) {
   return std::mem_fn(d)(std::forward<Args>(args)...);
 }
@@ -424,9 +424,6 @@ inline auto invoke(M(C::*d), Args&&... args)
 } // namespace function
 } // namespace detail
 
-FOLLY_PUSH_WARNING
-FOLLY_MSVC_DISABLE_WARNING(4521) // Multiple copy constructors
-FOLLY_MSVC_DISABLE_WARNING(4522) // Multiple assignment operators
 template <typename FunctionType>
 class Function final : private detail::function::FunctionTraits<FunctionType> {
   // These utility types are defined outside of the template to reduce
@@ -578,17 +575,23 @@ class Function final : private detail::function::FunctionTraits<FunctionType> {
 
   /**
    * Move assignment operator
+   *
+   * \note Leaves `that` in a valid but unspecified state. If `&that == this`
+   * then `*this` is left in a valid but unspecified state.
    */
   Function& operator=(Function&& that) noexcept {
-    if (&that != this) {
-      // Q: Why is is safe to destroy and reconstruct this object in place?
-      // A: Two reasons: First, `Function` is a final class, so in doing this
-      //    we aren't slicing off any derived parts. And second, the move
-      //    operation is guaranteed not to throw so we always leave the object
-      //    in a valid state.
-      this->~Function();
-      ::new (this) Function(std::move(that));
-    }
+    // Q: Why is is safe to destroy and reconstruct this object in place?
+    // A: Two reasons: First, `Function` is a final class, so in doing this
+    //    we aren't slicing off any derived parts. And second, the move
+    //    operation is guaranteed not to throw so we always leave the object
+    //    in a valid state.
+    // In the case of self-move (this == &that), this leaves the object in
+    // a default-constructed state. First the object is destroyed, then we
+    // pass the destroyed object to the move constructor. The first thing the
+    // move constructor does is default-construct the object. That object is
+    // "moved" into itself, which is a no-op for a default-constructed Function.
+    this->~Function();
+    ::new (this) Function(std::move(that));
     return *this;
   }
 
@@ -694,7 +697,6 @@ class Function final : private detail::function::FunctionTraits<FunctionType> {
     return std::move(*this).asSharedProxy();
   }
 };
-FOLLY_POP_WARNING
 
 template <typename FunctionType>
 void swap(Function<FunctionType>& lhs, Function<FunctionType>& rhs) noexcept {
@@ -738,6 +740,25 @@ Function<ReturnType(Args...) const> constCastFunction(
   return std::move(that);
 }
 
+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> {};
+}
+}
+
 /**
  * @class FunctionRef
  *
@@ -765,19 +786,21 @@ template <typename ReturnType, typename... Args>
 class FunctionRef<ReturnType(Args...)> final {
   using Call = ReturnType (*)(void*, Args&&...);
 
-  void* object_{nullptr};
-  Call call_{&FunctionRef::uninitCall};
-
   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>(detail::function::invoke(
-        *static_cast<Fun*>(object), static_cast<Args&&>(args)...));
+        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.
@@ -789,30 +812,27 @@ class FunctionRef<ReturnType(Args...)> final {
   /**
    * Construct a FunctionRef from a reference to a callable object.
    */
-  template <typename Fun>
-  /* implicit */ FunctionRef(Fun&& fun) noexcept {
-    using ReferencedType = typename std::remove_reference<Fun>::type;
-
-    static_assert(
-        std::is_convertible<
-            typename std::result_of<ReferencedType&(Args && ...)>::type,
-            ReturnType>::value,
-        "FunctionRef cannot be constructed from object with "
-        "incompatible function signature");
-
-    // `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<ReferencedType>;
-  }
+  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)...);
   }
 
-  explicit operator bool() const {
+  constexpr explicit operator bool() const {
     return object_;
   }
 };