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