blob: 16f51241392946b3c264687b77ef54998d86ac2c [file] [log] [blame]
oshima@chromium.orgcc654912011-09-28 09:33:59 +09001// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botf003cfe2008-08-24 09:55:55 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit3f4a7322008-07-27 06:49:38 +09004
deanm@google.com96aac0a2008-08-25 22:42:07 +09005// A Tuple is a generic templatized container, similar in concept to std::pair.
ojan@google.com38355092008-10-10 06:58:05 +09006// There are classes Tuple0 to Tuple6, cooresponding to the number of elements
7// it contains. The convenient MakeTuple() function takes 0 to 6 arguments,
deanm@google.com96aac0a2008-08-25 22:42:07 +09008// and will construct and return the appropriate Tuple object. The functions
9// DispatchToMethod and DispatchToFunction take a function pointer or instance
10// and method pointer, and unpack a tuple into arguments to the call.
11//
12// 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.
14//
15// Example usage:
16// // These two methods of creating a Tuple are identical.
17// Tuple2<int, const char*> tuple_a(1, "wee");
18// Tuple2<int, const char*> tuple_b = MakeTuple(1, "wee");
19//
20// void SomeFunc(int a, const char* b) { }
21// DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee")
22// DispatchToFunction(
23// &SomeFunc, MakeTuple(10, "foo")); // SomeFunc(10, "foo")
24//
25// struct { void SomeMeth(int a, int b, int c) { } } foo;
26// DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3));
27// // foo->SomeMeth(1, 2, 3);
28
initial.commit3f4a7322008-07-27 06:49:38 +090029#ifndef BASE_TUPLE_H__
30#define BASE_TUPLE_H__
31
rsleevi@chromium.org274c7222013-06-27 21:48:02 +090032#include "base/bind_helpers.h"
33
mdempsky0c1d6ed2014-12-10 12:10:59 +090034// Index sequences
35//
36// Minimal clone of the similarly-named C++14 functionality.
37
38template <size_t...>
39struct IndexSequence {};
40
41template <size_t... Ns>
42struct MakeIndexSequenceImpl;
43
44template <size_t... Ns>
45struct MakeIndexSequenceImpl<0, Ns...> {
46 using Type = IndexSequence<Ns...>;
47};
48
49template <size_t N, size_t... Ns>
50struct MakeIndexSequenceImpl<N, Ns...> {
51 using Type = typename MakeIndexSequenceImpl<N - 1, N - 1, Ns...>::Type;
52};
53
54template <size_t N>
55using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::Type;
56
initial.commit3f4a7322008-07-27 06:49:38 +090057// Traits ----------------------------------------------------------------------
58//
59// A simple traits class for tuple arguments.
60//
61// 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).
63// ParamType: what type to pass to functions (refs should not be constified).
64
65template <class P>
66struct TupleTraits {
67 typedef P ValueType;
68 typedef P& RefType;
69 typedef const P& ParamType;
70};
71
72template <class P>
73struct TupleTraits<P&> {
74 typedef P ValueType;
75 typedef P& RefType;
76 typedef P& ParamType;
77};
78
79// Tuple -----------------------------------------------------------------------
80//
81// 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
83// function objects that need to take an arbitrary number of parameters; see
84// RunnableMethod and IPC::MessageWithTuple.
85//
deanm@google.comff4b7292008-08-21 19:58:08 +090086// Tuple0 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
88// Dispatchers below).
initial.commit3f4a7322008-07-27 06:49:38 +090089// Tuple1<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
91// output (a "tier"). See MakeRefTuple and its usages.
92
mdempsky0c1d6ed2014-12-10 12:10:59 +090093template <typename... Ts>
94struct Tuple;
initial.commit3f4a7322008-07-27 06:49:38 +090095
mdempsky0c1d6ed2014-12-10 12:10:59 +090096template <>
97struct Tuple<> {};
98
99template <typename A>
100struct Tuple<A> {
initial.commit3f4a7322008-07-27 06:49:38 +0900101 public:
102 typedef A TypeA;
initial.commit3f4a7322008-07-27 06:49:38 +0900103
mdempsky0c1d6ed2014-12-10 12:10:59 +0900104 Tuple() {}
105 explicit Tuple(typename TupleTraits<A>::ParamType a) : a(a) {}
initial.commit3f4a7322008-07-27 06:49:38 +0900106
107 A a;
108};
109
mdempsky0c1d6ed2014-12-10 12:10:59 +0900110template <typename A, typename B>
111struct Tuple<A, B> {
initial.commit3f4a7322008-07-27 06:49:38 +0900112 public:
113 typedef A TypeA;
114 typedef B TypeB;
initial.commit3f4a7322008-07-27 06:49:38 +0900115
mdempsky0c1d6ed2014-12-10 12:10:59 +0900116 Tuple() {}
117 Tuple(typename TupleTraits<A>::ParamType a,
118 typename TupleTraits<B>::ParamType b)
119 : a(a), b(b) {}
initial.commit3f4a7322008-07-27 06:49:38 +0900120
121 A a;
122 B b;
123};
124
mdempsky0c1d6ed2014-12-10 12:10:59 +0900125template <typename A, typename B, typename C>
126struct Tuple<A, B, C> {
initial.commit3f4a7322008-07-27 06:49:38 +0900127 public:
128 typedef A TypeA;
129 typedef B TypeB;
130 typedef C TypeC;
initial.commit3f4a7322008-07-27 06:49:38 +0900131
mdempsky0c1d6ed2014-12-10 12:10:59 +0900132 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) {}
initial.commit3f4a7322008-07-27 06:49:38 +0900137
138 A a;
139 B b;
140 C c;
141};
142
mdempsky0c1d6ed2014-12-10 12:10:59 +0900143template <typename A, typename B, typename C, typename D>
144struct Tuple<A, B, C, D> {
initial.commit3f4a7322008-07-27 06:49:38 +0900145 public:
146 typedef A TypeA;
147 typedef B TypeB;
148 typedef C TypeC;
149 typedef D TypeD;
initial.commit3f4a7322008-07-27 06:49:38 +0900150
mdempsky0c1d6ed2014-12-10 12:10:59 +0900151 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) {}
initial.commit3f4a7322008-07-27 06:49:38 +0900157
158 A a;
159 B b;
160 C c;
161 D d;
162};
163
mdempsky0c1d6ed2014-12-10 12:10:59 +0900164template <typename A, typename B, typename C, typename D, typename E>
165struct Tuple<A, B, C, D, E> {
erg@google.combf6ce9f2010-01-27 08:08:02 +0900166 public:
initial.commit3f4a7322008-07-27 06:49:38 +0900167 typedef A TypeA;
168 typedef B TypeB;
169 typedef C TypeC;
170 typedef D TypeD;
171 typedef E TypeE;
initial.commit3f4a7322008-07-27 06:49:38 +0900172
mdempsky0c1d6ed2014-12-10 12:10:59 +0900173 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) {}
initial.commit3f4a7322008-07-27 06:49:38 +0900180
181 A a;
182 B b;
183 C c;
184 D d;
185 E e;
186};
187
mdempsky0c1d6ed2014-12-10 12:10:59 +0900188template <typename A,
189 typename B,
190 typename C,
191 typename D,
192 typename E,
193 typename F>
194struct Tuple<A, B, C, D, E, F> {
erg@google.combf6ce9f2010-01-27 08:08:02 +0900195 public:
ojan@google.com38355092008-10-10 06:58:05 +0900196 typedef A TypeA;
197 typedef B TypeB;
198 typedef C TypeC;
199 typedef D TypeD;
200 typedef E TypeE;
201 typedef F TypeF;
ojan@google.com38355092008-10-10 06:58:05 +0900202
mdempsky0c1d6ed2014-12-10 12:10:59 +0900203 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) {}
ojan@google.com38355092008-10-10 06:58:05 +0900211
212 A a;
213 B b;
214 C c;
215 D d;
216 E e;
217 F f;
218};
219
mdempsky0c1d6ed2014-12-10 12:10:59 +0900220template <typename A,
221 typename B,
222 typename C,
223 typename D,
224 typename E,
225 typename F,
226 typename G>
227struct Tuple<A, B, C, D, E, F, G> {
erg@google.combf6ce9f2010-01-27 08:08:02 +0900228 public:
sky@google.com67c35752008-11-13 07:10:20 +0900229 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;
sky@google.com67c35752008-11-13 07:10:20 +0900236
mdempsky0c1d6ed2014-12-10 12:10:59 +0900237 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) {}
sky@google.com67c35752008-11-13 07:10:20 +0900246
247 A a;
248 B b;
249 C c;
250 D d;
251 E e;
252 F f;
253 G g;
254};
255
mdempsky0c1d6ed2014-12-10 12:10:59 +0900256template <typename A,
257 typename B,
258 typename C,
259 typename D,
260 typename E,
261 typename F,
262 typename G,
263 typename H>
264struct Tuple<A, B, C, D, E, F, G, H> {
phajdan.jr@chromium.org5a468fc2010-07-21 01:56:26 +0900265 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;
phajdan.jr@chromium.org5a468fc2010-07-21 01:56:26 +0900274
mdempsky0c1d6ed2014-12-10 12:10:59 +0900275 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) {}
phajdan.jr@chromium.org5a468fc2010-07-21 01:56:26 +0900285
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
mdempsky0c1d6ed2014-12-10 12:10:59 +0900296// Deprecated compat aliases
297
298using Tuple0 = Tuple<>;
299template <typename A>
300using Tuple1 = Tuple<A>;
301template <typename A, typename B>
302using Tuple2 = Tuple<A, B>;
303template <typename A, typename B, typename C>
304using Tuple3 = Tuple<A, B, C>;
305template <typename A, typename B, typename C, typename D>
306using Tuple4 = Tuple<A, B, C, D>;
307template <typename A, typename B, typename C, typename D, typename E>
308using Tuple5 = Tuple<A, B, C, D, E>;
309template <typename A,
310 typename B,
311 typename C,
312 typename D,
313 typename E,
314 typename F>
315using Tuple6 = Tuple<A, B, C, D, E, F>;
316template <typename A,
317 typename B,
318 typename C,
319 typename D,
320 typename E,
321 typename F,
322 typename G>
323using Tuple7 = Tuple<A, B, C, D, E, F, G>;
324template <typename A,
325 typename B,
326 typename C,
327 typename D,
328 typename E,
329 typename F,
330 typename G,
331 typename H>
332using Tuple8 = Tuple<A, B, C, D, E, F, G, H>;
333
334// Tuple element --------------------------------------------------------------
335
336template <size_t N, typename T>
337struct TupleElement;
338
339template <typename T, typename... Ts>
340struct TupleElement<0, Tuple<T, Ts...>> {
341 using Type = T;
342};
343
344template <size_t N, typename T, typename... Ts>
345struct TupleElement<N, Tuple<T, Ts...>> {
346 using Type = typename TupleElement<N - 1, Tuple<Ts...>>::Type;
347};
348
349// Tuple getters --------------------------------------------------------------
350
351template <size_t, typename T>
352struct TupleGetter;
353
354template <typename... Ts>
355struct 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
361template <typename... Ts>
362struct 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
368template <typename... Ts>
369struct 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
375template <typename... Ts>
376struct 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
382template <typename... Ts>
383struct 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
389template <typename... Ts>
390struct 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
396template <typename... Ts>
397struct 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
403template <typename... Ts>
404struct 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
410template <size_t I, typename... Ts>
411typename TupleElement<I, Tuple<Ts...>>::Type& get(Tuple<Ts...>& tuple) {
412 return TupleGetter<I, Tuple<Ts...>>::Get(tuple);
413}
414
415template <size_t I, typename... Ts>
416const typename TupleElement<I, Tuple<Ts...>>::Type& get(
417 const Tuple<Ts...>& tuple) {
418 return TupleGetter<I, Tuple<Ts...>>::Get(tuple);
419}
420
erg@google.come6ffcb52010-08-18 03:38:24 +0900421// Tuple types ----------------------------------------------------------------
422//
423// Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the
424// definitions of class types the tuple takes as parameters.
425
mdempsky0c1d6ed2014-12-10 12:10:59 +0900426template <typename T>
427struct TupleTypes;
erg@google.come6ffcb52010-08-18 03:38:24 +0900428
mdempsky0c1d6ed2014-12-10 12:10:59 +0900429template <typename... Ts>
430struct TupleTypes<Tuple<Ts...>> {
431 using ValueTuple = Tuple<typename TupleTraits<Ts>::ValueType...>;
432 using RefTuple = Tuple<typename TupleTraits<Ts>::RefType...>;
433 using ParamTuple = Tuple<typename TupleTraits<Ts>::ParamType...>;
erg@google.come6ffcb52010-08-18 03:38:24 +0900434};
435
initial.commit3f4a7322008-07-27 06:49:38 +0900436// Tuple creators -------------------------------------------------------------
437//
438// Helper functions for constructing tuples while inferring the template
439// argument types.
440
mdempsky0c1d6ed2014-12-10 12:10:59 +0900441template <typename... Ts>
442inline Tuple<Ts...> MakeTuple(const Ts&... arg) {
443 return Tuple<Ts...>(arg...);
phajdan.jr@chromium.org5a468fc2010-07-21 01:56:26 +0900444}
445
initial.commit3f4a7322008-07-27 06:49:38 +0900446// The following set of helpers make what Boost refers to as "Tiers" - a tuple
447// of references.
448
mdempsky0c1d6ed2014-12-10 12:10:59 +0900449template <typename... Ts>
450inline Tuple<Ts&...> MakeRefTuple(Ts&... arg) {
451 return Tuple<Ts&...>(arg...);
phajdan.jr@chromium.org5a468fc2010-07-21 01:56:26 +0900452}
453
initial.commit3f4a7322008-07-27 06:49:38 +0900454// Dispatchers ----------------------------------------------------------------
455//
456// Helper functions that call the given method on an object, with the unpacked
457// tuple arguments. Notice that they all have the same number of arguments,
458// so you need only write:
459// DispatchToMethod(object, &Object::method, args);
460// This is very useful for templated dispatchers, since they don't need to know
461// what type |args| is.
462
463// Non-Static Dispatchers with no out params.
464
mdempsky0c1d6ed2014-12-10 12:10:59 +0900465template <typename ObjT, typename Method, typename A>
initial.commit3f4a7322008-07-27 06:49:38 +0900466inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) {
rsleevi@chromium.org274c7222013-06-27 21:48:02 +0900467 (obj->*method)(base::internal::UnwrapTraits<A>::Unwrap(arg));
initial.commit3f4a7322008-07-27 06:49:38 +0900468}
469
mdempsky0c1d6ed2014-12-10 12:10:59 +0900470template <typename ObjT, typename Method, typename... Ts, size_t... Ns>
471inline void DispatchToMethodImpl(ObjT* obj,
472 Method method,
473 const Tuple<Ts...>& arg,
474 IndexSequence<Ns...>) {
475 (obj->*method)(base::internal::UnwrapTraits<Ts>::Unwrap(get<Ns>(arg))...);
initial.commit3f4a7322008-07-27 06:49:38 +0900476}
477
mdempsky0c1d6ed2014-12-10 12:10:59 +0900478template <typename ObjT, typename Method, typename... Ts>
maruel@chromium.org8fe7adc2009-03-04 00:01:12 +0900479inline void DispatchToMethod(ObjT* obj,
480 Method method,
mdempsky0c1d6ed2014-12-10 12:10:59 +0900481 const Tuple<Ts...>& arg) {
482 DispatchToMethodImpl(obj, method, arg, MakeIndexSequence<sizeof...(Ts)>());
noelutz@google.comdd96ed82011-02-18 04:47:13 +0900483}
484
initial.commit3f4a7322008-07-27 06:49:38 +0900485// Static Dispatchers with no out params.
486
mdempsky0c1d6ed2014-12-10 12:10:59 +0900487template <typename Function, typename A>
488inline void DispatchToMethod(Function function, const A& arg) {
489 (*function)(base::internal::UnwrapTraits<A>::Unwrap(arg));
initial.commit3f4a7322008-07-27 06:49:38 +0900490}
491
mdempsky0c1d6ed2014-12-10 12:10:59 +0900492template <typename Function, typename... Ts, size_t... Ns>
493inline void DispatchToFunctionImpl(Function function,
494 const Tuple<Ts...>& arg,
495 IndexSequence<Ns...>) {
496 (*function)(base::internal::UnwrapTraits<Ts>::Unwrap(get<Ns>(arg))...);
initial.commit3f4a7322008-07-27 06:49:38 +0900497}
498
mdempsky0c1d6ed2014-12-10 12:10:59 +0900499template <typename Function, typename... Ts>
500inline void DispatchToFunction(Function function, const Tuple<Ts...>& arg) {
501 DispatchToFunctionImpl(function, arg, MakeIndexSequence<sizeof...(Ts)>());
initial.commit3f4a7322008-07-27 06:49:38 +0900502}
503
mdempsky0c1d6ed2014-12-10 12:10:59 +0900504// Dispatchers with out parameters.
505
506template <typename ObjT,
507 typename Method,
508 typename In,
509 typename... OutTs,
510 size_t... OutNs>
511inline void DispatchToMethodImpl(ObjT* obj,
512 Method method,
513 const In& in,
514 Tuple<OutTs...>* out,
515 IndexSequence<OutNs...>) {
516 (obj->*method)(base::internal::UnwrapTraits<In>::Unwrap(in),
517 &get<OutNs>(*out)...);
initial.commit3f4a7322008-07-27 06:49:38 +0900518}
519
mdempsky0c1d6ed2014-12-10 12:10:59 +0900520template <typename ObjT, typename Method, typename In, typename... OutTs>
maruel@chromium.org8fe7adc2009-03-04 00:01:12 +0900521inline void DispatchToMethod(ObjT* obj,
522 Method method,
mdempsky0c1d6ed2014-12-10 12:10:59 +0900523 const In& in,
524 Tuple<OutTs...>* out) {
525 DispatchToMethodImpl(obj, method, in, out,
526 MakeIndexSequence<sizeof...(OutTs)>());
initial.commit3f4a7322008-07-27 06:49:38 +0900527}
528
mdempsky0c1d6ed2014-12-10 12:10:59 +0900529template <typename ObjT,
530 typename Method,
531 typename... InTs,
532 typename... OutTs,
533 size_t... InNs,
534 size_t... OutNs>
535inline void DispatchToMethodImpl(ObjT* obj,
536 Method method,
537 const Tuple<InTs...>& in,
538 Tuple<OutTs...>* out,
539 IndexSequence<InNs...>,
540 IndexSequence<OutNs...>) {
541 (obj->*method)(base::internal::UnwrapTraits<InTs>::Unwrap(get<InNs>(in))...,
542 &get<OutNs>(*out)...);
initial.commit3f4a7322008-07-27 06:49:38 +0900543}
544
mdempsky0c1d6ed2014-12-10 12:10:59 +0900545template <typename ObjT, typename Method, typename... InTs, typename... OutTs>
maruel@chromium.org8fe7adc2009-03-04 00:01:12 +0900546inline void DispatchToMethod(ObjT* obj,
547 Method method,
mdempsky0c1d6ed2014-12-10 12:10:59 +0900548 const Tuple<InTs...>& in,
549 Tuple<OutTs...>* out) {
550 DispatchToMethodImpl(obj, method, in, out,
551 MakeIndexSequence<sizeof...(InTs)>(),
552 MakeIndexSequence<sizeof...(OutTs)>());
ojan@google.com38355092008-10-10 06:58:05 +0900553}
554
initial.commit3f4a7322008-07-27 06:49:38 +0900555#endif // BASE_TUPLE_H__