• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // A Tuple is a generic templatized container, similar in concept to std::pair
6 // and std::tuple.  The convenient MakeTuple() function takes any number of
7 // arguments and will construct and return the appropriate Tuple object.  The
8 // functions DispatchToMethod and DispatchToFunction take a function pointer or
9 // instance and method pointer, and unpack a tuple into arguments to the call.
10 //
11 // Tuple elements are copied by value, and stored in the tuple.  See the unit
12 // tests for more details of how/when the values are copied.
13 //
14 // Example usage:
15 //   // These two methods of creating a Tuple are identical.
16 //   Tuple<int, const char*> tuple_a(1, "wee");
17 //   Tuple<int, const char*> tuple_b = MakeTuple(1, "wee");
18 //
19 //   void SomeFunc(int a, const char* b) { }
20 //   DispatchToFunction(&SomeFunc, tuple_a);  // SomeFunc(1, "wee")
21 //   DispatchToFunction(
22 //       &SomeFunc, MakeTuple(10, "foo"));    // SomeFunc(10, "foo")
23 //
24 //   struct { void SomeMeth(int a, int b, int c) { } } foo;
25 //   DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3));
26 //   // foo->SomeMeth(1, 2, 3);
27 
28 #ifndef BASE_TUPLE_H_
29 #define BASE_TUPLE_H_
30 
31 #include <stddef.h>
32 
33 #include "base/bind_helpers.h"
34 #include "build/build_config.h"
35 
36 namespace base {
37 
38 // Index sequences
39 //
40 // Minimal clone of the similarly-named C++14 functionality.
41 
42 template <size_t...>
43 struct IndexSequence {};
44 
45 template <size_t... Ns>
46 struct MakeIndexSequenceImpl;
47 
48 #if defined(_PREFAST_) && defined(OS_WIN)
49 
50 // Work around VC++ 2013 /analyze internal compiler error:
51 // https://connect.microsoft.com/VisualStudio/feedback/details/1053626
52 
53 template <> struct MakeIndexSequenceImpl<0> {
54   using Type = IndexSequence<>;
55 };
56 template <> struct MakeIndexSequenceImpl<1> {
57   using Type = IndexSequence<0>;
58 };
59 template <> struct MakeIndexSequenceImpl<2> {
60   using Type = IndexSequence<0,1>;
61 };
62 template <> struct MakeIndexSequenceImpl<3> {
63   using Type = IndexSequence<0,1,2>;
64 };
65 template <> struct MakeIndexSequenceImpl<4> {
66   using Type = IndexSequence<0,1,2,3>;
67 };
68 template <> struct MakeIndexSequenceImpl<5> {
69   using Type = IndexSequence<0,1,2,3,4>;
70 };
71 template <> struct MakeIndexSequenceImpl<6> {
72   using Type = IndexSequence<0,1,2,3,4,5>;
73 };
74 template <> struct MakeIndexSequenceImpl<7> {
75   using Type = IndexSequence<0,1,2,3,4,5,6>;
76 };
77 template <> struct MakeIndexSequenceImpl<8> {
78   using Type = IndexSequence<0,1,2,3,4,5,6,7>;
79 };
80 template <> struct MakeIndexSequenceImpl<9> {
81   using Type = IndexSequence<0,1,2,3,4,5,6,7,8>;
82 };
83 template <> struct MakeIndexSequenceImpl<10> {
84   using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9>;
85 };
86 template <> struct MakeIndexSequenceImpl<11> {
87   using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10>;
88 };
89 template <> struct MakeIndexSequenceImpl<12> {
90   using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10,11>;
91 };
92 template <> struct MakeIndexSequenceImpl<13> {
93   using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10,11,12>;
94 };
95 
96 #else  // defined(WIN) && defined(_PREFAST_)
97 
98 template <size_t... Ns>
99 struct MakeIndexSequenceImpl<0, Ns...> {
100   using Type = IndexSequence<Ns...>;
101 };
102 
103 template <size_t N, size_t... Ns>
104 struct MakeIndexSequenceImpl<N, Ns...>
105     : MakeIndexSequenceImpl<N - 1, N - 1, Ns...> {};
106 
107 #endif  // defined(WIN) && defined(_PREFAST_)
108 
109 template <size_t N>
110 using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::Type;
111 
112 // Traits ----------------------------------------------------------------------
113 //
114 // A simple traits class for tuple arguments.
115 //
116 // ValueType: the bare, nonref version of a type (same as the type for nonrefs).
117 // RefType: the ref version of a type (same as the type for refs).
118 // ParamType: what type to pass to functions (refs should not be constified).
119 
120 template <class P>
121 struct TupleTraits {
122   typedef P ValueType;
123   typedef P& RefType;
124   typedef const P& ParamType;
125 };
126 
127 template <class P>
128 struct TupleTraits<P&> {
129   typedef P ValueType;
130   typedef P& RefType;
131   typedef P& ParamType;
132 };
133 
134 // Tuple -----------------------------------------------------------------------
135 //
136 // This set of classes is useful for bundling 0 or more heterogeneous data types
137 // into a single variable.  The advantage of this is that it greatly simplifies
138 // function objects that need to take an arbitrary number of parameters; see
139 // RunnableMethod and IPC::MessageWithTuple.
140 //
141 // Tuple<> is supplied to act as a 'void' type.  It can be used, for example,
142 // when dispatching to a function that accepts no arguments (see the
143 // Dispatchers below).
144 // Tuple<A> is rarely useful.  One such use is when A is non-const ref that you
145 // want filled by the dispatchee, and the tuple is merely a container for that
146 // output (a "tier").  See MakeRefTuple and its usages.
147 
148 template <typename IxSeq, typename... Ts>
149 struct TupleBaseImpl;
150 template <typename... Ts>
151 using TupleBase = TupleBaseImpl<MakeIndexSequence<sizeof...(Ts)>, Ts...>;
152 template <size_t N, typename T>
153 struct TupleLeaf;
154 
155 template <typename... Ts>
156 struct Tuple final : TupleBase<Ts...> {
157   Tuple() : TupleBase<Ts...>() {}
158   explicit Tuple(typename TupleTraits<Ts>::ParamType... args)
159       : TupleBase<Ts...>(args...) {}
160 };
161 
162 // Avoids ambiguity between Tuple's two constructors.
163 template <>
164 struct Tuple<> final {};
165 
166 template <size_t... Ns, typename... Ts>
167 struct TupleBaseImpl<IndexSequence<Ns...>, Ts...> : TupleLeaf<Ns, Ts>... {
168   TupleBaseImpl() : TupleLeaf<Ns, Ts>()... {}
169   explicit TupleBaseImpl(typename TupleTraits<Ts>::ParamType... args)
170       : TupleLeaf<Ns, Ts>(args)... {}
171 };
172 
173 template <size_t N, typename T>
174 struct TupleLeaf {
175   TupleLeaf() {}
176   explicit TupleLeaf(typename TupleTraits<T>::ParamType x) : x(x) {}
177 
178   T& get() { return x; }
179   const T& get() const { return x; }
180 
181   T x;
182 };
183 
184 // Tuple getters --------------------------------------------------------------
185 //
186 // Allows accessing an arbitrary tuple element by index.
187 //
188 // Example usage:
189 //   base::Tuple<int, double> t2;
190 //   base::get<0>(t2) = 42;
191 //   base::get<1>(t2) = 3.14;
192 
193 template <size_t I, typename T>
194 T& get(TupleLeaf<I, T>& leaf) {
195   return leaf.get();
196 }
197 
198 template <size_t I, typename T>
199 const T& get(const TupleLeaf<I, T>& leaf) {
200   return leaf.get();
201 }
202 
203 // Tuple types ----------------------------------------------------------------
204 //
205 // Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the
206 // definitions of class types the tuple takes as parameters.
207 
208 template <typename T>
209 struct TupleTypes;
210 
211 template <typename... Ts>
212 struct TupleTypes<Tuple<Ts...>> {
213   using ValueTuple = Tuple<typename TupleTraits<Ts>::ValueType...>;
214   using RefTuple = Tuple<typename TupleTraits<Ts>::RefType...>;
215   using ParamTuple = Tuple<typename TupleTraits<Ts>::ParamType...>;
216 };
217 
218 // Tuple creators -------------------------------------------------------------
219 //
220 // Helper functions for constructing tuples while inferring the template
221 // argument types.
222 
223 template <typename... Ts>
224 inline Tuple<Ts...> MakeTuple(const Ts&... arg) {
225   return Tuple<Ts...>(arg...);
226 }
227 
228 // The following set of helpers make what Boost refers to as "Tiers" - a tuple
229 // of references.
230 
231 template <typename... Ts>
232 inline Tuple<Ts&...> MakeRefTuple(Ts&... arg) {
233   return Tuple<Ts&...>(arg...);
234 }
235 
236 // Dispatchers ----------------------------------------------------------------
237 //
238 // Helper functions that call the given method on an object, with the unpacked
239 // tuple arguments.  Notice that they all have the same number of arguments,
240 // so you need only write:
241 //   DispatchToMethod(object, &Object::method, args);
242 // This is very useful for templated dispatchers, since they don't need to know
243 // what type |args| is.
244 
245 // Non-Static Dispatchers with no out params.
246 
247 template <typename ObjT, typename Method, typename... Ts, size_t... Ns>
248 inline void DispatchToMethodImpl(ObjT* obj,
249                                  Method method,
250                                  const Tuple<Ts...>& arg,
251                                  IndexSequence<Ns...>) {
252   (obj->*method)(base::internal::UnwrapTraits<Ts>::Unwrap(get<Ns>(arg))...);
253 }
254 
255 template <typename ObjT, typename Method, typename... Ts>
256 inline void DispatchToMethod(ObjT* obj,
257                              Method method,
258                              const Tuple<Ts...>& arg) {
259   DispatchToMethodImpl(obj, method, arg, MakeIndexSequence<sizeof...(Ts)>());
260 }
261 
262 // Static Dispatchers with no out params.
263 
264 template <typename Function, typename... Ts, size_t... Ns>
265 inline void DispatchToFunctionImpl(Function function,
266                                    const Tuple<Ts...>& arg,
267                                    IndexSequence<Ns...>) {
268   (*function)(base::internal::UnwrapTraits<Ts>::Unwrap(get<Ns>(arg))...);
269 }
270 
271 template <typename Function, typename... Ts>
272 inline void DispatchToFunction(Function function, const Tuple<Ts...>& arg) {
273   DispatchToFunctionImpl(function, arg, MakeIndexSequence<sizeof...(Ts)>());
274 }
275 
276 // Dispatchers with out parameters.
277 
278 template <typename ObjT,
279           typename Method,
280           typename... InTs,
281           typename... OutTs,
282           size_t... InNs,
283           size_t... OutNs>
284 inline void DispatchToMethodImpl(ObjT* obj,
285                                  Method method,
286                                  const Tuple<InTs...>& in,
287                                  Tuple<OutTs...>* out,
288                                  IndexSequence<InNs...>,
289                                  IndexSequence<OutNs...>) {
290   (obj->*method)(base::internal::UnwrapTraits<InTs>::Unwrap(get<InNs>(in))...,
291                  &get<OutNs>(*out)...);
292 }
293 
294 template <typename ObjT, typename Method, typename... InTs, typename... OutTs>
295 inline void DispatchToMethod(ObjT* obj,
296                              Method method,
297                              const Tuple<InTs...>& in,
298                              Tuple<OutTs...>* out) {
299   DispatchToMethodImpl(obj, method, in, out,
300                        MakeIndexSequence<sizeof...(InTs)>(),
301                        MakeIndexSequence<sizeof...(OutTs)>());
302 }
303 
304 }  // namespace base
305 
306 #endif  // BASE_TUPLE_H_
307