vrpc 2.6.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,11 +12,12 @@ __\/\\\_______\/\\\__/\\\///////\\\___\/\\\/////////\\\____/\\\////////__
12
12
 
13
13
  Non-intrusively binds any C++ code and provides access in form of asynchronous
14
14
  remote procedural callbacks (RPC).
15
- Author: Dr. Burkhard C. Heisen (https://github.com/bheisen/vrpc)
15
+ Author: Dr. Burkhard C. Heisen (https://github.com/heisenware/vrpc-hpp)
16
16
 
17
17
 
18
18
  Licensed under the MIT License <http://opensource.org/licenses/MIT>.
19
- Copyright (c) 2018 - 2021 Dr. Burkhard C. Heisen <burkhard.heisen@heisenware.com>.
19
+ Copyright (c) 2018 - 2022 Dr. Burkhard C. Heisen
20
+ <burkhard.heisen@heisenware.com>.
20
21
 
21
22
  Permission is hereby granted, free of charge, to any person obtaining a copy
22
23
  of this software and associated documentation files (the "Software"), to deal
@@ -37,1243 +38,1129 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37
38
  SOFTWARE.
38
39
  */
39
40
 
40
- #ifndef VRPC_HPP
41
- #define VRPC_HPP
41
+ #ifndef VRPC_ADAPTER_HPP
42
+ #define VRPC_ADAPTER_HPP
42
43
 
43
- #define VRPC_VERSION_MAJOR 2
44
- #define VRPC_VERSION_MINOR 6
44
+ #define VRPC_VERSION_MAJOR 3
45
+ #define VRPC_VERSION_MINOR 0
45
46
  #define VRPC_VERSION_PATCH 0
46
47
 
47
48
  #include <cstdint>
48
49
  #include <functional>
49
50
  #include <iostream>
51
+ #include <map>
52
+ #include <memory>
50
53
  #include <set>
51
54
  #include <sstream>
52
55
  #include <tuple>
56
+ #include <type_traits>
53
57
  #include <typeindex>
54
58
  #include <typeinfo>
55
- #include <type_traits>
56
- #include <map>
57
- #include <memory>
58
59
  #include <unordered_map>
59
60
  #include <utility>
60
61
  #include <vector>
61
62
  #if defined(VRPC_WITH_DL) && !defined(_WIN32)
62
- #include <dlfcn.h>
63
+ #include <dlfcn.h>
63
64
  #endif
64
- #include "json.hpp"
65
+
66
+ #include <vrpc/json.hpp>
65
67
 
66
68
  #ifdef VRPC_DEBUG
67
69
  #define _VRPC_DEBUG \
68
- if (1) std::cout << "vrpc::" << __func__ << "\t"
70
+ if (1) \
71
+ std::cout << "vrpc::" << __func__ << "\t"
69
72
  #else
70
73
  #define _VRPC_DEBUG \
71
- if (0) std::cout << "vrpc::" << __func__ << "\t"
74
+ if (0) \
75
+ std::cout << "vrpc::" << __func__ << "\t"
72
76
  #endif
73
77
 
74
78
  // Add std::function to json's serializable types
75
79
  namespace vrpc {
76
80
 
77
- template <typename R, typename ...Args>
78
- struct adl_serializer<std::function<R(Args...)>> {
79
-
80
- static void to_json(json& j, const std::function < R(Args...)>& func) {
81
- j = std::string(); // Callbacks expect a string id as argument signature
82
- }
83
-
84
- static void from_json(const json& j, std::function < R(Args...)>& func) {}
85
- };
86
- }
87
-
88
- namespace vrpc {
89
- namespace detail {
90
-
91
- // Reference and CV qualifier remover
92
- template<typename T>
93
- using no_ref_no_const = typename std::remove_const<
94
- typename std::remove_reference<T>::type
95
- >::type;
96
-
97
- // Singleton helper
98
- template <typename T>
99
- inline T& init() {
100
- static T t;
101
- return t;
102
- }
103
-
104
- inline void pack_r(vrpc::json &json, char i) {}
105
-
106
- template <class Tfirst, class ... Trest>
107
- inline void pack_r(
108
- vrpc::json& json,
109
- char i,
110
- const Tfirst& first,
111
- const Trest&... rest
112
- ) {
113
- char name[] = {'_', '\0', '\0', '\0'};
114
- name[1] = i;
115
- json[name] = first;
116
- detail::pack_r(json, i + 1, rest...);
117
- }
81
+ template <typename R, typename... Args>
82
+ struct adl_serializer<std::function<R(Args...)>> {
83
+ static void to_json(json& j, const std::function<R(Args...)>& func) {
84
+ j = std::string(); // Callbacks expect a string id as argument signature
118
85
  }
119
86
 
120
- /**
121
- * Pack the parameters into a json object.
122
- * @param json Will be filled with keys _1, _2, etc. and associated values
123
- * @param args Any type and number of arguments forming the values
124
- */
125
- template <class ... Ts>
126
- inline void pack(vrpc::json& json, const Ts& ... args) {
127
- detail::pack_r(json, '1', args...);
128
- }
87
+ static void from_json(const json& j, std::function<R(Args...)>& func) {}
88
+ };
89
+ } // namespace vrpc
129
90
 
130
- namespace detail {
91
+ namespace vrpc {
92
+ namespace detail {
93
+
94
+ // Reference and CV qualifier remover
95
+ template <typename T>
96
+ using no_ref_no_const =
97
+ typename std::remove_const<typename std::remove_reference<T>::type>::type;
98
+
99
+ // Singleton helper
100
+ template <typename T>
101
+ inline T& init() {
102
+ static T t;
103
+ return t;
104
+ }
131
105
 
132
- // The code below was formulated as an answer to StackOverflow and can be read here:
133
- // http://stackoverflow.com/questions/10766112/c11-i-can-go-from-multiple-args-to-tuple-but-can-i-go-from-tuple-to-multiple
106
+ inline void pack_r(json&) {}
134
107
 
135
- template <typename F, typename Tuple, bool Done, int Total, int... N>
136
- struct call_impl {
108
+ template <class Tfirst, class... Trest>
109
+ inline void pack_r(json& arr, const Tfirst& first, const Trest&... rest) {
110
+ arr.push_back(first);
111
+ detail::pack_r(arr, rest...);
112
+ }
113
+ } // namespace detail
114
+
115
+ /**
116
+ * Packs the arguments into a json object.
117
+ *
118
+ * @param args The arguments
119
+ * @return json array filled with arguments
120
+ *
121
+ * And by the way: that's the "V" in VRPC (variadic template based arguments)
122
+ * This feature that was introduced in C++11 sparked the idea for this library
123
+ */
124
+ template <class... Ts>
125
+ inline json pack(const Ts&... args) {
126
+ json arr;
127
+ detail::pack_r(arr, args...);
128
+ return arr;
129
+ }
137
130
 
138
- static auto call(F f, Tuple&& t) {
139
- return call_impl<
140
- F,
141
- Tuple,
142
- Total == 1 + sizeof...(N),
143
- Total,
144
- N...,
145
- sizeof...(N)
146
- >::call(f, std::forward<Tuple>(t));
147
- }
148
- };
131
+ namespace detail {
149
132
 
150
- template <typename F, typename Tuple, int Total, int... N>
151
- struct call_impl<F, Tuple, true, Total, N...> {
133
+ // The code below was formulated as an answer to StackOverflow and can be read
134
+ // here:
135
+ // http://stackoverflow.com/questions/10766112/c11-i-can-go-from-multiple-args-to-tuple-but-can-i-go-from-tuple-to-multiple
152
136
 
153
- static auto call(F f, Tuple&& t) {
154
- return f(std::get<N>(std::forward<Tuple>(t))...);
155
- }
156
- };
137
+ template <typename F, typename Tuple, bool Done, int Total, int... N>
138
+ struct call_impl {
139
+ static auto call(F f, Tuple&& t) {
140
+ return call_impl<F, Tuple, Total == 1 + sizeof...(N), Total, N...,
141
+ sizeof...(N)>::call(f, std::forward<Tuple>(t));
157
142
  }
143
+ };
158
144
 
159
- /**
160
- * Call a function f with arguments unpacked from a std::tuple
161
- * @param f The function to be called
162
- * @param t A tuple containing representing the parameters
163
- */
164
- template <typename F, typename Tuple>
165
- auto call(F f, Tuple && t) {
166
- typedef typename std::decay<Tuple>::type ttype;
167
- return detail::call_impl<
168
- F,
169
- Tuple,
170
- 0 == std::tuple_size<ttype>::value,
171
- std::tuple_size<ttype>::value
172
- >::call(f, std::forward<Tuple>(t));
145
+ template <typename F, typename Tuple, int Total, int... N>
146
+ struct call_impl<F, Tuple, true, Total, N...> {
147
+ static auto call(F f, Tuple&& t) {
148
+ return f(std::get<N>(std::forward<Tuple>(t))...);
173
149
  }
150
+ };
151
+ } // namespace detail
152
+
153
+ /**
154
+ * Call a function f with arguments unpacked from a std::tuple
155
+ * @param f The function to be called
156
+ * @param t A tuple containing representing the parameters
157
+ */
158
+ template <typename F, typename Tuple>
159
+ auto call(F f, Tuple&& t) {
160
+ typedef typename std::decay<Tuple>::type ttype;
161
+ return detail::call_impl<
162
+ F, Tuple, 0 == std::tuple_size<ttype>::value,
163
+ std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
164
+ }
174
165
 
175
- namespace detail {
166
+ namespace detail {
176
167
 
177
- template <std::size_t... Is>
178
- struct indices {};
168
+ template <std::size_t... Is>
169
+ struct indices {};
179
170
 
180
- template <std::size_t N, std::size_t... Is>
181
- struct build_indices
182
- : build_indices<N - 1, N - 1, Is...> {};
171
+ template <std::size_t N, std::size_t... Is>
172
+ struct build_indices : build_indices<N - 1, N - 1, Is...> {};
183
173
 
184
- template <std::size_t... Is>
185
- struct build_indices<0, Is...> : indices<Is...> {};
174
+ template <std::size_t... Is>
175
+ struct build_indices<0, Is...> : indices<Is...> {};
186
176
 
187
- template<int I> struct placeholder {};
177
+ template <int I>
178
+ struct placeholder {};
188
179
 
189
- template<std::size_t... Is, typename Klass, typename Func>
190
- auto variadic_bind_member(
191
- detail::indices<Is...>,
192
- const Func& f,
193
- const std::shared_ptr<Klass>& ptr
194
- ) -> decltype(std::bind(f, ptr, placeholder<Is + 1 >{}...)) {
195
- return std::bind(f, ptr, placeholder<Is + 1 >{}...);
196
- }
197
- }
180
+ template <std::size_t... Is, typename Klass, typename Func>
181
+ auto variadic_bind_member(detail::indices<Is...>,
182
+ const Func& f,
183
+ const std::shared_ptr<Klass>& ptr)
184
+ -> decltype(std::bind(f, ptr, placeholder<Is + 1>{}...)) {
185
+ return std::bind(f, ptr, placeholder<Is + 1>{}...);
198
186
  }
187
+ } // namespace detail
188
+ } // namespace vrpc
199
189
 
200
190
  namespace std {
201
- template<int I>
202
- struct is_placeholder<vrpc::detail::placeholder<I> >
203
- : std::integral_constant<int, I>{};
204
- }
191
+ template <int I>
192
+ struct is_placeholder<vrpc::detail::placeholder<I>>
193
+ : std::integral_constant<int, I> {};
194
+ } // namespace std
205
195
 
206
196
  namespace vrpc {
207
197
 
208
- template<typename Klass, typename Func, typename ...Args>
209
- auto variadic_bind_member(const Func& f, const std::shared_ptr<Klass>& ptr)
210
- -> decltype(
211
- detail::variadic_bind_member(
212
- detail::build_indices<sizeof...(Args)>{},
213
- f,
214
- ptr
215
- )
216
- ) {
217
- return detail::variadic_bind_member(
218
- detail::build_indices<sizeof...(Args)>{},
219
- f,
220
- ptr
221
- );
222
- }
223
-
224
- namespace detail {
225
-
226
- template<std::size_t... Is, typename Func>
227
- auto variadic_bind(detail::indices<Is...>, const Func& f)
228
- -> decltype(std::bind(f, placeholder<Is + 1 >{}...)) {
229
- return std::bind(f, placeholder < Is + 1 >{}...);
230
- }
231
- }
232
-
233
- template<typename Func, typename ...Args>
234
- auto variadic_bind(const Func& f)
235
- -> decltype(
236
- detail::variadic_bind(detail::build_indices<sizeof...(Args)>{}, f)
237
- ) {
238
- return detail::variadic_bind(detail::build_indices<sizeof...(Args)>{}, f);
239
- }
240
-
241
- typedef std::function<void (const vrpc::json&) > CallbackHandler;
242
-
243
- struct Callback {
244
-
245
- static void register_callback_handler(const CallbackHandler& handler) {
246
- detail::init<CallbackHandler>() = handler;
247
- }
248
- };
249
-
250
- namespace detail {
251
-
252
- template <typename T>
253
- struct CallbackT;
254
-
255
- template <typename R, typename ...Args>
256
- struct CallbackT<std::function<R(Args...)>> :
257
- public std::enable_shared_from_this<CallbackT<std::function<R(Args...)>>>,
258
- public vrpc::Callback {
259
- vrpc::json m_json;
260
- std::string m_callback_id;
198
+ template <typename Klass, typename Func, typename... Args>
199
+ auto variadic_bind_member(const Func& f, const std::shared_ptr<Klass>& ptr)
200
+ -> decltype(detail::variadic_bind_member(
201
+ detail::build_indices<sizeof...(Args)>{},
202
+ f,
203
+ ptr)) {
204
+ return detail::variadic_bind_member(detail::build_indices<sizeof...(Args)>{},
205
+ f, ptr);
206
+ }
261
207
 
262
- CallbackT(const vrpc::json& json, const std::string key) :
263
- m_json(json),
264
- m_callback_id(json["data"][key].get<std::string>()) {
265
- _VRPC_DEBUG << "Constructed with: " << m_json << " and "
266
- << m_callback_id << std::endl;
267
- }
208
+ namespace detail {
268
209
 
269
- void wrapper(Args... args) {
270
- vrpc::json data;
271
- pack(data, args...);
272
- m_json["data"] = data;
273
- m_json["id"] = m_callback_id;
274
- _VRPC_DEBUG << "Triggering callback: " << m_callback_id
275
- << " with payload: " << data << std::endl;
276
- detail::init<CallbackHandler>()(m_json);
277
- }
278
-
279
- auto bind_wrapper() {
280
- auto func = &CallbackT < std::function<R(Args...)>>::wrapper;
281
- auto ptr = std::enable_shared_from_this<
282
- CallbackT<std::function<R(Args...)>>
283
- >::shared_from_this();
284
- return detail::variadic_bind_member(
285
- detail::build_indices<sizeof...(Args)>{}, func, ptr
286
- );
287
- }
288
- };
289
-
290
- template <typename ...Args>
291
- struct is_std_function : std::false_type {
292
- };
210
+ template <std::size_t... Is, typename Func>
211
+ auto variadic_bind(detail::indices<Is...>, const Func& f)
212
+ -> decltype(std::bind(f, placeholder<Is + 1>{}...)) {
213
+ return std::bind(f, placeholder<Is + 1>{}...);
214
+ }
215
+ } // namespace detail
293
216
 
294
- template <typename ...Args>
295
- struct is_std_function<std::function<void (Args...)>>
296
- : std::true_type {};
297
-
298
- template <typename ...Args>
299
- struct is_std_function<const std::function<void (Args...)>&>
300
- : std::true_type {};
301
-
302
- template <char C, typename ...Args>
303
- struct unpack_impl;
304
-
305
- /* This specialization will remove reference and CV qualifier and bring
306
- * back the recursion to the standard path using vrpc::json::get().
307
- * Really, it should use vrpc::json::get_ref() in combination with
308
- * std::tie(), however currently json does not support custom types in refs.
309
- */
310
- template<char C, typename A, typename ...Args>
311
- struct unpack_impl<C, A, Args...> {
312
- template<
313
- typename T = A,
314
- typename std::enable_if<std::is_reference<T>::value, int>::type = 0
315
- >
316
- static auto unpack(vrpc::json& j)
317
- -> decltype(
318
- std::tuple_cat(
319
- std::make_tuple(std::declval<no_ref_no_const<T>>()),
320
- unpack_impl<C + 1, Args...>::unpack(j)
321
- )
322
- ) {
323
- // length 4 for better assembly alignment
324
- constexpr const char key[] = {'_', C, '\0', '\0'};
325
- typedef typename std::remove_const<
326
- typename std::remove_reference<T>::type
327
- >::type T_no_ref_no_const;
328
- return std::tuple_cat(
329
- std::make_tuple(j["data"][key].get<T_no_ref_no_const>()),
330
- unpack_impl < C + 1, Args...>::unpack(j)
331
- );
332
- }
217
+ template <typename Func, typename... Args>
218
+ auto variadic_bind(const Func& f)
219
+ -> decltype(detail::variadic_bind(detail::build_indices<sizeof...(Args)>{},
220
+ f)) {
221
+ return detail::variadic_bind(detail::build_indices<sizeof...(Args)>{}, f);
222
+ }
333
223
 
334
- template<
335
- typename T = A,
336
- typename std::enable_if<!std::is_reference<T>::value, int>::type = 0
337
- >
338
- static auto unpack(vrpc::json& j)
339
- -> decltype(std::tuple_cat(
340
- std::make_tuple(std::declval<T>()),
341
- unpack_impl<C + 1, Args...>::unpack(j))
342
- ) {
343
- constexpr const char key[] = {'_', C, '\0', '\0'};
344
- return std::tuple_cat(
345
- std::make_tuple(j["data"][key].get<T>()),
346
- unpack_impl < C + 1, Args...>::unpack(j)
347
- );
348
- }
349
- };
224
+ typedef std::function<void(const json&)> CallbackHandler;
350
225
 
351
- template<char C, typename A>
352
- struct unpack_impl<C, A> {
353
- template<
354
- typename T = A,
355
- typename std::enable_if<
356
- std::is_reference<T>::value &&
357
- !is_std_function<T>::value, int>::type = 0
358
- >
359
- static std::tuple<no_ref_no_const<T>> unpack(vrpc::json& j) {
360
- constexpr const char key[] = {'_', C, '\0', '\0'};
361
- return std::make_tuple(j["data"][key].get<no_ref_no_const<T>>());
362
- }
226
+ struct Callback {
227
+ static void register_callback_handler(const CallbackHandler& handler) {
228
+ detail::init<CallbackHandler>() = handler;
229
+ }
230
+ };
363
231
 
364
- template<
365
- typename T = A,
366
- typename std::enable_if<
367
- !std::is_reference<T>::value &&
368
- !is_std_function<T>::value, int>::type = 0
369
- >
370
- static std::tuple<T> unpack(vrpc::json& j) {
371
- constexpr const char key[] = {'_', C, '\0', '\0'};
372
- return std::make_tuple(j["data"][key].get<T>());
373
- }
232
+ namespace detail {
374
233
 
375
- template<
376
- typename T = A,
377
- typename std::enable_if<is_std_function<T>::value, int>::type = 0
378
- >
379
- static auto unpack(vrpc::json& j) {
380
- constexpr const char key[] = {'_', C, '\0', '\0'};
381
- auto ptr = std::make_shared<CallbackT<no_ref_no_const<T>>>(j, key);
382
- return std::make_tuple(ptr->bind_wrapper());
383
- }
384
- };
234
+ template <typename T>
235
+ struct CallbackT;
385
236
 
386
- template<char C>
387
- struct unpack_impl<C> {
237
+ template <typename R, typename... Args>
238
+ struct CallbackT<std::function<R(Args...)>>
239
+ : public std::enable_shared_from_this<CallbackT<std::function<R(Args...)>>>,
240
+ public vrpc::Callback {
241
+ json _json;
242
+ std::string _callback_id;
388
243
 
389
- static std::tuple<> unpack(vrpc::json&) {
390
- return std::tuple<>();
391
- }
392
- };
244
+ CallbackT(const json& json, int index)
245
+ : _json(json), _callback_id(json["a"][index].get<std::string>()) {
246
+ _VRPC_DEBUG << "Constructed with: " << _json << " and " << _callback_id
247
+ << std::endl;
393
248
  }
394
249
 
395
- /**
396
- * Unpack parameters into a tuple using perfect forwarding
397
- * @param j json with keys _1, _2, etc. encoding function arguments
398
- * @return std::tuple<Args...>
399
- */
400
- template<typename ...Args>
401
- auto unpack(vrpc::json& j)
402
- -> decltype(detail::unpack_impl < '1', Args...>::unpack(j)) {
403
- return detail::unpack_impl < '1', Args...>::unpack(j);
250
+ void wrapper(Args... args) {
251
+ _json["a"] = pack(args...);
252
+ _json["i"] = _callback_id;
253
+ _VRPC_DEBUG << "Triggering callback: " << _callback_id
254
+ << " with payload: " << _json["a"] << std::endl;
255
+ detail::init<CallbackHandler>()(_json);
404
256
  }
405
257
 
406
- namespace detail {
407
-
408
- template<std::size_t I = 0, typename ...Args>
409
- inline typename std::enable_if<I == sizeof...(Args), void>::type
410
- get_signature(const std::string& signature, const std::tuple<Args...>&) {
411
- // end recursion
412
- }
413
-
414
- template<std::size_t I = 0, typename ...Args>
415
- inline typename std::enable_if<I < sizeof...(Args), void>::type
416
- get_signature(std::string& signature, const std::tuple<Args...>& t) {
417
- vrpc::json j{
418
- {"t", std::get<I>(t)}};
419
- signature += j["t"].type_name();
420
- return get_signature < I + 1, Args...>(signature, t);
421
- }
258
+ auto bind_wrapper() {
259
+ auto func = &CallbackT<std::function<R(Args...)>>::wrapper;
260
+ auto ptr = std::enable_shared_from_this<
261
+ CallbackT<std::function<R(Args...)>>>::shared_from_this();
262
+ return detail::variadic_bind_member(
263
+ detail::build_indices<sizeof...(Args)>{}, func, ptr);
422
264
  }
423
-
424
- template<typename ...Args>
425
- inline std::string get_signature() {
426
- std::string signature;
427
- detail::get_signature(
428
- signature,
429
- std::tuple<typename std::remove_reference<Args>::type...>()
430
- );
431
- return signature.empty() ? signature : "-" + signature;
265
+ };
266
+
267
+ template <typename... Args>
268
+ struct is_std_function : std::false_type {};
269
+
270
+ template <typename... Args>
271
+ struct is_std_function<std::function<void(Args...)>> : std::true_type {};
272
+
273
+ template <typename... Args>
274
+ struct is_std_function<const std::function<void(Args...)>&> : std::true_type {};
275
+
276
+ template <int I, typename... Args>
277
+ struct unpack_impl;
278
+
279
+ /* This specialization will remove reference and CV qualifier and bring
280
+ * back the recursion to the standard path using json::get().
281
+ * Really, it should use json::get_ref() in combination with
282
+ * std::tie(), however currently json does not support custom types in refs.
283
+ */
284
+ template <int I, typename A, typename... Args>
285
+ struct unpack_impl<I, A, Args...> {
286
+ template <typename T = A,
287
+ typename std::enable_if<std::is_reference<T>::value &&
288
+ !is_std_function<T>::value,
289
+ int>::type = 0>
290
+ static auto unpack(json& j) -> decltype(std::tuple_cat(
291
+ std::make_tuple(std::declval<no_ref_no_const<T>>()),
292
+ unpack_impl<I + 1, Args...>::unpack(j))) {
293
+ typedef typename std::remove_const<
294
+ typename std::remove_reference<T>::type>::type T_no_ref_no_const;
295
+ return std::tuple_cat(std::make_tuple(j["a"][I].get<T_no_ref_no_const>()),
296
+ unpack_impl<I + 1, Args...>::unpack(j));
432
297
  }
433
298
 
434
- inline std::string get_signature(const vrpc::json& json) {
435
- std::string signature;
436
- for (const auto& it : json) {
437
- signature += it.type_name();
438
- }
439
- return signature.empty() ? signature : "-" + signature;
299
+ template <typename T = A,
300
+ typename std::enable_if<!std::is_reference<T>::value &&
301
+ !is_std_function<T>::value,
302
+ int>::type = 0>
303
+ static auto unpack(json& j)
304
+ -> decltype(std::tuple_cat(std::make_tuple(std::declval<T>()),
305
+ unpack_impl<I + 1, Args...>::unpack(j))) {
306
+ return std::tuple_cat(std::make_tuple(j["a"][I].get<T>()),
307
+ unpack_impl<I + 1, Args...>::unpack(j));
440
308
  }
441
309
 
442
- namespace detail {
443
-
444
- template <typename T>
445
- struct is_shared_ptr : std::false_type {};
446
-
447
- template <typename T>
448
- struct is_shared_ptr<std::shared_ptr<T> > : std::true_type {};
310
+ template <typename T = A,
311
+ typename std::enable_if<is_std_function<T>::value, int>::type = 0>
312
+ static auto unpack(json& j) {
313
+ // TODO hand over the index as template parameter
314
+ auto ptr = std::make_shared<CallbackT<no_ref_no_const<T>>>(j, I);
315
+ return std::tuple_cat(std::make_tuple(ptr->bind_wrapper()),
316
+ unpack_impl<I + 1, Args...>::unpack(j));
317
+ }
318
+ };
319
+
320
+ template <int I, typename A>
321
+ struct unpack_impl<I, A> {
322
+ template <typename T = A,
323
+ typename std::enable_if<std::is_reference<T>::value &&
324
+ !is_std_function<T>::value,
325
+ int>::type = 0>
326
+ static std::tuple<no_ref_no_const<T>> unpack(json& j) {
327
+ return std::make_tuple(j["a"][I].get<no_ref_no_const<T>>());
449
328
  }
450
329
 
451
- // Value class
452
- class Value {
453
- public:
454
-
455
- Value() noexcept
456
- : content(0) {}
457
-
458
- template<typename T>
459
- Value(const T& value)
460
- : content(new holder<
461
- typename std::remove_cv<typename std::decay<T>::type>::type
462
- >(value)) {}
463
-
464
- Value(const char* const& value)
465
- : Value(std::string(value)) {}
466
-
467
- /// Copy constructor
468
- Value(const Value& other)
469
- : content(other.content ? other.content->clone() : 0) {}
470
-
471
- /// Move constructor
472
- Value(Value&& other)
473
- : content(other.content) {
474
- other.content = 0;
475
- }
476
-
477
- template<typename T>
478
- Value(
479
- T&& value,
480
- typename std::enable_if<!std::is_same<Value&, T>::value >::type* = 0,
481
- typename std::enable_if<!std::is_const<T>::value >::type* = 0,
482
- typename std::enable_if<!detail::is_shared_ptr<T>::value >::type* = 0
483
- ) : content(
484
- new holder<typename std::remove_cv<typename std::decay<T>::type>::type>(
485
- std::forward<T>(value)
486
- )
487
- ) {}
488
-
489
- ~Value() noexcept {
490
- delete content;
491
- }
492
-
493
- public: // functions
494
-
495
- Value& swap(Value& rhs) noexcept {
496
- std::swap(content, rhs.content);
497
- return *this;
498
- }
499
-
500
- Value& operator=(const Value& rhs) {
501
- Value(rhs).swap(*this);
502
- return *this;
503
- }
504
-
505
- Value& operator=(Value&& rhs) noexcept {
506
- rhs.swap(*this);
507
- Value().swap(rhs);
508
- return *this;
509
- }
330
+ template <typename T = A,
331
+ typename std::enable_if<!std::is_reference<T>::value &&
332
+ !is_std_function<T>::value,
333
+ int>::type = 0>
334
+ static std::tuple<T> unpack(json& j) {
335
+ return std::make_tuple(j["a"][I].get<T>());
336
+ }
510
337
 
511
- template <typename T>
512
- Value& operator=(T&& rhs) {
513
- Value(static_cast<T&&> (rhs)).swap(*this);
514
- return *this;
515
- }
338
+ template <typename T = A,
339
+ typename std::enable_if<is_std_function<T>::value, int>::type = 0>
340
+ static auto unpack(json& j) {
341
+ auto ptr = std::make_shared<CallbackT<no_ref_no_const<T>>>(j, I);
342
+ return std::make_tuple(ptr->bind_wrapper());
343
+ }
344
+ };
345
+
346
+ template <int I>
347
+ struct unpack_impl<I> {
348
+ static std::tuple<> unpack(json&) { return {}; }
349
+ };
350
+ } // namespace detail
351
+
352
+ /**
353
+ * Unpack parameters into a tuple using perfect forwarding
354
+ * @param j json with keys _1, _2, etc. encoding function arguments
355
+ * @return std::tuple<Args...>
356
+ */
357
+ template <typename... Args>
358
+ auto unpack(json& j) -> decltype(detail::unpack_impl<0, Args...>::unpack(j)) {
359
+ return detail::unpack_impl<0, Args...>::unpack(j);
360
+ }
516
361
 
517
- Value& operator=(const char* const& rhs) {
518
- Value(std::string(rhs)).swap(*this);
519
- return *this;
520
- }
362
+ namespace detail {
521
363
 
522
- // NOTE: Windows compiler is broken here
523
- // template <typename T>
524
- // operator const T&() const {
525
- // return const_cast<Value*> (this)->template get<T>();
526
- // }
527
-
528
- // template <typename T>
529
- // operator T() const {
530
- // return const_cast<Value*> (this)->template get<T>();
531
- // }
532
-
533
- template <typename T>
534
- T& operator=(T& rhs) {
535
- Value(rhs).swap(*this);
536
- return *this;
537
- }
364
+ template <std::size_t I = 0, typename... Args>
365
+ inline typename std::enable_if<I == sizeof...(Args), void>::type get_signature(
366
+ const std::string& signature,
367
+ const std::tuple<Args...>&) {
368
+ // end recursion
369
+ }
538
370
 
539
- bool empty() const noexcept {
540
- return !content;
541
- }
371
+ template <std::size_t I = 0, typename... Args>
372
+ inline typename std::enable_if <
373
+ I<sizeof...(Args), void>::type get_signature(std::string& signature,
374
+ const std::tuple<Args...>& t) {
375
+ json j = {{"t", std::get<I>(t)}};
376
+ if (!signature.empty()) signature += ":";
377
+ signature += j["t"].type_name();
378
+ return get_signature<I + 1, Args...>(signature, t);
379
+ }
380
+ } // namespace detail
381
+
382
+ template <typename... Args>
383
+ inline std::string get_signature() {
384
+ std::string signature;
385
+ detail::get_signature(
386
+ signature, std::tuple<typename std::remove_reference<Args>::type...>());
387
+ return signature.empty() ? signature : "-" + signature;
388
+ }
542
389
 
543
- void clear() noexcept {
544
- Value().swap(*this);
545
- }
390
+ inline std::string get_signature(const json& json) {
391
+ std::string signature;
392
+ for (const auto& it : json) {
393
+ if (!signature.empty()) signature += ":";
394
+ signature += it.type_name();
395
+ }
396
+ return signature.empty() ? signature : "-" + signature;
397
+ }
546
398
 
547
- std::type_index type() const noexcept {
548
- static std::type_index void_type(typeid (void));
549
- return content ? content->type() : void_type;
550
- }
399
+ namespace detail {
551
400
 
552
- template <typename T>
553
- inline const T& get() const {
554
- // TODO Check type correctness here
555
- // TODO implement by specialization and not by overload
556
- return _get<T>(typename detail::is_shared_ptr<T>::type());
557
- }
401
+ template <typename T>
402
+ struct is_shared_ptr : std::false_type {};
558
403
 
559
- private: // functions
404
+ template <typename T>
405
+ struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
406
+ } // namespace detail
560
407
 
561
- template <typename T>
562
- inline const T& _get(const std::true_type&) const {
563
- return static_cast<
564
- holder<typename std::remove_cv<typename T::element_type>::type >*
565
- > (content)->held;
566
- }
408
+ // Value class
409
+ class Value {
410
+ public:
411
+ Value() noexcept : content(0) {}
567
412
 
568
- template <typename T>
569
- inline const T& _get(const std::false_type&) const {
570
- return *(static_cast<
571
- holder< typename std::remove_cv<T>::type >*
572
- > (content)->held);
573
- }
413
+ template <typename T>
414
+ Value(const T& value)
415
+ : content(new holder<
416
+ typename std::remove_cv<typename std::decay<T>::type>::type>(
417
+ value)) {}
574
418
 
575
- private: // types
419
+ Value(const char* const& value) : Value(std::string(value)) {}
576
420
 
577
- class placeholder {
578
- public: // structors
421
+ /// Copy constructor
422
+ Value(const Value& other)
423
+ : content(other.content ? other.content->clone() : 0) {}
579
424
 
580
- virtual ~placeholder() { }
425
+ /// Move constructor
426
+ Value(Value&& other) : content(other.content) { other.content = 0; }
581
427
 
582
- public: // queries
428
+ template <typename T>
429
+ Value(T&& value,
430
+ typename std::enable_if<!std::is_same<Value&, T>::value>::type* = 0,
431
+ typename std::enable_if<!std::is_const<T>::value>::type* = 0,
432
+ typename std::enable_if<!detail::is_shared_ptr<T>::value>::type* = 0)
433
+ : content(new holder<
434
+ typename std::remove_cv<typename std::decay<T>::type>::type>(
435
+ std::forward<T>(value))) {}
583
436
 
584
- virtual std::type_index type() const noexcept = 0;
437
+ ~Value() noexcept { delete content; }
585
438
 
586
- virtual placeholder* clone() const = 0;
587
- };
439
+ public: // functions
440
+ Value& swap(Value& rhs) noexcept {
441
+ std::swap(content, rhs.content);
442
+ return *this;
443
+ }
588
444
 
589
- template<typename T>
590
- class holder : public placeholder {
591
- public: // structors
445
+ Value& operator=(const Value& rhs) {
446
+ Value(rhs).swap(*this);
447
+ return *this;
448
+ }
592
449
 
593
- holder(const T& value)
594
- : held(new T(value)) { }
450
+ Value& operator=(Value&& rhs) noexcept {
451
+ rhs.swap(*this);
452
+ Value().swap(rhs);
453
+ return *this;
454
+ }
595
455
 
596
- holder(T&& value)
597
- : held(new T(static_cast<T&& > (value))) { }
456
+ template <typename T>
457
+ Value& operator=(T&& rhs) {
458
+ Value(static_cast<T&&>(rhs)).swap(*this);
459
+ return *this;
460
+ }
598
461
 
462
+ Value& operator=(const char* const& rhs) {
463
+ Value(std::string(rhs)).swap(*this);
464
+ return *this;
465
+ }
599
466
 
600
- public: // queries
467
+ // NOTE: Windows compiler is broken here
468
+ // template <typename T>
469
+ // operator const T&() const {
470
+ // return const_cast<Value*> (this)->template get<T>();
471
+ // }
472
+
473
+ // template <typename T>
474
+ // operator T() const {
475
+ // return const_cast<Value*> (this)->template get<T>();
476
+ // }
477
+
478
+ template <typename T>
479
+ T& operator=(T& rhs) {
480
+ Value(rhs).swap(*this);
481
+ return *this;
482
+ }
601
483
 
602
- virtual std::type_index type() const noexcept {
603
- return std::type_index(typeid (T));
604
- }
484
+ bool empty() const noexcept { return !content; }
605
485
 
606
- virtual placeholder* clone() const {
607
- // This copies a std::shared_ptr!
608
- return new holder(*held);
609
- }
486
+ void clear() noexcept { Value().swap(*this); }
610
487
 
611
- holder& operator=(const holder&) = delete;
488
+ std::type_index type() const noexcept {
489
+ static std::type_index void_type(typeid(void));
490
+ return content ? content->type() : void_type;
491
+ }
612
492
 
613
- public: // representation
493
+ template <typename T>
494
+ inline const T& get() const {
495
+ // TODO Check type correctness here
496
+ // TODO implement by specialization and not by overload
497
+ return _get<T>(typename detail::is_shared_ptr<T>::type());
498
+ }
614
499
 
615
- std::shared_ptr<T> held;
500
+ private: // functions
501
+ template <typename T>
502
+ inline const T& _get(const std::true_type&) const {
503
+ return static_cast<holder<
504
+ typename std::remove_cv<typename T::element_type>::type>*>(content)
505
+ ->held;
506
+ }
616
507
 
617
- };
508
+ template <typename T>
509
+ inline const T& _get(const std::false_type&) const {
510
+ return *(
511
+ static_cast<holder<typename std::remove_cv<T>::type>*>(content)->held);
512
+ }
618
513
 
619
- template <typename T>
620
- class holder<std::shared_ptr<T> > : public placeholder {
621
- public:
514
+ private: // types
515
+ class placeholder {
516
+ public: // structors
517
+ virtual ~placeholder() {}
622
518
 
623
- holder(const std::shared_ptr<T>& value)
624
- : held(value) { }
519
+ public: // queries
520
+ virtual std::type_index type() const noexcept = 0;
625
521
 
626
- public: // queries
522
+ virtual placeholder* clone() const = 0;
523
+ };
627
524
 
628
- virtual std::type_index type() const noexcept {
629
- return std::type_index(typeid (T));
630
- }
525
+ template <typename T>
526
+ class holder : public placeholder {
527
+ public: // structors
528
+ holder(const T& value) : held(new T(value)) {}
631
529
 
632
- virtual placeholder* clone() const {
633
- // This copies a std::shared_ptr!
634
- return new holder(held);
635
- }
530
+ holder(T&& value) : held(new T(static_cast<T&&>(value))) {}
636
531
 
637
- holder& operator=(const holder&) = delete;
532
+ public: // queries
533
+ virtual std::type_index type() const noexcept {
534
+ return std::type_index(typeid(T));
535
+ }
638
536
 
639
- public: // representation
537
+ virtual placeholder* clone() const {
538
+ // This copies a std::shared_ptr!
539
+ return new holder(*held);
540
+ }
640
541
 
641
- std::shared_ptr<T> held;
642
- };
542
+ holder& operator=(const holder&) = delete;
643
543
 
644
- placeholder* content;
544
+ public: // representation
545
+ std::shared_ptr<T> held;
645
546
  };
646
547
 
647
- inline bool operator==(const Value& lhs, const char& rhs) {
648
- return lhs.get<char>() == rhs;
649
- }
650
-
651
- class Function {
652
- public:
653
-
654
- Function() { }
548
+ template <typename T>
549
+ class holder<std::shared_ptr<T>> : public placeholder {
550
+ public:
551
+ holder(const std::shared_ptr<T>& value) : held(value) {}
655
552
 
656
- virtual ~Function() { }
657
-
658
- template <typename T>
659
- void bind_instance(const std::shared_ptr<T>& instance) {
660
- this->do_bind_instance(Value(instance));
553
+ public: // queries
554
+ virtual std::type_index type() const noexcept {
555
+ return std::type_index(typeid(T));
661
556
  }
662
557
 
663
- void call_function(vrpc::json& json) {
664
- this->do_call_function(json);
558
+ virtual placeholder* clone() const {
559
+ // This copies a std::shared_ptr!
560
+ return new holder(held);
665
561
  }
666
562
 
667
- std::shared_ptr<Function> clone() {
668
- return this->do_clone();
669
- }
563
+ holder& operator=(const holder&) = delete;
670
564
 
671
- protected:
672
-
673
- virtual void do_bind_instance(const Value& instance) = 0;
674
- virtual void do_call_function(vrpc::json& json) = 0;
675
- virtual std::shared_ptr<Function> do_clone() = 0;
565
+ public: // representation
566
+ std::shared_ptr<T> held;
676
567
  };
677
568
 
678
- template <typename Klass, typename Lambda, typename Ret, typename ...Args>
679
- class MemberFunction : public Function {
680
- Lambda m_lambda;
681
- std::shared_ptr<Klass> m_ptr;
682
-
683
- public:
569
+ placeholder* content;
570
+ };
684
571
 
685
- MemberFunction(
686
- const Lambda& lambda
687
- ) : m_lambda(lambda) { }
572
+ inline bool operator==(const Value& lhs, const char& rhs) {
573
+ return lhs.get<char>() == rhs;
574
+ }
688
575
 
689
- virtual ~MemberFunction() = default;
576
+ class Function {
577
+ public:
578
+ Function() {}
690
579
 
691
- virtual std::shared_ptr<Function> do_clone() {
692
- auto ptr = std::make_shared<MemberFunction>(m_lambda);
693
- return std::static_pointer_cast<Function>(ptr);
694
- }
580
+ virtual ~Function() {}
695
581
 
696
- virtual void do_call_function(vrpc::json& json) {
697
- try {
698
- json["data"]["r"] = vrpc::call(
699
- m_lambda(m_ptr),
700
- vrpc::unpack<Args...>(json)
701
- );
702
- } catch (const std::exception& e) {
703
- json["data"]["e"] = std::string(e.what());
704
- }
705
- }
582
+ template <typename T>
583
+ void bind_instance(const std::shared_ptr<T>& instance) {
584
+ this->do_bind_instance(Value(instance));
585
+ }
706
586
 
707
- virtual void do_bind_instance(const Value& instance) {
708
- m_ptr = instance.get<std::shared_ptr<Klass> >();
709
- }
710
- };
587
+ void call_function(json& json) { this->do_call_function(json); }
711
588
 
712
- template <typename Klass, typename Lambda, typename ...Args>
713
- class MemberFunction<Klass, Lambda, void, Args...> : public Function {
714
- Lambda m_lambda;
715
- std::shared_ptr<Klass> m_ptr;
589
+ std::shared_ptr<Function> clone() { return this->do_clone(); }
716
590
 
717
- public:
591
+ protected:
592
+ virtual void do_bind_instance(const Value& instance) = 0;
593
+ virtual void do_call_function(json& json) = 0;
594
+ virtual std::shared_ptr<Function> do_clone() = 0;
595
+ };
718
596
 
719
- MemberFunction(
720
- const Lambda& lambda
721
- ) : m_lambda(lambda) { }
597
+ template <typename Klass, typename Lambda, typename Ret, typename... Args>
598
+ class MemberFunction : public Function {
599
+ Lambda _lambda;
600
+ std::shared_ptr<Klass> _ptr;
722
601
 
723
- virtual ~MemberFunction() = default;
602
+ public:
603
+ MemberFunction(const Lambda& lambda) : _lambda(lambda) {}
724
604
 
725
- virtual std::shared_ptr<Function> do_clone() {
726
- auto ptr = std::make_shared<MemberFunction>(m_lambda);
727
- return std::static_pointer_cast<Function>(ptr);
728
- }
605
+ virtual ~MemberFunction() = default;
729
606
 
730
- virtual void do_call_function(vrpc::json& json) {
731
- try {
732
- vrpc::call(m_lambda(m_ptr), vrpc::unpack<Args...>(json));
733
- json["data"]["r"] = nullptr;
734
- } catch (const std::exception& e) {
735
- json["data"]["e"] = std::string(e.what());
736
- }
737
- }
607
+ virtual std::shared_ptr<Function> do_clone() {
608
+ auto ptr = std::make_shared<MemberFunction>(_lambda);
609
+ return std::static_pointer_cast<Function>(ptr);
610
+ }
738
611
 
739
- virtual void do_bind_instance(const Value& instance) {
740
- m_ptr = instance.get<std::shared_ptr<Klass> >();
612
+ virtual void do_call_function(json& json) {
613
+ try {
614
+ json["r"] = vrpc::call(_lambda(_ptr), vrpc::unpack<Args...>(json));
615
+ } catch (const std::exception& e) {
616
+ json["e"] = std::string(e.what());
741
617
  }
742
- };
743
-
744
- template <typename Lambda, typename Ret, typename ...Args>
745
- class StaticFunction : public Function {
746
- Lambda m_lambda;
618
+ }
747
619
 
748
- public:
620
+ virtual void do_bind_instance(const Value& instance) {
621
+ _ptr = instance.get<std::shared_ptr<Klass>>();
622
+ }
623
+ };
749
624
 
750
- StaticFunction(
751
- const Lambda& lambda
752
- ) : m_lambda(lambda) { }
625
+ template <typename Klass, typename Lambda, typename... Args>
626
+ class MemberFunction<Klass, Lambda, void, Args...> : public Function {
627
+ Lambda _lambda;
628
+ std::shared_ptr<Klass> _ptr;
753
629
 
754
- virtual ~StaticFunction() = default;
630
+ public:
631
+ MemberFunction(const Lambda& lambda) : _lambda(lambda) {}
755
632
 
756
- virtual std::shared_ptr<Function> do_clone() {
757
- auto ptr = std::make_shared<StaticFunction>(m_lambda);
758
- return std::static_pointer_cast<Function>(ptr);
759
- }
633
+ virtual ~MemberFunction() = default;
760
634
 
761
- virtual void do_call_function(vrpc::json& json) {
762
- try {
763
- json["data"]["r"] = vrpc::call(m_lambda(), vrpc::unpack<Args...>(json));
764
- } catch (const std::exception& e) {
765
- json["data"]["e"] = std::string(e.what());
766
- }
767
- }
635
+ virtual std::shared_ptr<Function> do_clone() {
636
+ auto ptr = std::make_shared<MemberFunction>(_lambda);
637
+ return std::static_pointer_cast<Function>(ptr);
638
+ }
768
639
 
769
- virtual void do_bind_instance(const Value&) {
770
- // Nothing to bind, static function
640
+ virtual void do_call_function(json& json) {
641
+ try {
642
+ vrpc::call(_lambda(_ptr), vrpc::unpack<Args...>(json));
643
+ json["r"] = nullptr;
644
+ } catch (const std::exception& e) {
645
+ json["e"] = std::string(e.what());
771
646
  }
772
- };
773
-
774
- template <typename Lambda, typename ...Args>
775
- class StaticFunction<Lambda, void, Args...> : public Function {
776
- Lambda m_lambda;
647
+ }
777
648
 
778
- public:
649
+ virtual void do_bind_instance(const Value& instance) {
650
+ _ptr = instance.get<std::shared_ptr<Klass>>();
651
+ }
652
+ };
779
653
 
780
- StaticFunction(
781
- const Lambda& lambda
782
- ) : m_lambda(lambda) { }
654
+ template <typename Lambda, typename Ret, typename... Args>
655
+ class StaticFunction : public Function {
656
+ Lambda _lambda;
783
657
 
784
- virtual ~StaticFunction() = default;
658
+ public:
659
+ StaticFunction(const Lambda& lambda) : _lambda(lambda) {}
785
660
 
786
- virtual std::shared_ptr<Function> do_clone() {
787
- auto ptr = std::make_shared<StaticFunction>(m_lambda);
788
- return std::static_pointer_cast<Function>(ptr);
789
- }
661
+ virtual ~StaticFunction() = default;
790
662
 
791
- virtual void do_call_function(vrpc::json& json) {
792
- try {
793
- vrpc::call(m_lambda(), vrpc::unpack<Args...>(json));
794
- json["data"]["r"] = nullptr;
795
- } catch (const std::exception& e) {
796
- json["data"]["e"] = std::string(e.what());
797
- }
798
- }
663
+ virtual std::shared_ptr<Function> do_clone() {
664
+ auto ptr = std::make_shared<StaticFunction>(_lambda);
665
+ return std::static_pointer_cast<Function>(ptr);
666
+ }
799
667
 
800
- virtual void do_bind_instance(const Value&) {
801
- // Nothing to bind, static function
668
+ virtual void do_call_function(json& json) {
669
+ try {
670
+ json["r"] = vrpc::call(_lambda(), vrpc::unpack<Args...>(json));
671
+ } catch (const std::exception& e) {
672
+ json["e"] = std::string(e.what());
802
673
  }
803
- };
804
-
805
- template <typename Lambda, typename ...Args>
806
- class ConstructorFunction : public Function {
807
- Lambda m_lambda;
674
+ }
808
675
 
809
- public:
676
+ virtual void do_bind_instance(const Value&) {
677
+ // Nothing to bind, static function
678
+ }
679
+ };
810
680
 
811
- ConstructorFunction(
812
- const Lambda& lambda
813
- ) : m_lambda(lambda) { }
681
+ template <typename Lambda, typename... Args>
682
+ class StaticFunction<Lambda, void, Args...> : public Function {
683
+ Lambda _lambda;
814
684
 
815
- virtual ~ConstructorFunction() = default;
685
+ public:
686
+ StaticFunction(const Lambda& lambda) : _lambda(lambda) {}
816
687
 
817
- virtual std::shared_ptr<Function> do_clone() {
818
- auto ptr = std::make_shared<ConstructorFunction>(m_lambda);
819
- return std::static_pointer_cast<Function>(ptr);
820
- }
688
+ virtual ~StaticFunction() = default;
821
689
 
822
- virtual void do_call_function(vrpc::json& json) {
823
- try {
824
- json["data"]["r"] = vrpc::call(m_lambda, vrpc::unpack<Args...>(json));
825
- } catch (const std::exception& e) {
826
- json["data"]["e"] = std::string(e.what());
827
- }
828
- }
690
+ virtual std::shared_ptr<Function> do_clone() {
691
+ auto ptr = std::make_shared<StaticFunction>(_lambda);
692
+ return std::static_pointer_cast<Function>(ptr);
693
+ }
829
694
 
830
- virtual void do_bind_instance(const Value&) {
831
- // Nothing to bind
695
+ virtual void do_call_function(json& json) {
696
+ try {
697
+ vrpc::call(_lambda(), vrpc::unpack<Args...>(json));
698
+ json["r"] = nullptr;
699
+ } catch (const std::exception& e) {
700
+ json["e"] = std::string(e.what());
832
701
  }
833
- };
702
+ }
834
703
 
835
- struct required {};
704
+ virtual void do_bind_instance(const Value&) {
705
+ // Nothing to bind, static function
706
+ }
707
+ };
836
708
 
709
+ template <typename Lambda, typename... Args>
710
+ class ConstructorFunction : public Function {
711
+ Lambda _lambda;
837
712
 
713
+ public:
714
+ ConstructorFunction(const Lambda& lambda) : _lambda(lambda) {}
838
715
 
839
- namespace detail {
840
- struct param {
841
- json j;
842
- template <typename DefaultType>
843
- param(const std::string& name,
844
- const DefaultType& default_value,
845
- const std::string& description) {
846
- // json tmp{{"t", type()}};
847
- // j["type"] = tmp["t"].type_name();
848
- j["name"] = name;
849
- j["optional"] = true;
850
- j["default"] = default_value;
851
- j["description"] = description;
852
- }
853
- param(const std::string& name,
854
- const required& default_value,
855
- const std::string& description) {
856
- // json tmp{{"t", type()}};
857
- // j["type"] = tmp["t"].type_name();
858
- j["name"] = name;
859
- j["optional"] = false;
860
- j["default"] = nullptr;
861
- j["description"] = description;
862
- }
863
- };
716
+ virtual ~ConstructorFunction() = default;
864
717
 
865
- template <typename ValueType>
866
- struct ret {
867
- json j;
868
- ret(const std::string& description) {
869
- j["type"] = json(ValueType()).type_name();
870
- j["description"] = description;
871
- }
872
- };
873
- template<>
874
- struct ret<void>{
875
- json j;
876
- ret(const std::string& description) {
877
- j["type"] = "void";
878
- j["description"] = description;
879
- }
880
- };
718
+ virtual std::shared_ptr<Function> do_clone() {
719
+ auto ptr = std::make_shared<ConstructorFunction>(_lambda);
720
+ return std::static_pointer_cast<Function>(ptr);
881
721
  }
882
722
 
883
- class LocalFactory {
884
- friend LocalFactory& detail::init<LocalFactory>();
885
- friend class Proxy;
886
- friend class MqttClient;
887
-
888
- typedef std::unordered_map<std::string, Value > StringAnyMap;
889
- typedef std::unordered_map<std::string, std::shared_ptr<Function> > StringFunctionMap;
890
- typedef std::unordered_map<std::string, StringFunctionMap> FunctionRegistry;
891
- typedef std::unordered_map<std::string, std::string > NamedInstances;
892
- typedef std::unordered_map<std::string, vrpc::json > MetaData;
893
-
894
- // Maps: class_name => function_name => functionCallback
895
- FunctionRegistry m_class_function_registry;
896
- // Maps: instanceId => function_name => functionCallback
897
- FunctionRegistry m_function_registry;
898
- // Maps: instanceId => instanceObj
899
- StringAnyMap m_instances;
900
- // Maps: instanceId => class_name
901
- NamedInstances m_named_instances;
902
- // Optional schema information
903
- MetaData m_meta_data;
904
-
905
- public:
906
-
907
- template <typename Klass, typename ...Args>
908
- static void register_constructor(const std::string& class_name) {
909
- LocalFactory::inject_create_function<Klass, Args...>(class_name);
910
- LocalFactory::inject_create_named_function<Klass, Args...>(class_name);
911
- LocalFactory::inject_get_named_function<Klass>(class_name);
912
- LocalFactory::inject_delete_function<Klass>(class_name);
723
+ virtual void do_call_function(json& json) {
724
+ try {
725
+ json["r"] = vrpc::call(_lambda, vrpc::unpack<Args...>(json));
726
+ } catch (const std::exception& e) {
727
+ json["e"] = std::string(e.what());
913
728
  }
729
+ }
914
730
 
915
- template <typename Klass,
916
- typename Func,
917
- Func f,
918
- typename Ret,
919
- typename... Args>
920
- static void register_member_function(const std::string& class_name,
921
- const std::string& function_name) {
922
- auto func = [](const std::shared_ptr<Klass>& ptr) {
923
- return vrpc::variadic_bind_member<Klass, Func, Args...>(f, ptr);
924
- };
925
- auto funcT =
926
- std::make_shared<MemberFunction<Klass, decltype(func), Ret, Args...>>(
927
- func);
928
- detail::init<LocalFactory>()
929
- .m_class_function_registry[class_name][function_name] =
930
- std::static_pointer_cast<Function>(funcT);
931
- _VRPC_DEBUG << "Registered: " << class_name << "::" << function_name
932
- << std::endl;
933
- }
731
+ virtual void do_bind_instance(const Value&) {
732
+ // Nothing to bind
733
+ }
734
+ };
735
+
736
+ struct required {};
737
+
738
+ namespace detail {
739
+ struct param {
740
+ json j;
741
+ template <typename DefaultType>
742
+ param(const std::string& name,
743
+ const DefaultType& default_value,
744
+ const std::string& description) {
745
+ // json tmp{{"t", type()}};
746
+ // j["type"] = tmp["t"].type_name();
747
+ j["name"] = name;
748
+ j["optional"] = true;
749
+ j["default"] = default_value;
750
+ j["description"] = description;
751
+ }
752
+ param(const std::string& name,
753
+ const required& default_value,
754
+ const std::string& description) {
755
+ // json tmp{{"t", type()}};
756
+ // j["type"] = tmp["t"].type_name();
757
+ j["name"] = name;
758
+ j["optional"] = false;
759
+ j["default"] = nullptr;
760
+ j["description"] = description;
761
+ }
762
+ };
763
+
764
+ template <typename ValueType>
765
+ struct ret {
766
+ json j;
767
+ ret(const std::string& description) {
768
+ j["type"] = json(ValueType()).type_name();
769
+ j["description"] = description;
770
+ }
771
+ };
772
+ template <>
773
+ struct ret<void> {
774
+ json j;
775
+ ret(const std::string& description) {
776
+ j["type"] = "void";
777
+ j["description"] = description;
778
+ }
779
+ };
780
+ } // namespace detail
781
+
782
+ class LocalFactory {
783
+ friend LocalFactory& detail::init<LocalFactory>();
784
+ friend class Proxy;
785
+ friend class MqttClient;
786
+
787
+ typedef std::unordered_map<std::string, Value> StringAnyMap;
788
+ typedef std::unordered_map<std::string, std::shared_ptr<Function>>
789
+ StringFunctionMap;
790
+ typedef std::unordered_map<std::string, StringFunctionMap> FunctionRegistry;
791
+ typedef std::unordered_map<std::string, std::string> SharedInstances;
792
+ typedef std::unordered_map<std::string, json> MetaData;
793
+
794
+ // Maps: class_name => function_name => functionCallback
795
+ FunctionRegistry _class_function_registry;
796
+ // Maps: instanceId => function_name => functionCallback
797
+ FunctionRegistry _function_registry;
798
+ // Maps: instanceId => instanceObj
799
+ StringAnyMap _instances;
800
+ // Maps: instanceId => class_name
801
+ SharedInstances _shared_instances;
802
+ // Optional schema information
803
+ MetaData _meta_data;
804
+
805
+ public:
806
+ template <typename Klass, typename... Args>
807
+ static void register_constructor(const std::string& class_name) {
808
+ LocalFactory::inject_create_isolated_function<Klass, Args...>(class_name);
809
+ LocalFactory::inject_create_shared_function<Klass, Args...>(class_name);
810
+ LocalFactory::inject_delete_function<Klass>(class_name);
811
+ }
934
812
 
935
- template <typename Func, Func f, typename Ret, typename... Args>
936
- static void register_static_function(const std::string& class_name,
937
- const std::string& function_name) {
938
- auto func = []() { return vrpc::variadic_bind<Func, Args...>(f); };
939
- auto funcT =
940
- std::make_shared<StaticFunction<decltype(func), Ret, Args...>>(func);
941
- detail::init<LocalFactory>().m_function_registry[class_name][function_name] =
942
- std::static_pointer_cast<Function>(funcT);
943
- _VRPC_DEBUG << "Registered: " << class_name << "::" << function_name
944
- << std::endl;
945
- }
813
+ template <typename Klass,
814
+ typename Func,
815
+ Func f,
816
+ typename Ret,
817
+ typename... Args>
818
+ static void register_member_function(const std::string& class_name,
819
+ const std::string& function_name) {
820
+ auto func = [](const std::shared_ptr<Klass>& ptr) {
821
+ return vrpc::variadic_bind_member<Klass, Func, Args...>(f, ptr);
822
+ };
823
+ auto funcT =
824
+ std::make_shared<MemberFunction<Klass, decltype(func), Ret, Args...>>(
825
+ func);
826
+ detail::init<LocalFactory>()
827
+ ._class_function_registry[class_name][function_name] =
828
+ std::static_pointer_cast<Function>(funcT);
829
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << function_name
830
+ << std::endl;
831
+ }
946
832
 
947
- static void register_meta_data(const std::string& class_name,
948
- const std::string& function_name,
949
- const std::string& description,
950
- const json& params,
951
- const json& ret) {
952
- LocalFactory& rf = detail::init<LocalFactory>();
953
- vrpc::json& j = rf.m_meta_data[class_name];
954
- j[function_name]["description"] = description;
955
- j[function_name]["params"] = params;
956
- j[function_name]["ret"] = ret;
957
- }
833
+ template <typename Func, Func f, typename Ret, typename... Args>
834
+ static void register_static_function(const std::string& class_name,
835
+ const std::string& function_name) {
836
+ auto func = []() { return vrpc::variadic_bind<Func, Args...>(f); };
837
+ auto funcT =
838
+ std::make_shared<StaticFunction<decltype(func), Ret, Args...>>(func);
839
+ detail::init<LocalFactory>()._function_registry[class_name][function_name] =
840
+ std::static_pointer_cast<Function>(funcT);
841
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << function_name
842
+ << std::endl;
843
+ }
958
844
 
959
- static std::vector<std::string> get_instances(const std::string& class_name) {
960
- std::vector<std::string> instances;
961
- for (const auto& kv : detail::init<LocalFactory>().m_named_instances) {
962
- if (kv.second == class_name) instances.push_back(kv.first);
963
- }
964
- return instances;
965
- }
845
+ static void register_meta_data(const std::string& class_name,
846
+ const std::string& function_name,
847
+ const std::string& description,
848
+ const json& params,
849
+ const json& ret) {
850
+ LocalFactory& rf = detail::init<LocalFactory>();
851
+ json& j = rf._meta_data[class_name];
852
+ j[function_name]["description"] = description;
853
+ j[function_name]["params"] = params;
854
+ j[function_name]["ret"] = ret;
855
+ }
966
856
 
967
- static std::vector<std::string> get_member_functions(const std::string& class_name) {
968
- std::vector<std::string> functions;
969
- const auto& it = detail::init<LocalFactory>().m_class_function_registry.find(class_name);
970
- if (it != detail::init<LocalFactory>().m_class_function_registry.end()) {
971
- for (const auto& kv : it->second) {
972
- functions.push_back(kv.first);
973
- }
974
- }
975
- return functions;
857
+ static std::vector<std::string> get_instances(const std::string& class_name) {
858
+ std::vector<std::string> instances;
859
+ for (const auto& kv : detail::init<LocalFactory>()._shared_instances) {
860
+ if (kv.second == class_name)
861
+ instances.push_back(kv.first);
976
862
  }
863
+ return instances;
864
+ }
977
865
 
978
- static std::vector<std::string> get_static_functions(
979
- const std::string& class_name
980
- ) {
981
- std::vector<std::string> functions;
982
- const auto& it = detail::init<LocalFactory>().m_function_registry.find(class_name);
983
- if (it != detail::init<LocalFactory>().m_function_registry.end()) {
984
- for (const auto& kv : it->second) {
985
- functions.push_back(kv.first);
986
- }
866
+ static std::vector<std::string> get_member_functions(
867
+ const std::string& class_name) {
868
+ std::vector<std::string> functions;
869
+ const auto& it =
870
+ detail::init<LocalFactory>()._class_function_registry.find(class_name);
871
+ if (it != detail::init<LocalFactory>()._class_function_registry.end()) {
872
+ for (const auto& kv : it->second) {
873
+ functions.push_back(kv.first);
987
874
  }
988
- return functions;
989
875
  }
876
+ return functions;
877
+ }
990
878
 
991
- static std::vector<std::string> get_classes() {
992
- std::vector<std::string> classes;
993
- for (const auto& kv : detail::init<LocalFactory>().m_class_function_registry) {
994
- classes.push_back(kv.first);
879
+ static std::vector<std::string> get_static_functions(
880
+ const std::string& class_name) {
881
+ std::vector<std::string> functions;
882
+ const auto& it =
883
+ detail::init<LocalFactory>()._function_registry.find(class_name);
884
+ if (it != detail::init<LocalFactory>()._function_registry.end()) {
885
+ for (const auto& kv : it->second) {
886
+ functions.push_back(kv.first);
995
887
  }
996
- return classes;
997
888
  }
889
+ return functions;
890
+ }
998
891
 
999
- static json get_meta_data(const std::string& class_name) {
1000
- LocalFactory& rf = detail::init<LocalFactory>();
1001
- return rf.m_meta_data[class_name];
892
+ static std::vector<std::string> get_classes() {
893
+ std::vector<std::string> classes;
894
+ for (const auto& kv :
895
+ detail::init<LocalFactory>()._class_function_registry) {
896
+ classes.push_back(kv.first);
1002
897
  }
898
+ return classes;
899
+ }
1003
900
 
1004
- static std::string call(const std::string& jsonString) {
1005
- vrpc::json json;
1006
- json = vrpc::json::parse(jsonString);
1007
- LocalFactory::call(json);
1008
- return json.dump();
1009
- }
901
+ static json get_meta_data(const std::string& class_name) {
902
+ LocalFactory& rf = detail::init<LocalFactory>();
903
+ return rf._meta_data[class_name];
904
+ }
1010
905
 
1011
- static void call(vrpc::json& json) {
1012
- const std::string& context = json["context"];
1013
- std::string function = json["method"];
1014
- vrpc::json& args = json["data"];
1015
- function += vrpc::get_signature(args);
1016
- _VRPC_DEBUG << "Calling function: " << function
1017
- << " with payload: " << args << std::endl;
1018
- auto it_t = detail::init<LocalFactory>().m_function_registry.find(context);
1019
- if (it_t != detail::init<LocalFactory>().m_function_registry.end()) {
1020
- auto it_f = it_t->second.find(function);
1021
- if (it_f != it_t->second.end()) {
1022
- it_f->second->call_function(json);
1023
- return;
1024
- }
1025
- json["data"]["e"] = "Could not find function: " + function;
906
+ static std::string call(const std::string& jsonString) {
907
+ json json;
908
+ json = json::parse(jsonString);
909
+ LocalFactory::call(json);
910
+ return json.dump();
911
+ }
912
+
913
+ static void call(json& json) {
914
+ const std::string context = json["c"].get<std::string>();
915
+ std::string function = json["f"].get<std::string>();
916
+ function += vrpc::get_signature(json["a"]);
917
+ _VRPC_DEBUG << "Calling function: " << function
918
+ << " with payload: " << json["a"] << std::endl;
919
+ auto it_t = detail::init<LocalFactory>()._function_registry.find(context);
920
+ if (it_t != detail::init<LocalFactory>()._function_registry.end()) {
921
+ auto it_f = it_t->second.find(function);
922
+ if (it_f != it_t->second.end()) {
923
+ it_f->second->call_function(json);
1026
924
  return;
1027
925
  }
1028
- json["data"]["e"] = "Could not find context: " + context;
1029
- }
1030
-
1031
- static void load_bindings(const std::string& path) {
1032
- #if defined(VRPC_WITH_DL) && !defined(_WIN32)
1033
- void* libHandle = dlopen(path.c_str(), RTLD_LAZY);
1034
- if (libHandle == 0) {
1035
- throw std::runtime_error("Problem loading bindings: " +
1036
- std::string(dlerror()));
1037
- }
1038
- #else
1039
- _VRPC_DEBUG << "Ignored call, dynamic loading is disabled" << std::endl;
1040
- #endif
926
+ json["e"] = "Could not find function: " + function;
927
+ return;
1041
928
  }
929
+ json["e"] = "Could not find context: " + context;
930
+ }
1042
931
 
1043
- private:
1044
-
1045
- LocalFactory() { }
1046
-
1047
- LocalFactory(const LocalFactory&) = default;
1048
-
1049
- virtual ~LocalFactory() = default;
1050
-
1051
- template <typename Klass>
1052
- static std::string create_instance_id(
1053
- const std::shared_ptr<Klass>& ptr
1054
- ) noexcept {
1055
- std::ostringstream ss;
1056
- ss << reinterpret_cast<std::uintptr_t> (ptr.get());
1057
- return ss.str();
932
+ static void load_bindings(const std::string& path) {
933
+ #if defined(VRPC_WITH_DL) && !defined(_WIN32)
934
+ void* libHandle = dlopen(path.c_str(), RTLD_LAZY);
935
+ if (libHandle == 0) {
936
+ throw std::runtime_error("Problem loading bindings: " +
937
+ std::string(dlerror()));
1058
938
  }
939
+ #else
940
+ _VRPC_DEBUG << "Ignored call, dynamic loading is disabled" << std::endl;
941
+ #endif
942
+ }
1059
943
 
1060
- template <typename Klass, typename ...Args>
1061
- static void inject_create_function(const std::string& class_name) {
1062
- auto func = [ = ](Args... args){
1063
- LocalFactory& rf = detail::init<LocalFactory>();
1064
- // Create instance
1065
- auto ptr = std::shared_ptr<Klass>(new Klass(args...));
1066
- // Generate instance_id
1067
- const std::string instance_id = create_instance_id(ptr);
1068
- // Bind member functions
1069
- for (auto& i : rf.m_class_function_registry[class_name]) {
1070
- auto functionCallback = i.second->clone();
1071
- functionCallback->bind_instance(ptr);
1072
- rf.m_function_registry[instance_id][i.first] = functionCallback;
1073
- }
1074
- // Keep instance alive by saving the shared_ptr
1075
- rf.m_instances[instance_id] = Value(ptr);
1076
- return instance_id;
1077
- };
1078
- auto funcT = std::make_shared<ConstructorFunction<decltype(func), Args...>>(func);
1079
- const std::string func_name("__create__" + vrpc::get_signature<Args...>());
1080
- detail::init<LocalFactory>().m_function_registry[class_name][func_name] =
1081
- std::static_pointer_cast<Function>(funcT);
1082
- _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name << std::endl;
1083
- }
1084
-
1085
- template <typename Klass, typename ...Args>
1086
- static void inject_create_named_function(const std::string& class_name) {
1087
- auto func = [ = ](const std::string& instance_id, Args... args){
1088
- LocalFactory& rf = detail::init<LocalFactory>();
1089
- const auto& it = rf.m_instances.find(instance_id);
1090
- if (it != rf.m_instances.end()) return instance_id;
1091
- // Create instance
1092
- auto ptr = std::shared_ptr<Klass>(new Klass(args...));
1093
- // Bind member functions
1094
- for (auto& i : rf.m_class_function_registry[class_name]) {
1095
- auto functionCallback = i.second->clone();
1096
- functionCallback->bind_instance(ptr);
1097
- rf.m_function_registry[instance_id][i.first] = functionCallback;
1098
- }
1099
- // Keep instance alive by saving the shared_ptr
1100
- rf.m_instances[instance_id] = Value(ptr);
1101
- // Store named instance
1102
- rf.m_named_instances.insert({instance_id, class_name});
1103
- return instance_id;
1104
- };
1105
- auto funcT = std::make_shared<ConstructorFunction<decltype(func), const std::string&, Args...>>(func);
1106
- const std::string func_name("__createNamed__" + vrpc::get_signature<std::string, Args...>());
1107
- detail::init<LocalFactory>().m_function_registry[class_name][func_name] =
1108
- std::static_pointer_cast<Function>(funcT);
1109
- _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name << std::endl;
1110
- }
1111
-
1112
- template <typename Klass>
1113
- static void inject_get_named_function(const std::string& class_name) {
1114
- auto func = [ = ](const std::string& instance_id){
1115
- LocalFactory& rf = detail::init<LocalFactory>();
1116
- const auto& it = rf.m_instances.find(instance_id);
1117
- if (it != rf.m_instances.end()) return instance_id;
1118
- throw std::runtime_error("Instance with id: " + instance_id + " does not exist");
1119
- };
1120
- auto funcT = std::make_shared<ConstructorFunction<decltype(func), const std::string& >>(func);
1121
- const std::string func_name("__getNamed__" + vrpc::get_signature<std::string>());
1122
- detail::init<LocalFactory>().m_function_registry[class_name][func_name] =
1123
- std::static_pointer_cast<Function>(funcT);
1124
- _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name << std::endl;
1125
- }
1126
-
1127
- template <typename Klass>
1128
- static void inject_delete_function(const std::string& class_name) {
1129
- auto func = [ = ](const std::string& instance_id){
1130
- LocalFactory& rf = detail::init<LocalFactory>();
1131
- const auto& it = rf.m_instances.find(instance_id);
1132
- if (it == rf.m_instances.end()) return false;
1133
- rf.m_function_registry.erase(instance_id);
1134
- rf.m_instances.erase(instance_id);
1135
- rf.m_named_instances.erase(instance_id);
1136
- return true;
1137
- };
1138
- auto funcT = std::make_shared<ConstructorFunction<decltype(func), const std::string& >>(func);
1139
- const std::string func_name("__delete__" + vrpc::get_signature<std::string>());
1140
- detail::init<LocalFactory>().m_function_registry[class_name][func_name] =
1141
- std::static_pointer_cast<Function>(funcT);
1142
- _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name << std::endl;
1143
- }
1144
- };
1145
-
1146
- namespace detail {
1147
-
1148
- template <class Klass, typename ...Args>
1149
- struct CtorRegistrar {
1150
-
1151
- CtorRegistrar(const std::string& class_name) {
1152
- LocalFactory::register_constructor<Klass, Args...> (class_name);
1153
- }
1154
- };
1155
-
1156
- template <class Klass, typename ...Args>
1157
- struct RegisterCtor {
1158
- static const CtorRegistrar<Klass, Args...> registerAs;
1159
- };
1160
-
1161
- template <class Klass, typename... Args>
1162
- struct CtorXRegistrar {
1163
- CtorXRegistrar(const std::string& class_name,
1164
- const std::string& ctor_description,
1165
- const ret<std::string>& ret,
1166
- const std::vector<param> params = {}) {
1167
- LocalFactory::register_constructor<Klass, Args...>(class_name);
1168
- const std::string ctor_name("__createNamed__" + vrpc::get_signature<std::string, Args...>());
1169
- json jp;
1170
- for (const auto& param : params) {
1171
- jp.push_back(param.j);
1172
- }
1173
- LocalFactory::register_meta_data(class_name, ctor_name,
1174
- ctor_description, jp, ret.j);
1175
- }
1176
- };
944
+ private:
945
+ LocalFactory() {}
1177
946
 
1178
- template <class Klass, typename ...Args>
1179
- struct RegisterCtorX {
1180
- static const CtorXRegistrar<Klass, Args...> registerAs;
1181
- };
947
+ LocalFactory(const LocalFactory&) = default;
1182
948
 
949
+ virtual ~LocalFactory() = default;
1183
950
 
1184
- template <class Klass, typename Func, Func f, typename Ret, typename ...Args>
1185
- struct MemberFunctionRegistrar {
951
+ template <typename Klass>
952
+ static std::string create_instance_id(
953
+ const std::shared_ptr<Klass>& ptr) noexcept {
954
+ std::ostringstream ss;
955
+ ss << reinterpret_cast<std::uintptr_t>(ptr.get());
956
+ return ss.str();
957
+ }
1186
958
 
1187
- MemberFunctionRegistrar(
1188
- const std::string& class_name,
1189
- const std::string& function_name
1190
- ) {
1191
- const std::string full_function_name(function_name +
1192
- vrpc::get_signature<Args...>());
1193
- LocalFactory::register_member_function<Klass, Func, f, Ret, Args...>(
1194
- class_name,
1195
- full_function_name
1196
- );
959
+ template <typename Klass, typename... Args>
960
+ static void inject_create_isolated_function(const std::string& class_name) {
961
+ auto func = [=](const std::string& instance_id, Args... args) {
962
+ LocalFactory& rf = detail::init<LocalFactory>();
963
+ const auto& it = rf._instances.find(instance_id);
964
+ if (it != rf._instances.end())
965
+ return instance_id;
966
+ // Create instance
967
+ auto ptr = std::shared_ptr<Klass>(new Klass(args...));
968
+ // Bind member functions
969
+ for (auto& i : rf._class_function_registry[class_name]) {
970
+ auto functionCallback = i.second->clone();
971
+ functionCallback->bind_instance(ptr);
972
+ rf._function_registry[instance_id][i.first] = functionCallback;
1197
973
  }
974
+ // Keep instance alive by saving the shared_ptr
975
+ rf._instances[instance_id] = Value(ptr);
976
+ return instance_id;
1198
977
  };
978
+ auto funcT = std::make_shared<
979
+ ConstructorFunction<decltype(func), const std::string&, Args...>>(func);
980
+ const std::string func_name("__createIsolated__" +
981
+ vrpc::get_signature<std::string, Args...>());
982
+ detail::init<LocalFactory>()._function_registry[class_name][func_name] =
983
+ std::static_pointer_cast<Function>(funcT);
984
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name
985
+ << std::endl;
986
+ }
1199
987
 
1200
- template <class Klass,
1201
- typename Func,
1202
- Func f,
1203
- typename Ret,
1204
- typename... Args>
1205
- struct MemberFunctionXRegistrar {
1206
- MemberFunctionXRegistrar(const std::string& class_name,
1207
- const std::string& function_name,
1208
- const std::string& function_description,
1209
- const ret<Ret>& ret,
1210
- const std::vector<param> params = {}) {
1211
- const std::string full_function_name(function_name +
1212
- vrpc::get_signature<Args...>());
1213
- LocalFactory::register_member_function<Klass, Func, f, Ret, Args...>(
1214
- class_name, full_function_name);
1215
- json jp;
1216
- for (const auto& param : params) {
1217
- jp.push_back(param.j);
1218
- }
1219
- LocalFactory::register_meta_data(class_name, full_function_name,
1220
- function_description, jp, ret.j);
988
+ template <typename Klass, typename... Args>
989
+ static void inject_create_shared_function(const std::string& class_name) {
990
+ auto func = [=](const std::string& instance_id, Args... args) {
991
+ LocalFactory& rf = detail::init<LocalFactory>();
992
+ const auto& it = rf._instances.find(instance_id);
993
+ if (it != rf._instances.end())
994
+ return instance_id;
995
+ // Create instance
996
+ auto ptr = std::shared_ptr<Klass>(new Klass(args...));
997
+ // Bind member functions
998
+ for (auto& i : rf._class_function_registry[class_name]) {
999
+ auto functionCallback = i.second->clone();
1000
+ functionCallback->bind_instance(ptr);
1001
+ rf._function_registry[instance_id][i.first] = functionCallback;
1221
1002
  }
1003
+ // Keep instance alive by saving the shared_ptr
1004
+ rf._instances[instance_id] = Value(ptr);
1005
+ // Store shared instance
1006
+ rf._shared_instances.insert({instance_id, class_name});
1007
+ return instance_id;
1222
1008
  };
1009
+ auto funcT = std::make_shared<
1010
+ ConstructorFunction<decltype(func), const std::string&, Args...>>(func);
1011
+ const std::string func_name("__createShared__" +
1012
+ vrpc::get_signature<std::string, Args...>());
1013
+ detail::init<LocalFactory>()._function_registry[class_name][func_name] =
1014
+ std::static_pointer_cast<Function>(funcT);
1015
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name
1016
+ << std::endl;
1017
+ }
1223
1018
 
1224
- template <class Klass, typename Func, Func f, typename Ret, typename ...Args>
1225
- struct RegisterMemberFunction {
1226
- static const MemberFunctionRegistrar<Klass, Func, f, Ret, Args...> registerAs;
1227
- };
1228
-
1229
- template <class Klass, typename Func, Func f, typename Ret, typename ...Args>
1230
- struct RegisterMemberFunctionX {
1231
- static const MemberFunctionXRegistrar<Klass, Func, f, Ret, Args...> registerAs;
1232
- };
1233
-
1234
- template <typename Func, Func f, typename Ret, typename... Args>
1235
- struct StaticFunctionRegistrar {
1236
- StaticFunctionRegistrar(const std::string& class_name,
1237
- const std::string& function_name) {
1238
- const std::string full_function_name(function_name +
1239
- vrpc::get_signature<Args...>());
1240
- LocalFactory::register_static_function<Func, f, Ret, Args...>(
1241
- class_name, full_function_name);
1242
- }
1019
+ template <typename Klass>
1020
+ static void inject_delete_function(const std::string& class_name) {
1021
+ auto func = [=](const std::string& instance_id) {
1022
+ LocalFactory& rf = detail::init<LocalFactory>();
1023
+ const auto& it = rf._instances.find(instance_id);
1024
+ if (it == rf._instances.end())
1025
+ return false;
1026
+ rf._function_registry.erase(instance_id);
1027
+ rf._instances.erase(instance_id);
1028
+ rf._shared_instances.erase(instance_id);
1029
+ return true;
1243
1030
  };
1031
+ auto funcT = std::make_shared<
1032
+ ConstructorFunction<decltype(func), const std::string&>>(func);
1033
+ const std::string func_name("__delete__" +
1034
+ vrpc::get_signature<std::string>());
1035
+ detail::init<LocalFactory>()._function_registry[class_name][func_name] =
1036
+ std::static_pointer_cast<Function>(funcT);
1037
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name
1038
+ << std::endl;
1039
+ }
1040
+ };
1244
1041
 
1245
- template <typename Func, Func f, typename Ret, typename... Args>
1246
- struct RegisterStaticFunction {
1247
- static const StaticFunctionRegistrar<Func, f, Ret, Args...> registerAs;
1248
- };
1042
+ namespace detail {
1249
1043
 
1250
- template <typename Func, Func f, typename Ret, typename... Args>
1251
- struct StaticFunctionXRegistrar {
1252
- StaticFunctionXRegistrar(const std::string& class_name,
1253
- const std::string& function_name,
1254
- const std::string& function_description,
1255
- const ret<Ret>& ret,
1256
- const std::vector<param> params = {}) {
1257
- const std::string full_function_name(function_name +
1258
- vrpc::get_signature<Args...>());
1259
- LocalFactory::register_static_function<Func, f, Ret, Args...>(
1260
- class_name, full_function_name);
1261
- json jp;
1262
- for (const auto& param : params) {
1263
- jp.push_back(param.j);
1264
- }
1265
- LocalFactory::register_meta_data(class_name, full_function_name,
1266
- function_description, jp, ret.j);
1267
- }
1268
- };
1044
+ template <class Klass, typename... Args>
1045
+ struct CtorRegistrar {
1046
+ CtorRegistrar(const std::string& class_name) {
1047
+ LocalFactory::register_constructor<Klass, Args...>(class_name);
1048
+ }
1049
+ };
1050
+
1051
+ template <class Klass, typename... Args>
1052
+ struct RegisterCtor {
1053
+ static const CtorRegistrar<Klass, Args...> registerAs;
1054
+ };
1055
+
1056
+ template <class Klass, typename... Args>
1057
+ struct CtorXRegistrar {
1058
+ CtorXRegistrar(const std::string& class_name,
1059
+ const std::string& ctor_description,
1060
+ const ret<std::string>& ret,
1061
+ const std::vector<param> params = {}) {
1062
+ LocalFactory::register_constructor<Klass, Args...>(class_name);
1063
+ const std::string ctor_name("__createShared__" +
1064
+ vrpc::get_signature<std::string, Args...>());
1065
+ json jp;
1066
+ for (const auto& param : params) {
1067
+ jp.push_back(param.j);
1068
+ }
1069
+ LocalFactory::register_meta_data(class_name, ctor_name, ctor_description,
1070
+ jp, ret.j);
1071
+ }
1072
+ };
1073
+
1074
+ template <class Klass, typename... Args>
1075
+ struct RegisterCtorX {
1076
+ static const CtorXRegistrar<Klass, Args...> registerAs;
1077
+ };
1078
+
1079
+ template <class Klass, typename Func, Func f, typename Ret, typename... Args>
1080
+ struct MemberFunctionRegistrar {
1081
+ MemberFunctionRegistrar(const std::string& class_name,
1082
+ const std::string& function_name) {
1083
+ const std::string full_function_name(function_name +
1084
+ vrpc::get_signature<Args...>());
1085
+ LocalFactory::register_member_function<Klass, Func, f, Ret, Args...>(
1086
+ class_name, full_function_name);
1087
+ }
1088
+ };
1089
+
1090
+ template <class Klass, typename Func, Func f, typename Ret, typename... Args>
1091
+ struct MemberFunctionXRegistrar {
1092
+ MemberFunctionXRegistrar(const std::string& class_name,
1093
+ const std::string& function_name,
1094
+ const std::string& function_description,
1095
+ const ret<Ret>& ret,
1096
+ const std::vector<param> params = {}) {
1097
+ const std::string full_function_name(function_name +
1098
+ vrpc::get_signature<Args...>());
1099
+ LocalFactory::register_member_function<Klass, Func, f, Ret, Args...>(
1100
+ class_name, full_function_name);
1101
+ json jp;
1102
+ for (const auto& param : params) {
1103
+ jp.push_back(param.j);
1104
+ }
1105
+ LocalFactory::register_meta_data(class_name, full_function_name,
1106
+ function_description, jp, ret.j);
1107
+ }
1108
+ };
1109
+
1110
+ template <class Klass, typename Func, Func f, typename Ret, typename... Args>
1111
+ struct RegisterMemberFunction {
1112
+ static const MemberFunctionRegistrar<Klass, Func, f, Ret, Args...> registerAs;
1113
+ };
1114
+
1115
+ template <class Klass, typename Func, Func f, typename Ret, typename... Args>
1116
+ struct RegisterMemberFunctionX {
1117
+ static const MemberFunctionXRegistrar<Klass, Func, f, Ret, Args...>
1118
+ registerAs;
1119
+ };
1120
+
1121
+ template <typename Func, Func f, typename Ret, typename... Args>
1122
+ struct StaticFunctionRegistrar {
1123
+ StaticFunctionRegistrar(const std::string& class_name,
1124
+ const std::string& function_name) {
1125
+ const std::string full_function_name(function_name +
1126
+ vrpc::get_signature<Args...>());
1127
+ LocalFactory::register_static_function<Func, f, Ret, Args...>(
1128
+ class_name, full_function_name);
1129
+ }
1130
+ };
1131
+
1132
+ template <typename Func, Func f, typename Ret, typename... Args>
1133
+ struct RegisterStaticFunction {
1134
+ static const StaticFunctionRegistrar<Func, f, Ret, Args...> registerAs;
1135
+ };
1136
+
1137
+ template <typename Func, Func f, typename Ret, typename... Args>
1138
+ struct StaticFunctionXRegistrar {
1139
+ StaticFunctionXRegistrar(const std::string& class_name,
1140
+ const std::string& function_name,
1141
+ const std::string& function_description,
1142
+ const ret<Ret>& ret,
1143
+ const std::vector<param> params = {}) {
1144
+ const std::string full_function_name(function_name +
1145
+ vrpc::get_signature<Args...>());
1146
+ LocalFactory::register_static_function<Func, f, Ret, Args...>(
1147
+ class_name, full_function_name);
1148
+ json jp;
1149
+ for (const auto& param : params) {
1150
+ jp.push_back(param.j);
1151
+ }
1152
+ LocalFactory::register_meta_data(class_name, full_function_name,
1153
+ function_description, jp, ret.j);
1154
+ }
1155
+ };
1269
1156
 
1270
- template <typename Func, Func f, typename Ret, typename... Args>
1271
- struct RegisterStaticFunctionX {
1272
- static const StaticFunctionXRegistrar<Func, f, Ret, Args...> registerAs;
1273
- };
1274
- } // namespace detail
1157
+ template <typename Func, Func f, typename Ret, typename... Args>
1158
+ struct RegisterStaticFunctionX {
1159
+ static const StaticFunctionXRegistrar<Func, f, Ret, Args...> registerAs;
1160
+ };
1161
+ } // namespace detail
1275
1162
 
1276
- // ####################### Macro utility #######################
1163
+ // ####################### Macro utility #######################
1277
1164
 
1278
1165
  #define CAT(A, B) A##B
1279
1166
  #define SELECT(NAME, NUM) CAT(_##NAME##_, NUM)
@@ -1298,7 +1185,7 @@ namespace vrpc {
1298
1185
  #define VRPC_STATIC_FUNCTION_X(...) \
1299
1186
  VA_SELECT(VRPC_STATIC_FUNCTION_X, __VA_ARGS__)
1300
1187
 
1301
- // deprecate
1188
+ // deprecate
1302
1189
  #define VRPC_MEMBER_FUNCTION_CONST(...) \
1303
1190
  VA_SELECT(VRPC_CONST_MEMBER_FUNCTION, __VA_ARGS__)
1304
1191
  #define VRPC_VOID_MEMBER_FUNCTION(...) \
@@ -1308,17 +1195,18 @@ namespace vrpc {
1308
1195
  #define VRPC_VOID_STATIC_FUNCTION(...) \
1309
1196
  VA_SELECT(VRPC_VOID_STATIC_FUNCTION, __VA_ARGS__)
1310
1197
 
1311
- // ####################### Callbacks #######################
1198
+ // ####################### Callbacks #######################
1312
1199
 
1313
- #define VRPC_CALLBACK( ... ) const std::function<void (__VA_ARGS__)>&
1200
+ #define VRPC_CALLBACK(...) const std::function<void(__VA_ARGS__)>&
1314
1201
 
1315
- // ####################### Constructors #######################
1202
+ // ####################### Constructors #######################
1316
1203
 
1317
1204
  #define _VRPC_CTOR_RET_DESC "returns the id of the created instance"
1318
1205
 
1319
- #define _VRPC_CTOR_VA_ARGS(Klass, ...) \
1320
- template<> const vrpc::detail::CtorRegistrar<Klass, __VA_ARGS__> \
1321
- vrpc::detail::RegisterCtor<Klass, __VA_ARGS__>::registerAs(#Klass);
1206
+ #define _VRPC_CTOR_VA_ARGS(Klass, ...) \
1207
+ template <> \
1208
+ const vrpc::detail::CtorRegistrar<Klass, __VA_ARGS__> \
1209
+ vrpc::detail::RegisterCtor<Klass, __VA_ARGS__>::registerAs(#Klass);
1322
1210
 
1323
1211
  #define _VRPC_CTOR_1(Klass) \
1324
1212
  template <> \
@@ -1408,13 +1296,13 @@ namespace vrpc {
1408
1296
  {A5Name, A5Default, A5Desc}, \
1409
1297
  {A6Name, A6Default, A6Desc}});
1410
1298
 
1411
- // deprecate
1299
+ // deprecate
1412
1300
  #define VRPC_VOID_CTOR(Klass) \
1413
1301
  template <> \
1414
1302
  const vrpc::detail::CtorRegistrar<Klass> \
1415
1303
  vrpc::detail::RegisterCtor<Klass>::registerAs(#Klass);
1416
1304
 
1417
- // ####################### Zero arguments #######################
1305
+ // ####################### Zero arguments #######################
1418
1306
 
1419
1307
  #define _VRPC_MEMBER_FUNCTION_3(Klass, Ret, Function) \
1420
1308
  template <> \
@@ -1484,7 +1372,7 @@ namespace vrpc {
1484
1372
  #define _VRPC_VOID_STATIC_FUNCTION_2(Klass, Function) \
1485
1373
  _VRPC_STATIC_FUNCTION_3(Klass, void, Function)
1486
1374
 
1487
- // ####################### One argument #######################
1375
+ // ####################### One argument #######################
1488
1376
 
1489
1377
  #define _VRPC_MEMBER_FUNCTION_4(Klass, Ret, Function, A1) \
1490
1378
  template <> \
@@ -1566,7 +1454,7 @@ namespace vrpc {
1566
1454
  #define _VRPC_VOID_STATIC_FUNCTION_3(Klass, Function, A1) \
1567
1455
  _VRPC_STATIC_FUNCTION_4(Klass, void, Function, A1)
1568
1456
 
1569
- // ####################### Two arguments #######################
1457
+ // ####################### Two arguments #######################
1570
1458
 
1571
1459
  #define _VRPC_MEMBER_FUNCTION_5(Klass, Ret, Function, A1, A2) \
1572
1460
  template <> \
@@ -1586,8 +1474,8 @@ namespace vrpc {
1586
1474
  &Klass::Function, Ret, A1, A2> \
1587
1475
  vrpc::detail::RegisterMemberFunction< \
1588
1476
  Klass, \
1589
- decltype( \
1590
- static_cast<Ret (Klass::*)(A1, A2) const>(&Klass::Function)), \
1477
+ decltype(static_cast<Ret (Klass::*)(A1, A2) const>( \
1478
+ &Klass::Function)), \
1591
1479
  &Klass::Function, Ret, A1, A2>::registerAs(#Klass, #Function);
1592
1480
 
1593
1481
  #define _VRPC_STATIC_FUNCTION_5(Klass, Ret, Function, A1, A2) \
@@ -1626,8 +1514,8 @@ namespace vrpc {
1626
1514
  &Klass::Function, Ret, A1, A2> \
1627
1515
  vrpc::detail::RegisterMemberFunctionX< \
1628
1516
  Klass, \
1629
- decltype( \
1630
- static_cast<Ret (Klass::*)(A1, A2) const>(&Klass::Function)), \
1517
+ decltype(static_cast<Ret (Klass::*)(A1, A2) const>( \
1518
+ &Klass::Function)), \
1631
1519
  &Klass::Function, Ret, A1, A2>::registerAs(#Klass, #Function, \
1632
1520
  FunctionDesc, {RetDesc}, \
1633
1521
  {{A1Name, A1Default, \
@@ -1660,7 +1548,7 @@ namespace vrpc {
1660
1548
  #define _VRPC_VOID_STATIC_FUNCTION_4(Klass, Function, A1, A2) \
1661
1549
  _VRPC_STATIC_FUNCTION_5(Klass, void, Function, A1, A2)
1662
1550
 
1663
- // ####################### Three arguments #######################
1551
+ // ####################### Three arguments #######################
1664
1552
 
1665
1553
  #define _VRPC_MEMBER_FUNCTION_6(Klass, Ret, Function, A1, A2, A3) \
1666
1554
  template <> \
@@ -1673,17 +1561,17 @@ namespace vrpc {
1673
1561
  decltype(static_cast<Ret (Klass::*)(A1, A2, A3)>(&Klass::Function)), \
1674
1562
  &Klass::Function, Ret, A1, A2, A3>::registerAs(#Klass, #Function);
1675
1563
 
1676
- #define _VRPC_CONST_MEMBER_FUNCTION_6(Klass, Ret, Function, A1, A2, A3) \
1677
- template <> \
1678
- const vrpc::detail::MemberFunctionRegistrar< \
1679
- Klass, \
1680
- decltype( \
1681
- static_cast<Ret (Klass::*)(A1, A2, A3) const>(&Klass::Function)), \
1682
- &Klass::Function, Ret, A1, A2, A3> \
1683
- vrpc::detail::RegisterMemberFunction< \
1684
- Klass, \
1685
- decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1686
- &Klass::Function)), \
1564
+ #define _VRPC_CONST_MEMBER_FUNCTION_6(Klass, Ret, Function, A1, A2, A3) \
1565
+ template <> \
1566
+ const vrpc::detail::MemberFunctionRegistrar< \
1567
+ Klass, \
1568
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1569
+ &Klass::Function)), \
1570
+ &Klass::Function, Ret, A1, A2, A3> \
1571
+ vrpc::detail::RegisterMemberFunction< \
1572
+ Klass, \
1573
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1574
+ &Klass::Function)), \
1687
1575
  &Klass::Function, Ret, A1, A2, A3>::registerAs(#Klass, #Function);
1688
1576
 
1689
1577
  #define _VRPC_STATIC_FUNCTION_6(Klass, Ret, Function, A1, A2, A3) \
@@ -1712,23 +1600,23 @@ namespace vrpc {
1712
1600
  {A2Name, A2Default, A2Desc}, \
1713
1601
  {A3Name, A3Default, A3Desc}});
1714
1602
 
1715
- #define _VRPC_CONST_MEMBER_FUNCTION_X_17( \
1716
- Klass, Ret, RetDesc, Function, FunctionDesc, A1, A1Name, A1Default, \
1717
- A1Desc, A2, A2Name, A2Default, A2Desc, A3, A3Name, A3Default, A3Desc) \
1718
- template <> \
1719
- const vrpc::detail::MemberFunctionXRegistrar< \
1720
- Klass, \
1721
- decltype( \
1722
- static_cast<Ret (Klass::*)(A1, A2, A3) const>(&Klass::Function)), \
1723
- &Klass::Function, Ret, A1, A2, A3> \
1724
- vrpc::detail::RegisterMemberFunctionX< \
1725
- Klass, \
1726
- decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1727
- &Klass::Function)), \
1728
- &Klass::Function, Ret, A1, A2, \
1729
- A3>::registerAs(#Klass, #Function, FunctionDesc, {RetDesc}, \
1730
- {{A1Name, A1Default, A1Desc}, \
1731
- {A2Name, A2Default, A2Desc}, \
1603
+ #define _VRPC_CONST_MEMBER_FUNCTION_X_17( \
1604
+ Klass, Ret, RetDesc, Function, FunctionDesc, A1, A1Name, A1Default, \
1605
+ A1Desc, A2, A2Name, A2Default, A2Desc, A3, A3Name, A3Default, A3Desc) \
1606
+ template <> \
1607
+ const vrpc::detail::MemberFunctionXRegistrar< \
1608
+ Klass, \
1609
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1610
+ &Klass::Function)), \
1611
+ &Klass::Function, Ret, A1, A2, A3> \
1612
+ vrpc::detail::RegisterMemberFunctionX< \
1613
+ Klass, \
1614
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1615
+ &Klass::Function)), \
1616
+ &Klass::Function, Ret, A1, A2, \
1617
+ A3>::registerAs(#Klass, #Function, FunctionDesc, {RetDesc}, \
1618
+ {{A1Name, A1Default, A1Desc}, \
1619
+ {A2Name, A2Default, A2Desc}, \
1732
1620
  {A3Name, A3Default, A3Desc}});
1733
1621
 
1734
1622
  #define _VRPC_STATIC_FUNCTION_X_17( \
@@ -1755,7 +1643,7 @@ namespace vrpc {
1755
1643
  #define _VRPC_VOID_STATIC_FUNCTION_5(Klass, Function, A1, A2, A3) \
1756
1644
  _VRPC_STATIC_FUNCTION_6(Klass, void, Function, A1, A2, A3)
1757
1645
 
1758
- // ####################### Four arguments #######################
1646
+ // ####################### Four arguments #######################
1759
1647
 
1760
1648
  #define _VRPC_MEMBER_FUNCTION_7(Klass, Ret, Function, A1, A2, A3, A4) \
1761
1649
  template <> \
@@ -1765,8 +1653,8 @@ namespace vrpc {
1765
1653
  &Klass::Function, Ret, A1, A2, A3, A4> \
1766
1654
  vrpc::detail::RegisterMemberFunction< \
1767
1655
  Klass, \
1768
- decltype( \
1769
- static_cast<Ret (Klass::*)(A1, A2, A3, A4)>(&Klass::Function)), \
1656
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4)>( \
1657
+ &Klass::Function)), \
1770
1658
  &Klass::Function, Ret, A1, A2, A3, A4>::registerAs(#Klass, \
1771
1659
  #Function);
1772
1660
 
@@ -1805,8 +1693,8 @@ namespace vrpc {
1805
1693
  &Klass::Function, Ret, A1, A2, A3, A4> \
1806
1694
  vrpc::detail::RegisterMemberFunctionX< \
1807
1695
  Klass, \
1808
- decltype( \
1809
- static_cast<Ret (Klass::*)(A1, A2, A3, A4)>(&Klass::Function)), \
1696
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4)>( \
1697
+ &Klass::Function)), \
1810
1698
  &Klass::Function, Ret, A1, A2, A3, \
1811
1699
  A4>::registerAs(#Klass, #Function, FunctionDesc, {RetDesc}, \
1812
1700
  {{A1Name, A1Default, A1Desc}, \
@@ -1861,20 +1749,20 @@ namespace vrpc {
1861
1749
  #define _VRPC_VOID_STATIC_FUNCTION_6(Klass, Function, A1, A2, A3, A4) \
1862
1750
  _VRPC_STATIC_FUNCTION_7(Klass, void, Function, A1, A2, A3, A4)
1863
1751
 
1864
- // ####################### Five arguments #######################
1752
+ // ####################### Five arguments #######################
1865
1753
 
1866
- #define _VRPC_MEMBER_FUNCTION_8(Klass, Ret, Function, A1, A2, A3, A4, A5) \
1867
- template <> \
1868
- const vrpc::detail::MemberFunctionRegistrar< \
1869
- Klass, \
1870
- decltype( \
1871
- static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>(&Klass::Function)), \
1872
- &Klass::Function, Ret, A1, A2, A3, A4, A5> \
1873
- vrpc::detail::RegisterMemberFunction< \
1874
- Klass, \
1875
- decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>( \
1876
- &Klass::Function)), \
1877
- &Klass::Function, Ret, A1, A2, A3, A4, A5>::registerAs(#Klass, \
1754
+ #define _VRPC_MEMBER_FUNCTION_8(Klass, Ret, Function, A1, A2, A3, A4, A5) \
1755
+ template <> \
1756
+ const vrpc::detail::MemberFunctionRegistrar< \
1757
+ Klass, \
1758
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>( \
1759
+ &Klass::Function)), \
1760
+ &Klass::Function, Ret, A1, A2, A3, A4, A5> \
1761
+ vrpc::detail::RegisterMemberFunction< \
1762
+ Klass, \
1763
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>( \
1764
+ &Klass::Function)), \
1765
+ &Klass::Function, Ret, A1, A2, A3, A4, A5>::registerAs(#Klass, \
1878
1766
  #Function);
1879
1767
 
1880
1768
  #define _VRPC_CONST_MEMBER_FUNCTION_8(Klass, Ret, Function, A1, A2, A3, A4, \
@@ -1909,8 +1797,8 @@ namespace vrpc {
1909
1797
  template <> \
1910
1798
  const vrpc::detail::MemberFunctionXRegistrar< \
1911
1799
  Klass, \
1912
- decltype( \
1913
- static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>(&Klass::Function)), \
1800
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>( \
1801
+ &Klass::Function)), \
1914
1802
  &Klass::Function, Ret, A1, A2, A3, A4, A5> \
1915
1803
  vrpc::detail::RegisterMemberFunctionX< \
1916
1804
  Klass, \
@@ -1974,7 +1862,7 @@ namespace vrpc {
1974
1862
  #define _VRPC_VOID_STATIC_FUNCTION_7(Klass, Function, A1, A2, A3, A4, A5) \
1975
1863
  _VRPC_STATIC_FUNCTION_8(Klass, void, Function, A1, A2, A3, A4, A5)
1976
1864
 
1977
- // ####################### Six arguments #######################
1865
+ // ####################### Six arguments #######################
1978
1866
 
1979
1867
  #define _VRPC_MEMBER_FUNCTION_9(Klass, Ret, Function, A1, A2, A3, A4, A5, A6) \
1980
1868
  template <> \
@@ -2011,8 +1899,8 @@ namespace vrpc {
2011
1899
  decltype(static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>(Klass::Function)), \
2012
1900
  &Klass::Function, Ret, A1, A2, A3, A4, A5, A6> \
2013
1901
  vrpc::detail::RegisterStaticFunction< \
2014
- decltype( \
2015
- static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>(Klass::Function)), \
1902
+ decltype(static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>( \
1903
+ Klass::Function)), \
2016
1904
  &Klass::Function, Ret, A1, A2, A3, A4, A5, \
2017
1905
  A6>::registerAs(#Klass, #Function);
2018
1906
 
@@ -2074,8 +1962,8 @@ namespace vrpc {
2074
1962
  decltype(static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>(Klass::Function)), \
2075
1963
  &Klass::Function, Ret, A1, A2, A3, A4, A5, A6> \
2076
1964
  vrpc::detail::RegisterStaticFunctionX< \
2077
- decltype( \
2078
- static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>(Klass::Function)), \
1965
+ decltype(static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>( \
1966
+ Klass::Function)), \
2079
1967
  &Klass::Function, Ret, A1, A2, A3, A4, A5, \
2080
1968
  A6>::registerAs(#Klass, #Function, FunctionDesc, {RetDesc}, \
2081
1969
  {{A1Name, A1Default, A1Desc}, \
@@ -2095,6 +1983,6 @@ namespace vrpc {
2095
1983
  #define _VRPC_VOID_STATIC_FUNCTION_8(Klass, Function, A1, A2, A3, A4, A5, A6) \
2096
1984
  _VRPC_STATIC_FUNCTION_9(Klass, void, Function, A1, A2, A3, A4, A5, A6)
2097
1985
 
2098
- } // namespace vrpc
1986
+ } // namespace vrpc
2099
1987
 
2100
1988
  #endif