1 // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
2 // Google Inc. All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the name Chromium Embedded
15 // Framework nor the names of its contributors may be used to endorse
16 // or promote products derived from this software without specific prior
17 // written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Use std::tuple as tuple type. This file contains helper functions for
32 // working with std::tuples.
33 // The functions DispatchToMethod and DispatchToFunction take a function pointer
34 // or instance and method pointer, and unpack a tuple into arguments to the
35 // call.
36 //
37 // Example usage:
38 // // These two methods of creating a Tuple are identical.
39 // std::tuple<int, const char*> tuple_a(1, "wee");
40 // std::tuple<int, const char*> tuple_b = std::make_tuple(1, "wee");
41 //
42 // void SomeFunc(int a, const char* b) { }
43 // DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee")
44 // DispatchToFunction(
45 // &SomeFunc, std::make_tuple(10, "foo")); // SomeFunc(10, "foo")
46 //
47 // struct { void SomeMeth(int a, int b, int c) { } } foo;
48 // DispatchToMethod(&foo, &Foo::SomeMeth, std::make_tuple(1, 2, 3));
49 // // foo->SomeMeth(1, 2, 3);
50
51 #ifndef CEF_INCLUDE_BASE_CEF_TUPLE_H_
52 #define CEF_INCLUDE_BASE_CEF_TUPLE_H_
53 #pragma once
54
55 #if defined(USING_CHROMIUM_INCLUDES)
56 // When building CEF include the Chromium header directly.
57 #include "base/tuple.h"
58 #else // !USING_CHROMIUM_INCLUDES
59 // The following is substantially similar to the Chromium implementation.
60 // If the Chromium implementation diverges the below implementation should be
61 // updated to match.
62
63 #include <stddef.h>
64 #include <tuple>
65 #include <utility>
66
67 #include "include/base/cef_build.h"
68
69 namespace base {
70
71 // Dispatchers ----------------------------------------------------------------
72 //
73 // Helper functions that call the given method on an object, with the unpacked
74 // tuple arguments. Notice that they all have the same number of arguments,
75 // so you need only write:
76 // DispatchToMethod(object, &Object::method, args);
77 // This is very useful for templated dispatchers, since they don't need to know
78 // what type |args| is.
79
80 // Non-Static Dispatchers with no out params.
81
82 template <typename ObjT, typename Method, typename Tuple, size_t... Ns>
DispatchToMethodImpl(const ObjT & obj,Method method,Tuple && args,std::index_sequence<Ns...>)83 inline void DispatchToMethodImpl(const ObjT& obj,
84 Method method,
85 Tuple&& args,
86 std::index_sequence<Ns...>) {
87 (obj->*method)(std::get<Ns>(std::forward<Tuple>(args))...);
88 }
89
90 template <typename ObjT, typename Method, typename Tuple>
DispatchToMethod(const ObjT & obj,Method method,Tuple && args)91 inline void DispatchToMethod(const ObjT& obj,
92 Method method,
93 Tuple&& args) {
94 constexpr size_t size = std::tuple_size<std::decay_t<Tuple>>::value;
95 DispatchToMethodImpl(obj, method, std::forward<Tuple>(args),
96 std::make_index_sequence<size>());
97 }
98
99 // Static Dispatchers with no out params.
100
101 template <typename Function, typename Tuple, size_t... Ns>
DispatchToFunctionImpl(Function function,Tuple && args,std::index_sequence<Ns...>)102 inline void DispatchToFunctionImpl(Function function,
103 Tuple&& args,
104 std::index_sequence<Ns...>) {
105 (*function)(std::get<Ns>(std::forward<Tuple>(args))...);
106 }
107
108 template <typename Function, typename Tuple>
DispatchToFunction(Function function,Tuple && args)109 inline void DispatchToFunction(Function function, Tuple&& args) {
110 constexpr size_t size = std::tuple_size<std::decay_t<Tuple>>::value;
111 DispatchToFunctionImpl(function, std::forward<Tuple>(args),
112 std::make_index_sequence<size>());
113 }
114
115 // Dispatchers with out parameters.
116
117 template <typename ObjT,
118 typename Method,
119 typename InTuple,
120 typename OutTuple,
121 size_t... InNs,
122 size_t... OutNs>
DispatchToMethodImpl(const ObjT & obj,Method method,InTuple && in,OutTuple * out,std::index_sequence<InNs...>,std::index_sequence<OutNs...>)123 inline void DispatchToMethodImpl(const ObjT& obj,
124 Method method,
125 InTuple&& in,
126 OutTuple* out,
127 std::index_sequence<InNs...>,
128 std::index_sequence<OutNs...>) {
129 (obj->*method)(std::get<InNs>(std::forward<InTuple>(in))...,
130 &std::get<OutNs>(*out)...);
131 }
132
133 template <typename ObjT, typename Method, typename InTuple, typename OutTuple>
DispatchToMethod(const ObjT & obj,Method method,InTuple && in,OutTuple * out)134 inline void DispatchToMethod(const ObjT& obj,
135 Method method,
136 InTuple&& in,
137 OutTuple* out) {
138 constexpr size_t in_size = std::tuple_size<std::decay_t<InTuple>>::value;
139 constexpr size_t out_size = std::tuple_size<OutTuple>::value;
140 DispatchToMethodImpl(obj, method, std::forward<InTuple>(in), out,
141 std::make_index_sequence<in_size>(),
142 std::make_index_sequence<out_size>());
143 }
144
145 } // namespace base
146
147 #endif // !USING_CHROMIUM_INCLUDES
148
149 #endif // CEF_INCLUDE_BASE_CEF_TUPLE_H_
150