libshit

Just some random shit
git clone https://git.neptards.moe/neptards/libshit.git
Log | Files | Refs | Submodules | README | LICENSE

functional (4113B)


      1 // -*- c++ -*-
      2 #pragma once
      3 
      4 #include <type_traits>
      5 #include_next <functional>
      6 
      7 namespace std
      8 {
      9   // based on http://en.cppreference.com/w/cpp/utility/functional/invoke
     10   namespace detail
     11   {
     12     template <typename T>
     13     struct is_reference_wrapper : false_type {};
     14 
     15     template <typename U>
     16     struct is_reference_wrapper<reference_wrapper<U>> : true_type {};
     17 
     18     template <typename T>
     19     constexpr bool is_reference_wrapper_v = is_reference_wrapper<T>::value;
     20 
     21 #define _DEF_INVOKE(check, ret)                                         \
     22     template <typename T, typename Type, typename T1, typename... Args> \
     23     auto INVOKE(Type T::* f, T1&& t1, Args&&... args)                   \
     24       noexcept(noexcept(ret))                                           \
     25       -> enable_if_t<                                                   \
     26         is_member_function_pointer_v<decltype(f)> && check,             \
     27         decltype(ret)>                                                  \
     28     { return ret; }
     29 
     30     _DEF_INVOKE(
     31       (is_base_of_v<T, decay_t<T1>>),
     32       (std::forward<T1>(t1).*f)(std::forward<Args>(args)...))
     33     _DEF_INVOKE(
     34       (!is_base_of_v<T, decay_t<T1>> &&
     35        is_reference_wrapper_v<decay_t<T1>>),
     36       (t1.get().*f)(std::forward<Args>(args)...))
     37     _DEF_INVOKE(
     38       (!is_base_of_v<T, decay_t<T1>> &&
     39        !is_reference_wrapper_v<decay_t<T1>>),
     40       ((*std::forward<T1>(t1)).*f)(std::forward<Args>(args)...))
     41 #undef _DEF_INVOKE
     42 
     43 #define _DEF_INVOKE(check, ret)                                \
     44     template <typename T, typename Type, typename T1>          \
     45     auto INVOKE(Type T::* f, T1&& t1)                          \
     46       noexcept(noexcept(ret))                                  \
     47       -> enable_if_t<                                          \
     48         is_member_object_pointer_v<decltype(f)> && check,      \
     49         decltype(ret)>                                         \
     50     { return ret; }
     51 
     52     _DEF_INVOKE(
     53       (is_base_of_v<T, decay_t<T1>>),
     54       std::forward<T1>(t1).*f)
     55     _DEF_INVOKE(
     56       (!is_base_of_v<T, decay_t<T1>> &&
     57        is_reference_wrapper_v<decay_t<T1>>),
     58       t1.get().*f)
     59     _DEF_INVOKE(
     60       (!is_base_of_v<T, decay_t<T1>> &&
     61        !is_reference_wrapper_v<decay_t<T1>>),
     62       (*std::forward<T1>(t1)).*f)
     63 #undef _DEF_INVOKE
     64 
     65     template <class F, class... Args>
     66     auto INVOKE(F&& f, Args&&... args)
     67       noexcept(noexcept(std::forward<F>(f)(std::forward<Args>(args)...)))
     68       -> enable_if_t<
     69         !is_member_function_pointer_v<F>,
     70         decltype(std::forward<F>(f)(std::forward<Args>(args)...))>
     71     {
     72       return std::forward<F>(f)(std::forward<Args>(args)...);
     73     }
     74 
     75     template <typename AlwaysVoid, typename F, typename... Args>
     76     struct invoke_result
     77     {
     78       decltype(void(INVOKE(declval<F>(), declval<Args>()...)))* x;
     79     };
     80     template <typename F, typename... Args>
     81     struct invoke_result<
     82       decltype(void(INVOKE(declval<F>(), declval<Args>()...))),
     83       F, Args...>
     84     {
     85       using type = decltype(INVOKE(declval<F>(), declval<Args>()...));
     86     };
     87 
     88     template <bool AlwaysTrue, typename F, typename... Args>
     89     struct is_nothrow_invocable : false_type {};
     90 
     91     template <typename F, typename... Args>
     92     struct is_nothrow_invocable<
     93       noexcept(INVOKE(declval<F>(), declval<Args>()...)),
     94       F, Args...> : true_type {};
     95   }
     96 
     97 
     98   template <typename F, typename... ArgTypes>
     99   struct invoke_result : detail::invoke_result<void, F, ArgTypes...> {};
    100 
    101   template <typename F, typename... ArgTypes>
    102   using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
    103 
    104   template <typename F, typename... ArgTypes>
    105   struct is_nothrow_invocable
    106     : detail::is_nothrow_invocable<true, F, ArgTypes...> {};
    107 
    108   template <typename F, typename... ArgTypes>
    109   inline constexpr bool is_nothrow_invocable_v =
    110     is_nothrow_invocable<F, ArgTypes...>::value;
    111 
    112   template <typename F, typename... Args>
    113   invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
    114     noexcept(is_nothrow_invocable_v<F, Args...>)
    115   {
    116     return detail::INVOKE(std::forward<F>(f), std::forward<Args>(args)...);
    117   }
    118 }