tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

invoke.h (5152B)


      1 // Copyright 2020 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_FUNCTIONAL_INVOKE_H_
      6 #define BASE_FUNCTIONAL_INVOKE_H_
      7 
      8 #include <type_traits>
      9 #include <utility>
     10 
     11 namespace base {
     12 
     13 namespace internal {
     14 
     15 // Helper struct and alias to deduce the class type from a member function
     16 // pointer or member object pointer.
     17 template <typename DecayedF>
     18 struct member_pointer_class {};
     19 
     20 template <typename ReturnT, typename ClassT>
     21 struct member_pointer_class<ReturnT ClassT::*> {
     22  using type = ClassT;
     23 };
     24 
     25 template <typename DecayedF>
     26 using member_pointer_class_t = typename member_pointer_class<DecayedF>::type;
     27 
     28 // Utility struct to detect specializations of std::reference_wrapper.
     29 template <typename T>
     30 struct is_reference_wrapper : std::false_type {};
     31 
     32 template <typename T>
     33 struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
     34 
     35 // Small helpers used below in internal::invoke to make the SFINAE more concise.
     36 template <typename F>
     37 const bool& IsMemFunPtr = std::is_member_function_pointer_v<std::decay_t<F>>;
     38 
     39 template <typename F>
     40 const bool& IsMemObjPtr = std::is_member_object_pointer_v<std::decay_t<F>>;
     41 
     42 template <typename F,
     43          typename T,
     44          typename MemPtrClass = member_pointer_class_t<std::decay_t<F>>>
     45 const bool& IsMemPtrToBaseOf = std::is_base_of_v<MemPtrClass, std::decay_t<T>>;
     46 
     47 template <typename T>
     48 const bool& IsRefWrapper = is_reference_wrapper<std::decay_t<T>>::value;
     49 
     50 template <bool B>
     51 using EnableIf = std::enable_if_t<B, bool>;
     52 
     53 // Invokes a member function pointer on a reference to an object of a suitable
     54 // type. Covers bullet 1 of the INVOKE definition.
     55 //
     56 // Reference: https://wg21.link/func.require#1.1
     57 template <typename F,
     58          typename T1,
     59          typename... Args,
     60          EnableIf<IsMemFunPtr<F> && IsMemPtrToBaseOf<F, T1>> = true>
     61 constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1, Args&&... args) {
     62  return (std::forward<T1>(t1).*f)(std::forward<Args>(args)...);
     63 }
     64 
     65 // Invokes a member function pointer on a std::reference_wrapper to an object of
     66 // a suitable type. Covers bullet 2 of the INVOKE definition.
     67 //
     68 // Reference: https://wg21.link/func.require#1.2
     69 template <typename F,
     70          typename T1,
     71          typename... Args,
     72          EnableIf<IsMemFunPtr<F> && IsRefWrapper<T1>> = true>
     73 constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1, Args&&... args) {
     74  return (t1.get().*f)(std::forward<Args>(args)...);
     75 }
     76 
     77 // Invokes a member function pointer on a pointer-like type to an object of a
     78 // suitable type. Covers bullet 3 of the INVOKE definition.
     79 //
     80 // Reference: https://wg21.link/func.require#1.3
     81 template <typename F,
     82          typename T1,
     83          typename... Args,
     84          EnableIf<IsMemFunPtr<F> && !IsMemPtrToBaseOf<F, T1> &&
     85                   !IsRefWrapper<T1>> = true>
     86 constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1, Args&&... args) {
     87  return ((*std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
     88 }
     89 
     90 // Invokes a member object pointer on a reference to an object of a suitable
     91 // type. Covers bullet 4 of the INVOKE definition.
     92 //
     93 // Reference: https://wg21.link/func.require#1.4
     94 template <typename F,
     95          typename T1,
     96          EnableIf<IsMemObjPtr<F> && IsMemPtrToBaseOf<F, T1>> = true>
     97 constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1) {
     98  return std::forward<T1>(t1).*f;
     99 }
    100 
    101 // Invokes a member object pointer on a std::reference_wrapper to an object of
    102 // a suitable type. Covers bullet 5 of the INVOKE definition.
    103 //
    104 // Reference: https://wg21.link/func.require#1.5
    105 template <typename F,
    106          typename T1,
    107          EnableIf<IsMemObjPtr<F> && IsRefWrapper<T1>> = true>
    108 constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1) {
    109  return t1.get().*f;
    110 }
    111 
    112 // Invokes a member object pointer on a pointer-like type to an object of a
    113 // suitable type. Covers bullet 6 of the INVOKE definition.
    114 //
    115 // Reference: https://wg21.link/func.require#1.6
    116 template <typename F,
    117          typename T1,
    118          EnableIf<IsMemObjPtr<F> && !IsMemPtrToBaseOf<F, T1> &&
    119                   !IsRefWrapper<T1>> = true>
    120 constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1) {
    121  return (*std::forward<T1>(t1)).*f;
    122 }
    123 
    124 // Invokes a regular function or function object. Covers bullet 7 of the INVOKE
    125 // definition.
    126 //
    127 // Reference: https://wg21.link/func.require#1.7
    128 template <typename F, typename... Args>
    129 constexpr decltype(auto) InvokeImpl(F&& f, Args&&... args) {
    130  return std::forward<F>(f)(std::forward<Args>(args)...);
    131 }
    132 
    133 }  // namespace internal
    134 
    135 // Implementation of C++17's std::invoke. This is not based on implementation
    136 // referenced in original std::invoke proposal, but rather a manual
    137 // implementation, so that it can be constexpr.
    138 //
    139 // References:
    140 // - https://wg21.link/n4169#implementability
    141 // - https://en.cppreference.com/w/cpp/utility/functional/invoke
    142 // - https://wg21.link/func.invoke
    143 template <typename F, typename... Args>
    144 constexpr decltype(auto) invoke(F&& f, Args&&... args) {
    145  return internal::InvokeImpl(std::forward<F>(f), std::forward<Args>(args)...);
    146 }
    147 
    148 }  // namespace base
    149 
    150 #endif  // BASE_FUNCTIONAL_INVOKE_H_