1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Use std::tuple as tuple type. This file contains helper functions for 6 // working with std::tuples. 7 // The functions DispatchToMethod and DispatchToFunction take a function pointer 8 // or instance and method pointer, and unpack a tuple into arguments to the 9 // call. 10 // 11 // Example usage: 12 // // These two methods of creating a Tuple are identical. 13 // std::tuple<int, const char*> tuple_a(1, "wee"); 14 // std::tuple<int, const char*> tuple_b = std::make_tuple(1, "wee"); 15 // 16 // void SomeFunc(int a, const char* b) { } 17 // DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee") 18 // DispatchToFunction( 19 // &SomeFunc, std::make_tuple(10, "foo")); // SomeFunc(10, "foo") 20 // 21 // struct { void SomeMeth(int a, int b, int c) { } } foo; 22 // DispatchToMethod(&foo, &Foo::SomeMeth, std::make_tuple(1, 2, 3)); 23 // // foo->SomeMeth(1, 2, 3); 24 25 #ifndef BASE_TUPLE_H_ 26 #define BASE_TUPLE_H_ 27 28 #include <stddef.h> 29 #include <tuple> 30 31 #include "build/build_config.h" 32 33 namespace base { 34 35 // Index sequences 36 // 37 // Minimal clone of the similarly-named C++14 functionality. 38 39 template <size_t...> 40 struct IndexSequence {}; 41 42 template <size_t... Ns> 43 struct MakeIndexSequenceImpl; 44 45 template <size_t... Ns> 46 struct MakeIndexSequenceImpl<0, Ns...> { 47 using Type = IndexSequence<Ns...>; 48 }; 49 50 template <size_t N, size_t... Ns> 51 struct MakeIndexSequenceImpl<N, Ns...> 52 : MakeIndexSequenceImpl<N - 1, N - 1, Ns...> {}; 53 54 // std::get() in <=libstdc++-4.6 returns an lvalue-reference for 55 // rvalue-reference of a tuple, where an rvalue-reference is expected. 56 template <size_t I, typename... Ts> 57 typename std::tuple_element<I, std::tuple<Ts...>>::type&& get( 58 std::tuple<Ts...>&& t) { 59 using ElemType = typename std::tuple_element<I, std::tuple<Ts...>>::type; 60 return std::forward<ElemType>(std::get<I>(t)); 61 } 62 63 template <size_t I, typename T> 64 auto get(T& t) -> decltype(std::get<I>(t)) { 65 return std::get<I>(t); 66 } 67 68 template <size_t N> 69 using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::Type; 70 71 template <typename T> 72 using MakeIndexSequenceForTuple = 73 MakeIndexSequence<std::tuple_size<typename std::decay<T>::type>::value>; 74 75 // Dispatchers ---------------------------------------------------------------- 76 // 77 // Helper functions that call the given method on an object, with the unpacked 78 // tuple arguments. Notice that they all have the same number of arguments, 79 // so you need only write: 80 // DispatchToMethod(object, &Object::method, args); 81 // This is very useful for templated dispatchers, since they don't need to know 82 // what type |args| is. 83 84 // Non-Static Dispatchers with no out params. 85 86 template <typename ObjT, typename Method, typename Tuple, size_t... Ns> 87 inline void DispatchToMethodImpl(const ObjT& obj, 88 Method method, 89 Tuple&& args, 90 IndexSequence<Ns...>) { 91 (obj->*method)(base::get<Ns>(std::forward<Tuple>(args))...); 92 } 93 94 template <typename ObjT, typename Method, typename Tuple> 95 inline void DispatchToMethod(const ObjT& obj, 96 Method method, 97 Tuple&& args) { 98 DispatchToMethodImpl(obj, method, std::forward<Tuple>(args), 99 MakeIndexSequenceForTuple<Tuple>()); 100 } 101 102 // Static Dispatchers with no out params. 103 104 template <typename Function, typename Tuple, size_t... Ns> 105 inline void DispatchToFunctionImpl(Function function, 106 Tuple&& args, 107 IndexSequence<Ns...>) { 108 (*function)(base::get<Ns>(std::forward<Tuple>(args))...); 109 } 110 111 template <typename Function, typename Tuple> 112 inline void DispatchToFunction(Function function, Tuple&& args) { 113 DispatchToFunctionImpl(function, std::forward<Tuple>(args), 114 MakeIndexSequenceForTuple<Tuple>()); 115 } 116 117 // Dispatchers with out parameters. 118 119 template <typename ObjT, 120 typename Method, 121 typename InTuple, 122 typename OutTuple, 123 size_t... InNs, 124 size_t... OutNs> 125 inline void DispatchToMethodImpl(const ObjT& obj, 126 Method method, 127 InTuple&& in, 128 OutTuple* out, 129 IndexSequence<InNs...>, 130 IndexSequence<OutNs...>) { 131 (obj->*method)(base::get<InNs>(std::forward<InTuple>(in))..., 132 &std::get<OutNs>(*out)...); 133 } 134 135 template <typename ObjT, typename Method, typename InTuple, typename OutTuple> 136 inline void DispatchToMethod(const ObjT& obj, 137 Method method, 138 InTuple&& in, 139 OutTuple* out) { 140 DispatchToMethodImpl(obj, method, std::forward<InTuple>(in), out, 141 MakeIndexSequenceForTuple<InTuple>(), 142 MakeIndexSequenceForTuple<OutTuple>()); 143 } 144 145 } // namespace base 146 147 #endif // BASE_TUPLE_H_ 148