Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: base/tuple.h

Issue 792763002: tuple: further generalize/simplify Tuple implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // A Tuple is a generic templatized container, similar in concept to std::pair. 5 // A Tuple is a generic templatized container, similar in concept to std::pair
6 // There are classes Tuple0 to Tuple6, cooresponding to the number of elements 6 // and std::tuple. The convenient MakeTuple() function takes any number of
7 // it contains. The convenient MakeTuple() function takes 0 to 6 arguments, 7 // arguments and will construct and return the appropriate Tuple object. The
8 // and will construct and return the appropriate Tuple object. The functions 8 // functions DispatchToMethod and DispatchToFunction take a function pointer or
9 // DispatchToMethod and DispatchToFunction take a function pointer or instance 9 // instance and method pointer, and unpack a tuple into arguments to the call.
10 // and method pointer, and unpack a tuple into arguments to the call.
11 // 10 //
12 // Tuple elements are copied by value, and stored in the tuple. See the unit 11 // Tuple elements are copied by value, and stored in the tuple. See the unit
13 // tests for more details of how/when the values are copied. 12 // tests for more details of how/when the values are copied.
14 // 13 //
15 // Example usage: 14 // Example usage:
16 // // These two methods of creating a Tuple are identical. 15 // // These two methods of creating a Tuple are identical.
17 // Tuple2<int, const char*> tuple_a(1, "wee"); 16 // Tuple<int, const char*> tuple_a(1, "wee");
18 // Tuple2<int, const char*> tuple_b = MakeTuple(1, "wee"); 17 // Tuple<int, const char*> tuple_b = MakeTuple(1, "wee");
19 // 18 //
20 // void SomeFunc(int a, const char* b) { } 19 // void SomeFunc(int a, const char* b) { }
21 // DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee") 20 // DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee")
22 // DispatchToFunction( 21 // DispatchToFunction(
23 // &SomeFunc, MakeTuple(10, "foo")); // SomeFunc(10, "foo") 22 // &SomeFunc, MakeTuple(10, "foo")); // SomeFunc(10, "foo")
24 // 23 //
25 // struct { void SomeMeth(int a, int b, int c) { } } foo; 24 // struct { void SomeMeth(int a, int b, int c) { } } foo;
26 // DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3)); 25 // DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3));
27 // // foo->SomeMeth(1, 2, 3); 26 // // foo->SomeMeth(1, 2, 3);
28 27
(...skipping 11 matching lines...) Expand all
40 39
41 template <size_t... Ns> 40 template <size_t... Ns>
42 struct MakeIndexSequenceImpl; 41 struct MakeIndexSequenceImpl;
43 42
44 template <size_t... Ns> 43 template <size_t... Ns>
45 struct MakeIndexSequenceImpl<0, Ns...> { 44 struct MakeIndexSequenceImpl<0, Ns...> {
46 using Type = IndexSequence<Ns...>; 45 using Type = IndexSequence<Ns...>;
47 }; 46 };
48 47
49 template <size_t N, size_t... Ns> 48 template <size_t N, size_t... Ns>
50 struct MakeIndexSequenceImpl<N, Ns...> { 49 struct MakeIndexSequenceImpl<N, Ns...>
51 using Type = typename MakeIndexSequenceImpl<N - 1, N - 1, Ns...>::Type; 50 : public MakeIndexSequenceImpl<N - 1, N - 1, Ns...> {};
tzik 2014/12/10 06:43:27 can we remove "public" since it's default for stru
mdempsky 2014/12/10 07:46:03 Done (here and below).
52 };
53 51
54 template <size_t N> 52 template <size_t N>
55 using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::Type; 53 using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::Type;
56 54
57 // Traits ---------------------------------------------------------------------- 55 // Traits ----------------------------------------------------------------------
58 // 56 //
59 // A simple traits class for tuple arguments. 57 // A simple traits class for tuple arguments.
60 // 58 //
61 // ValueType: the bare, nonref version of a type (same as the type for nonrefs). 59 // ValueType: the bare, nonref version of a type (same as the type for nonrefs).
62 // RefType: the ref version of a type (same as the type for refs). 60 // RefType: the ref version of a type (same as the type for refs).
(...skipping 13 matching lines...) Expand all
76 typedef P& ParamType; 74 typedef P& ParamType;
77 }; 75 };
78 76
79 // Tuple ----------------------------------------------------------------------- 77 // Tuple -----------------------------------------------------------------------
80 // 78 //
81 // This set of classes is useful for bundling 0 or more heterogeneous data types 79 // This set of classes is useful for bundling 0 or more heterogeneous data types
82 // into a single variable. The advantage of this is that it greatly simplifies 80 // into a single variable. The advantage of this is that it greatly simplifies
83 // function objects that need to take an arbitrary number of parameters; see 81 // function objects that need to take an arbitrary number of parameters; see
84 // RunnableMethod and IPC::MessageWithTuple. 82 // RunnableMethod and IPC::MessageWithTuple.
85 // 83 //
86 // Tuple0 is supplied to act as a 'void' type. It can be used, for example, 84 // Tuple<> is supplied to act as a 'void' type. It can be used, for example,
87 // when dispatching to a function that accepts no arguments (see the 85 // when dispatching to a function that accepts no arguments (see the
88 // Dispatchers below). 86 // Dispatchers below).
89 // Tuple1<A> is rarely useful. One such use is when A is non-const ref that you 87 // Tuple<A> is rarely useful. One such use is when A is non-const ref that you
90 // want filled by the dispatchee, and the tuple is merely a container for that 88 // want filled by the dispatchee, and the tuple is merely a container for that
91 // output (a "tier"). See MakeRefTuple and its usages. 89 // output (a "tier"). See MakeRefTuple and its usages.
92 90
91 template <typename IxSeq, typename... Ts>
92 struct TupleBaseImpl;
93 template <typename... Ts> 93 template <typename... Ts>
94 struct Tuple; 94 using TupleBase = TupleBaseImpl<MakeIndexSequence<sizeof...(Ts)>, Ts...>;
95 template <size_t N, typename T>
96 struct TupleLeaf;
95 97
98 template <typename... Ts>
99 struct Tuple : public TupleBase<Ts...> {
100 Tuple() : TupleBase<Ts...>() {}
Nico 2014/12/10 07:00:31 Isn't this the same as the constructor in the line
mdempsky 2014/12/10 07:15:23 If I understand your question: "for Tuple<>, would
mdempsky 2014/12/10 07:46:03 (On the chance that issue was the Tuple<> speciali
101 explicit Tuple(typename TupleTraits<Ts>::ParamType... args)
102 : TupleBase<Ts...>(args...) {}
103 };
104
105 template <size_t... Ns, typename... Ts>
106 struct TupleBaseImpl<IndexSequence<Ns...>, Ts...>
107 : public TupleLeaf<Ns, Ts>... {
108 TupleBaseImpl() : TupleLeaf<Ns, Ts>()... {}
Nico 2014/12/10 07:00:31 same question
109 explicit TupleBaseImpl(typename TupleTraits<Ts>::ParamType... args)
110 : TupleLeaf<Ns, Ts>(args)... {}
111 };
112
113 template <size_t N, typename T>
114 struct TupleLeaf {
115 TupleLeaf() : x() {}
116 explicit TupleLeaf(typename TupleTraits<T>::ParamType x) : x(x) {}
117
118 T& get() { return x; }
119 const T& get() const { return x; }
120
121 T x;
122 };
123
124 // Avoids ambiguity between Tuple's two constructors.
96 template <> 125 template <>
97 struct Tuple<> {}; 126 struct Tuple<> {};
98 127
99 template <typename A> 128 // For legacy compatibility, we name the first 8 tuple elements "a", "b", ...
Nico 2014/12/10 07:00:31 Does it make sense to remove all clients of this a
mdempsky 2014/12/10 07:46:03 Done.
100 struct Tuple<A> {
101 public:
102 typedef A TypeA;
103 129
104 Tuple() {} 130 #define DEFINE_TUPLE_LEAF(N, x) \
105 explicit Tuple(typename TupleTraits<A>::ParamType a) : a(a) {} 131 template <typename T> \
132 struct TupleLeaf<N, T> { \
133 TupleLeaf() : x() {} \
134 explicit TupleLeaf(typename TupleTraits<T>::ParamType x) : x(x) {} \
135 \
136 T& get() { return x; } \
137 const T& get() const { return x; } \
138 \
139 T x; \
140 }
106 141
107 A a; 142 DEFINE_TUPLE_LEAF(0, a);
108 }; 143 DEFINE_TUPLE_LEAF(1, b);
144 DEFINE_TUPLE_LEAF(2, c);
145 DEFINE_TUPLE_LEAF(3, d);
146 DEFINE_TUPLE_LEAF(4, e);
147 DEFINE_TUPLE_LEAF(5, f);
148 DEFINE_TUPLE_LEAF(6, g);
149 DEFINE_TUPLE_LEAF(7, h);
109 150
110 template <typename A, typename B> 151 #undef DEFINE_TUPLE_LEAF
111 struct Tuple<A, B> {
112 public:
113 typedef A TypeA;
114 typedef B TypeB;
115
116 Tuple() {}
117 Tuple(typename TupleTraits<A>::ParamType a,
118 typename TupleTraits<B>::ParamType b)
119 : a(a), b(b) {}
120
121 A a;
122 B b;
123 };
124
125 template <typename A, typename B, typename C>
126 struct Tuple<A, B, C> {
127 public:
128 typedef A TypeA;
129 typedef B TypeB;
130 typedef C TypeC;
131
132 Tuple() {}
133 Tuple(typename TupleTraits<A>::ParamType a,
134 typename TupleTraits<B>::ParamType b,
135 typename TupleTraits<C>::ParamType c)
136 : a(a), b(b), c(c) {}
137
138 A a;
139 B b;
140 C c;
141 };
142
143 template <typename A, typename B, typename C, typename D>
144 struct Tuple<A, B, C, D> {
145 public:
146 typedef A TypeA;
147 typedef B TypeB;
148 typedef C TypeC;
149 typedef D TypeD;
150
151 Tuple() {}
152 Tuple(typename TupleTraits<A>::ParamType a,
153 typename TupleTraits<B>::ParamType b,
154 typename TupleTraits<C>::ParamType c,
155 typename TupleTraits<D>::ParamType d)
156 : a(a), b(b), c(c), d(d) {}
157
158 A a;
159 B b;
160 C c;
161 D d;
162 };
163
164 template <typename A, typename B, typename C, typename D, typename E>
165 struct Tuple<A, B, C, D, E> {
166 public:
167 typedef A TypeA;
168 typedef B TypeB;
169 typedef C TypeC;
170 typedef D TypeD;
171 typedef E TypeE;
172
173 Tuple() {}
174 Tuple(typename TupleTraits<A>::ParamType a,
175 typename TupleTraits<B>::ParamType b,
176 typename TupleTraits<C>::ParamType c,
177 typename TupleTraits<D>::ParamType d,
178 typename TupleTraits<E>::ParamType e)
179 : a(a), b(b), c(c), d(d), e(e) {}
180
181 A a;
182 B b;
183 C c;
184 D d;
185 E e;
186 };
187
188 template <typename A,
189 typename B,
190 typename C,
191 typename D,
192 typename E,
193 typename F>
194 struct Tuple<A, B, C, D, E, F> {
195 public:
196 typedef A TypeA;
197 typedef B TypeB;
198 typedef C TypeC;
199 typedef D TypeD;
200 typedef E TypeE;
201 typedef F TypeF;
202
203 Tuple() {}
204 Tuple(typename TupleTraits<A>::ParamType a,
205 typename TupleTraits<B>::ParamType b,
206 typename TupleTraits<C>::ParamType c,
207 typename TupleTraits<D>::ParamType d,
208 typename TupleTraits<E>::ParamType e,
209 typename TupleTraits<F>::ParamType f)
210 : a(a), b(b), c(c), d(d), e(e), f(f) {}
211
212 A a;
213 B b;
214 C c;
215 D d;
216 E e;
217 F f;
218 };
219
220 template <typename A,
221 typename B,
222 typename C,
223 typename D,
224 typename E,
225 typename F,
226 typename G>
227 struct Tuple<A, B, C, D, E, F, G> {
228 public:
229 typedef A TypeA;
230 typedef B TypeB;
231 typedef C TypeC;
232 typedef D TypeD;
233 typedef E TypeE;
234 typedef F TypeF;
235 typedef G TypeG;
236
237 Tuple() {}
238 Tuple(typename TupleTraits<A>::ParamType a,
239 typename TupleTraits<B>::ParamType b,
240 typename TupleTraits<C>::ParamType c,
241 typename TupleTraits<D>::ParamType d,
242 typename TupleTraits<E>::ParamType e,
243 typename TupleTraits<F>::ParamType f,
244 typename TupleTraits<G>::ParamType g)
245 : a(a), b(b), c(c), d(d), e(e), f(f), g(g) {}
246
247 A a;
248 B b;
249 C c;
250 D d;
251 E e;
252 F f;
253 G g;
254 };
255
256 template <typename A,
257 typename B,
258 typename C,
259 typename D,
260 typename E,
261 typename F,
262 typename G,
263 typename H>
264 struct Tuple<A, B, C, D, E, F, G, H> {
265 public:
266 typedef A TypeA;
267 typedef B TypeB;
268 typedef C TypeC;
269 typedef D TypeD;
270 typedef E TypeE;
271 typedef F TypeF;
272 typedef G TypeG;
273 typedef H TypeH;
274
275 Tuple() {}
276 Tuple(typename TupleTraits<A>::ParamType a,
277 typename TupleTraits<B>::ParamType b,
278 typename TupleTraits<C>::ParamType c,
279 typename TupleTraits<D>::ParamType d,
280 typename TupleTraits<E>::ParamType e,
281 typename TupleTraits<F>::ParamType f,
282 typename TupleTraits<G>::ParamType g,
283 typename TupleTraits<H>::ParamType h)
284 : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h) {}
285
286 A a;
287 B b;
288 C c;
289 D d;
290 E e;
291 F f;
292 G g;
293 H h;
294 };
295 152
296 // Deprecated compat aliases 153 // Deprecated compat aliases
297 154
298 using Tuple0 = Tuple<>; 155 using Tuple0 = Tuple<>;
299 template <typename A> 156 template <typename A>
300 using Tuple1 = Tuple<A>; 157 using Tuple1 = Tuple<A>;
301 template <typename A, typename B> 158 template <typename A, typename B>
302 using Tuple2 = Tuple<A, B>; 159 using Tuple2 = Tuple<A, B>;
303 template <typename A, typename B, typename C> 160 template <typename A, typename B, typename C>
304 using Tuple3 = Tuple<A, B, C>; 161 using Tuple3 = Tuple<A, B, C>;
(...skipping 21 matching lines...) Expand all
326 typename C, 183 typename C,
327 typename D, 184 typename D,
328 typename E, 185 typename E,
329 typename F, 186 typename F,
330 typename G, 187 typename G,
331 typename H> 188 typename H>
332 using Tuple8 = Tuple<A, B, C, D, E, F, G, H>; 189 using Tuple8 = Tuple<A, B, C, D, E, F, G, H>;
333 190
334 // Tuple element -------------------------------------------------------------- 191 // Tuple element --------------------------------------------------------------
335 192
336 template <size_t N, typename T> 193 template <size_t N, typename... Ts>
337 struct TupleElement; 194 struct NthType;
338 195
339 template <typename T, typename... Ts> 196 template <typename T, typename... Ts>
340 struct TupleElement<0, Tuple<T, Ts...>> { 197 struct NthType<0, T, Ts...> {
341 using Type = T; 198 using Type = T;
342 }; 199 };
343 200
344 template <size_t N, typename T, typename... Ts> 201 template <size_t N, typename T, typename... Ts>
345 struct TupleElement<N, Tuple<T, Ts...>> { 202 struct NthType<N, T, Ts...> : public NthType<N - 1, Ts...> {};
346 using Type = typename TupleElement<N - 1, Tuple<Ts...>>::Type;
347 };
348 203
349 // Tuple getters -------------------------------------------------------------- 204 // Tuple getters --------------------------------------------------------------
350 205
351 template <size_t, typename T>
352 struct TupleGetter;
353
354 template <typename... Ts>
355 struct TupleGetter<0, Tuple<Ts...>> {
356 using Elem = typename TupleElement<0, Tuple<Ts...>>::Type;
357 static Elem& Get(Tuple<Ts...>& t) { return t.a; }
358 static const Elem& Get(const Tuple<Ts...>& t) { return t.a; }
359 };
360
361 template <typename... Ts>
362 struct TupleGetter<1, Tuple<Ts...>> {
363 using Elem = typename TupleElement<1, Tuple<Ts...>>::Type;
364 static Elem& Get(Tuple<Ts...>& t) { return t.b; }
365 static const Elem& Get(const Tuple<Ts...>& t) { return t.b; }
366 };
367
368 template <typename... Ts>
369 struct TupleGetter<2, Tuple<Ts...>> {
370 using Elem = typename TupleElement<2, Tuple<Ts...>>::Type;
371 static Elem& Get(Tuple<Ts...>& t) { return t.c; }
372 static const Elem& Get(const Tuple<Ts...>& t) { return t.c; }
373 };
374
375 template <typename... Ts>
376 struct TupleGetter<3, Tuple<Ts...>> {
377 using Elem = typename TupleElement<3, Tuple<Ts...>>::Type;
378 static Elem& Get(Tuple<Ts...>& t) { return t.d; }
379 static const Elem& Get(const Tuple<Ts...>& t) { return t.d; }
380 };
381
382 template <typename... Ts>
383 struct TupleGetter<4, Tuple<Ts...>> {
384 using Elem = typename TupleElement<4, Tuple<Ts...>>::Type;
385 static Elem& Get(Tuple<Ts...>& t) { return t.e; }
386 static const Elem& Get(const Tuple<Ts...>& t) { return t.e; }
387 };
388
389 template <typename... Ts>
390 struct TupleGetter<5, Tuple<Ts...>> {
391 using Elem = typename TupleElement<5, Tuple<Ts...>>::Type;
392 static Elem& Get(Tuple<Ts...>& t) { return t.f; }
393 static const Elem& Get(const Tuple<Ts...>& t) { return t.f; }
394 };
395
396 template <typename... Ts>
397 struct TupleGetter<6, Tuple<Ts...>> {
398 using Elem = typename TupleElement<6, Tuple<Ts...>>::Type;
399 static Elem& Get(Tuple<Ts...>& t) { return t.g; }
400 static const Elem& Get(const Tuple<Ts...>& t) { return t.g; }
401 };
402
403 template <typename... Ts>
404 struct TupleGetter<7, Tuple<Ts...>> {
405 using Elem = typename TupleElement<7, Tuple<Ts...>>::Type;
406 static Elem& Get(Tuple<Ts...>& t) { return t.h; }
407 static const Elem& Get(const Tuple<Ts...>& t) { return t.h; }
408 };
409
410 template <size_t I, typename... Ts> 206 template <size_t I, typename... Ts>
411 typename TupleElement<I, Tuple<Ts...>>::Type& get(Tuple<Ts...>& tuple) { 207 typename NthType<I, Ts...>::Type& get(Tuple<Ts...>& tuple) {
tzik 2014/12/10 06:43:27 If it works, how about matching the tuple against
mdempsky 2014/12/10 07:46:03 Nice, seems to work, and means NthType isn't neede
412 return TupleGetter<I, Tuple<Ts...>>::Get(tuple); 208 using Elem = typename NthType<I, Ts...>::Type;
209 return static_cast<TupleLeaf<I, Elem>&>(tuple).get();
413 } 210 }
414 211
415 template <size_t I, typename... Ts> 212 template <size_t I, typename... Ts>
416 const typename TupleElement<I, Tuple<Ts...>>::Type& get( 213 const typename NthType<I, Ts...>::Type& get(const Tuple<Ts...>& tuple) {
417 const Tuple<Ts...>& tuple) { 214 using Elem = typename NthType<I, Ts...>::Type;
418 return TupleGetter<I, Tuple<Ts...>>::Get(tuple); 215 return static_cast<const TupleLeaf<I, Elem>&>(tuple).get();
419 } 216 }
420 217
421 // Tuple types ---------------------------------------------------------------- 218 // Tuple types ----------------------------------------------------------------
422 // 219 //
423 // Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the 220 // Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the
424 // definitions of class types the tuple takes as parameters. 221 // definitions of class types the tuple takes as parameters.
425 222
426 template <typename T> 223 template <typename T>
427 struct TupleTypes; 224 struct TupleTypes;
428 225
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 inline void DispatchToMethod(ObjT* obj, 343 inline void DispatchToMethod(ObjT* obj,
547 Method method, 344 Method method,
548 const Tuple<InTs...>& in, 345 const Tuple<InTs...>& in,
549 Tuple<OutTs...>* out) { 346 Tuple<OutTs...>* out) {
550 DispatchToMethodImpl(obj, method, in, out, 347 DispatchToMethodImpl(obj, method, in, out,
551 MakeIndexSequence<sizeof...(InTs)>(), 348 MakeIndexSequence<sizeof...(InTs)>(),
552 MakeIndexSequence<sizeof...(OutTs)>()); 349 MakeIndexSequence<sizeof...(OutTs)>());
553 } 350 }
554 351
555 #endif // BASE_TUPLE_H__ 352 #endif // BASE_TUPLE_H__
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698