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