File indexing completed on 2024-05-19 05:33:31
0001 /* 0002 SPDX-FileCopyrightText: 2019 Ivan Čukić <ivan.cukic(at)kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #ifndef UTILS_FRONT_BIND_H 0008 #define UTILS_FRONT_BIND_H 0009 0010 namespace std_ex { 0011 0012 // bind_front is based on http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0356r3.html 0013 0014 template <typename T> struct decay_unwrap; 0015 0016 template <typename T> struct decay_unwrap<std::reference_wrapper<T>> { 0017 using type = T &; 0018 }; 0019 0020 template <typename T> 0021 struct decay_unwrap 0022 : std::conditional_t<!std::is_same<std::decay_t<T>, T>::value, 0023 decay_unwrap<std::decay_t<T>>, std::decay<T>> { 0024 }; 0025 0026 template <typename T> using decay_unwrap_t = typename decay_unwrap<T>::type; 0027 0028 template <typename Func, typename BoundArgsTuple, typename... CallArgs> 0029 decltype(auto) bind_front_caller(Func &&func, BoundArgsTuple &&boundArgsTuple, 0030 CallArgs &&... callArgs) 0031 { 0032 return std::apply( 0033 [&func, &callArgs...](auto &&... boundArgs) -> decltype(auto) { 0034 return std::invoke(std::forward<Func>(func), 0035 std::forward<decltype(boundArgs)>(boundArgs)..., 0036 std::forward<CallArgs>(callArgs)...); 0037 }, 0038 std::forward<BoundArgsTuple>(boundArgsTuple)); 0039 } 0040 0041 template <typename Func, typename... BoundArgs> class bind_front_t { 0042 public: 0043 template < 0044 typename F, typename... BA, 0045 std::enable_if_t<!(sizeof...(BA) == 0 0046 && std::is_base_of_v<bind_front_t, std::decay_t<F>>), 0047 bool> = true> 0048 explicit bind_front_t(F &&f, BA &&... ba) 0049 : func(std::forward<F>(f)), boundArgs(std::forward<BA>(ba)...) 0050 { 0051 } 0052 0053 template <typename... CallArgs> 0054 auto operator()(CallArgs &&... callArgs) 0055 & noexcept( 0056 std::is_nothrow_invocable_v<Func &, BoundArgs &..., CallArgs...>) 0057 -> std::invoke_result_t<Func &, BoundArgs &..., CallArgs...> 0058 { 0059 return bind_front_caller(func, boundArgs, 0060 std::forward<CallArgs>(callArgs)...); 0061 } 0062 0063 template <typename... CallArgs> 0064 auto operator()(CallArgs &&... callArgs) const& noexcept( 0065 std::is_nothrow_invocable_v<const Func&, const BoundArgs&..., 0066 CallArgs...>) 0067 -> std::invoke_result_t<const Func&, const BoundArgs&..., CallArgs...> 0068 { 0069 return bind_front_caller(func, boundArgs, 0070 std::forward<CallArgs>(callArgs)...); 0071 } 0072 0073 template <typename... CallArgs> 0074 auto operator()(CallArgs &&... callArgs) 0075 && noexcept( 0076 std::is_nothrow_invocable_v<Func, BoundArgs..., CallArgs...>) 0077 -> std::invoke_result_t<Func, BoundArgs..., CallArgs...> 0078 { 0079 return bind_front_caller(std::move(func), std::move(boundArgs), 0080 std::forward<CallArgs>(callArgs)...); 0081 } 0082 0083 template <typename... CallArgs> 0084 auto operator()(CallArgs &&... callArgs) const&& noexcept( 0085 std::is_nothrow_invocable_v<const Func, const BoundArgs..., 0086 CallArgs...>) 0087 -> std::invoke_result_t<const Func, const BoundArgs..., CallArgs...> 0088 { 0089 return bind_front_caller(std::move(func), std::move(boundArgs), 0090 std::forward<CallArgs>(callArgs)...); 0091 } 0092 0093 private: 0094 Func func; 0095 std::tuple<BoundArgs...> boundArgs; 0096 }; 0097 0098 template <typename Func, typename... BoundArgs> 0099 auto bind_front(Func &&func, BoundArgs &&... boundArgs) 0100 { 0101 return bind_front_t<std::decay_t<Func>, decay_unwrap_t<BoundArgs>...>{ 0102 std::forward<Func>(func), std::forward<BoundArgs>(boundArgs)... 0103 }; 0104 } 0105 0106 } // namespace std_ex 0107 0108 #endif // include guard 0109