xref: /aosp_15_r20/external/libchrome/base/tuple.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker // Use std::tuple as tuple type. This file contains helper functions for
6*635a8641SAndroid Build Coastguard Worker // working with std::tuples.
7*635a8641SAndroid Build Coastguard Worker // The functions DispatchToMethod and DispatchToFunction take a function pointer
8*635a8641SAndroid Build Coastguard Worker // or instance and method pointer, and unpack a tuple into arguments to the
9*635a8641SAndroid Build Coastguard Worker // call.
10*635a8641SAndroid Build Coastguard Worker //
11*635a8641SAndroid Build Coastguard Worker // Example usage:
12*635a8641SAndroid Build Coastguard Worker //   // These two methods of creating a Tuple are identical.
13*635a8641SAndroid Build Coastguard Worker //   std::tuple<int, const char*> tuple_a(1, "wee");
14*635a8641SAndroid Build Coastguard Worker //   std::tuple<int, const char*> tuple_b = std::make_tuple(1, "wee");
15*635a8641SAndroid Build Coastguard Worker //
16*635a8641SAndroid Build Coastguard Worker //   void SomeFunc(int a, const char* b) { }
17*635a8641SAndroid Build Coastguard Worker //   DispatchToFunction(&SomeFunc, tuple_a);  // SomeFunc(1, "wee")
18*635a8641SAndroid Build Coastguard Worker //   DispatchToFunction(
19*635a8641SAndroid Build Coastguard Worker //       &SomeFunc, std::make_tuple(10, "foo"));    // SomeFunc(10, "foo")
20*635a8641SAndroid Build Coastguard Worker //
21*635a8641SAndroid Build Coastguard Worker //   struct { void SomeMeth(int a, int b, int c) { } } foo;
22*635a8641SAndroid Build Coastguard Worker //   DispatchToMethod(&foo, &Foo::SomeMeth, std::make_tuple(1, 2, 3));
23*635a8641SAndroid Build Coastguard Worker //   // foo->SomeMeth(1, 2, 3);
24*635a8641SAndroid Build Coastguard Worker 
25*635a8641SAndroid Build Coastguard Worker #ifndef BASE_TUPLE_H_
26*635a8641SAndroid Build Coastguard Worker #define BASE_TUPLE_H_
27*635a8641SAndroid Build Coastguard Worker 
28*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
29*635a8641SAndroid Build Coastguard Worker #include <tuple>
30*635a8641SAndroid Build Coastguard Worker #include <utility>
31*635a8641SAndroid Build Coastguard Worker 
32*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
33*635a8641SAndroid Build Coastguard Worker 
34*635a8641SAndroid Build Coastguard Worker namespace base {
35*635a8641SAndroid Build Coastguard Worker 
36*635a8641SAndroid Build Coastguard Worker // Dispatchers ----------------------------------------------------------------
37*635a8641SAndroid Build Coastguard Worker //
38*635a8641SAndroid Build Coastguard Worker // Helper functions that call the given method on an object, with the unpacked
39*635a8641SAndroid Build Coastguard Worker // tuple arguments.  Notice that they all have the same number of arguments,
40*635a8641SAndroid Build Coastguard Worker // so you need only write:
41*635a8641SAndroid Build Coastguard Worker //   DispatchToMethod(object, &Object::method, args);
42*635a8641SAndroid Build Coastguard Worker // This is very useful for templated dispatchers, since they don't need to know
43*635a8641SAndroid Build Coastguard Worker // what type |args| is.
44*635a8641SAndroid Build Coastguard Worker 
45*635a8641SAndroid Build Coastguard Worker // Non-Static Dispatchers with no out params.
46*635a8641SAndroid Build Coastguard Worker 
47*635a8641SAndroid Build Coastguard Worker template <typename ObjT, typename Method, typename Tuple, size_t... Ns>
DispatchToMethodImpl(const ObjT & obj,Method method,Tuple && args,std::index_sequence<Ns...>)48*635a8641SAndroid Build Coastguard Worker inline void DispatchToMethodImpl(const ObjT& obj,
49*635a8641SAndroid Build Coastguard Worker                                  Method method,
50*635a8641SAndroid Build Coastguard Worker                                  Tuple&& args,
51*635a8641SAndroid Build Coastguard Worker                                  std::index_sequence<Ns...>) {
52*635a8641SAndroid Build Coastguard Worker   (obj->*method)(std::get<Ns>(std::forward<Tuple>(args))...);
53*635a8641SAndroid Build Coastguard Worker }
54*635a8641SAndroid Build Coastguard Worker 
55*635a8641SAndroid Build Coastguard Worker template <typename ObjT, typename Method, typename Tuple>
DispatchToMethod(const ObjT & obj,Method method,Tuple && args)56*635a8641SAndroid Build Coastguard Worker inline void DispatchToMethod(const ObjT& obj,
57*635a8641SAndroid Build Coastguard Worker                              Method method,
58*635a8641SAndroid Build Coastguard Worker                              Tuple&& args) {
59*635a8641SAndroid Build Coastguard Worker   constexpr size_t size = std::tuple_size<std::decay_t<Tuple>>::value;
60*635a8641SAndroid Build Coastguard Worker   DispatchToMethodImpl(obj, method, std::forward<Tuple>(args),
61*635a8641SAndroid Build Coastguard Worker                        std::make_index_sequence<size>());
62*635a8641SAndroid Build Coastguard Worker }
63*635a8641SAndroid Build Coastguard Worker 
64*635a8641SAndroid Build Coastguard Worker // Static Dispatchers with no out params.
65*635a8641SAndroid Build Coastguard Worker 
66*635a8641SAndroid Build Coastguard Worker template <typename Function, typename Tuple, size_t... Ns>
DispatchToFunctionImpl(Function function,Tuple && args,std::index_sequence<Ns...>)67*635a8641SAndroid Build Coastguard Worker inline void DispatchToFunctionImpl(Function function,
68*635a8641SAndroid Build Coastguard Worker                                    Tuple&& args,
69*635a8641SAndroid Build Coastguard Worker                                    std::index_sequence<Ns...>) {
70*635a8641SAndroid Build Coastguard Worker   (*function)(std::get<Ns>(std::forward<Tuple>(args))...);
71*635a8641SAndroid Build Coastguard Worker }
72*635a8641SAndroid Build Coastguard Worker 
73*635a8641SAndroid Build Coastguard Worker template <typename Function, typename Tuple>
DispatchToFunction(Function function,Tuple && args)74*635a8641SAndroid Build Coastguard Worker inline void DispatchToFunction(Function function, Tuple&& args) {
75*635a8641SAndroid Build Coastguard Worker   constexpr size_t size = std::tuple_size<std::decay_t<Tuple>>::value;
76*635a8641SAndroid Build Coastguard Worker   DispatchToFunctionImpl(function, std::forward<Tuple>(args),
77*635a8641SAndroid Build Coastguard Worker                          std::make_index_sequence<size>());
78*635a8641SAndroid Build Coastguard Worker }
79*635a8641SAndroid Build Coastguard Worker 
80*635a8641SAndroid Build Coastguard Worker // Dispatchers with out parameters.
81*635a8641SAndroid Build Coastguard Worker 
82*635a8641SAndroid Build Coastguard Worker template <typename ObjT,
83*635a8641SAndroid Build Coastguard Worker           typename Method,
84*635a8641SAndroid Build Coastguard Worker           typename InTuple,
85*635a8641SAndroid Build Coastguard Worker           typename OutTuple,
86*635a8641SAndroid Build Coastguard Worker           size_t... InNs,
87*635a8641SAndroid Build Coastguard Worker           size_t... OutNs>
DispatchToMethodImpl(const ObjT & obj,Method method,InTuple && in,OutTuple * out,std::index_sequence<InNs...>,std::index_sequence<OutNs...>)88*635a8641SAndroid Build Coastguard Worker inline void DispatchToMethodImpl(const ObjT& obj,
89*635a8641SAndroid Build Coastguard Worker                                  Method method,
90*635a8641SAndroid Build Coastguard Worker                                  InTuple&& in,
91*635a8641SAndroid Build Coastguard Worker                                  OutTuple* out,
92*635a8641SAndroid Build Coastguard Worker                                  std::index_sequence<InNs...>,
93*635a8641SAndroid Build Coastguard Worker                                  std::index_sequence<OutNs...>) {
94*635a8641SAndroid Build Coastguard Worker   (obj->*method)(std::get<InNs>(std::forward<InTuple>(in))...,
95*635a8641SAndroid Build Coastguard Worker                  &std::get<OutNs>(*out)...);
96*635a8641SAndroid Build Coastguard Worker }
97*635a8641SAndroid Build Coastguard Worker 
98*635a8641SAndroid Build Coastguard Worker template <typename ObjT, typename Method, typename InTuple, typename OutTuple>
DispatchToMethod(const ObjT & obj,Method method,InTuple && in,OutTuple * out)99*635a8641SAndroid Build Coastguard Worker inline void DispatchToMethod(const ObjT& obj,
100*635a8641SAndroid Build Coastguard Worker                              Method method,
101*635a8641SAndroid Build Coastguard Worker                              InTuple&& in,
102*635a8641SAndroid Build Coastguard Worker                              OutTuple* out) {
103*635a8641SAndroid Build Coastguard Worker   constexpr size_t in_size = std::tuple_size<std::decay_t<InTuple>>::value;
104*635a8641SAndroid Build Coastguard Worker   constexpr size_t out_size = std::tuple_size<OutTuple>::value;
105*635a8641SAndroid Build Coastguard Worker   DispatchToMethodImpl(obj, method, std::forward<InTuple>(in), out,
106*635a8641SAndroid Build Coastguard Worker                        std::make_index_sequence<in_size>(),
107*635a8641SAndroid Build Coastguard Worker                        std::make_index_sequence<out_size>());
108*635a8641SAndroid Build Coastguard Worker }
109*635a8641SAndroid Build Coastguard Worker 
110*635a8641SAndroid Build Coastguard Worker }  // namespace base
111*635a8641SAndroid Build Coastguard Worker 
112*635a8641SAndroid Build Coastguard Worker #endif  // BASE_TUPLE_H_
113