vrpc 2.4.0 → 3.0.0-alpha.1

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.
@@ -16,7 +16,8 @@ Author: Dr. Burkhard C. Heisen (https://github.com/bheisen/vrpc)
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 - 2021 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,1127 @@ 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 4
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
+ signature += j["t"].type_name();
377
+ return get_signature<I + 1, Args...>(signature, t);
378
+ }
379
+ } // namespace detail
380
+
381
+ template <typename... Args>
382
+ inline std::string get_signature() {
383
+ std::string signature;
384
+ detail::get_signature(
385
+ signature, std::tuple<typename std::remove_reference<Args>::type...>());
386
+ return signature.empty() ? signature : "-" + signature;
387
+ }
542
388
 
543
- void clear() noexcept {
544
- Value().swap(*this);
545
- }
389
+ inline std::string get_signature(const json& json) {
390
+ std::string signature;
391
+ for (const auto& it : json) {
392
+ signature += it.type_name();
393
+ }
394
+ return signature.empty() ? signature : "-" + signature;
395
+ }
546
396
 
547
- std::type_index type() const noexcept {
548
- static std::type_index void_type(typeid (void));
549
- return content ? content->type() : void_type;
550
- }
397
+ namespace detail {
551
398
 
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
- }
399
+ template <typename T>
400
+ struct is_shared_ptr : std::false_type {};
558
401
 
559
- private: // functions
402
+ template <typename T>
403
+ struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
404
+ } // namespace detail
560
405
 
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
- }
406
+ // Value class
407
+ class Value {
408
+ public:
409
+ Value() noexcept : content(0) {}
567
410
 
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
- }
411
+ template <typename T>
412
+ Value(const T& value)
413
+ : content(new holder<
414
+ typename std::remove_cv<typename std::decay<T>::type>::type>(
415
+ value)) {}
574
416
 
575
- private: // types
417
+ Value(const char* const& value) : Value(std::string(value)) {}
576
418
 
577
- class placeholder {
578
- public: // structors
419
+ /// Copy constructor
420
+ Value(const Value& other)
421
+ : content(other.content ? other.content->clone() : 0) {}
579
422
 
580
- virtual ~placeholder() { }
423
+ /// Move constructor
424
+ Value(Value&& other) : content(other.content) { other.content = 0; }
581
425
 
582
- public: // queries
426
+ template <typename T>
427
+ Value(T&& value,
428
+ typename std::enable_if<!std::is_same<Value&, T>::value>::type* = 0,
429
+ typename std::enable_if<!std::is_const<T>::value>::type* = 0,
430
+ typename std::enable_if<!detail::is_shared_ptr<T>::value>::type* = 0)
431
+ : content(new holder<
432
+ typename std::remove_cv<typename std::decay<T>::type>::type>(
433
+ std::forward<T>(value))) {}
583
434
 
584
- virtual std::type_index type() const noexcept = 0;
435
+ ~Value() noexcept { delete content; }
585
436
 
586
- virtual placeholder* clone() const = 0;
587
- };
437
+ public: // functions
438
+ Value& swap(Value& rhs) noexcept {
439
+ std::swap(content, rhs.content);
440
+ return *this;
441
+ }
588
442
 
589
- template<typename T>
590
- class holder : public placeholder {
591
- public: // structors
443
+ Value& operator=(const Value& rhs) {
444
+ Value(rhs).swap(*this);
445
+ return *this;
446
+ }
592
447
 
593
- holder(const T& value)
594
- : held(new T(value)) { }
448
+ Value& operator=(Value&& rhs) noexcept {
449
+ rhs.swap(*this);
450
+ Value().swap(rhs);
451
+ return *this;
452
+ }
595
453
 
596
- holder(T&& value)
597
- : held(new T(static_cast<T&& > (value))) { }
454
+ template <typename T>
455
+ Value& operator=(T&& rhs) {
456
+ Value(static_cast<T&&>(rhs)).swap(*this);
457
+ return *this;
458
+ }
598
459
 
460
+ Value& operator=(const char* const& rhs) {
461
+ Value(std::string(rhs)).swap(*this);
462
+ return *this;
463
+ }
599
464
 
600
- public: // queries
465
+ // NOTE: Windows compiler is broken here
466
+ // template <typename T>
467
+ // operator const T&() const {
468
+ // return const_cast<Value*> (this)->template get<T>();
469
+ // }
470
+
471
+ // template <typename T>
472
+ // operator T() const {
473
+ // return const_cast<Value*> (this)->template get<T>();
474
+ // }
475
+
476
+ template <typename T>
477
+ T& operator=(T& rhs) {
478
+ Value(rhs).swap(*this);
479
+ return *this;
480
+ }
601
481
 
602
- virtual std::type_index type() const noexcept {
603
- return std::type_index(typeid (T));
604
- }
482
+ bool empty() const noexcept { return !content; }
605
483
 
606
- virtual placeholder* clone() const {
607
- // This copies a std::shared_ptr!
608
- return new holder(*held);
609
- }
484
+ void clear() noexcept { Value().swap(*this); }
610
485
 
611
- holder& operator=(const holder&) = delete;
486
+ std::type_index type() const noexcept {
487
+ static std::type_index void_type(typeid(void));
488
+ return content ? content->type() : void_type;
489
+ }
612
490
 
613
- public: // representation
491
+ template <typename T>
492
+ inline const T& get() const {
493
+ // TODO Check type correctness here
494
+ // TODO implement by specialization and not by overload
495
+ return _get<T>(typename detail::is_shared_ptr<T>::type());
496
+ }
614
497
 
615
- std::shared_ptr<T> held;
498
+ private: // functions
499
+ template <typename T>
500
+ inline const T& _get(const std::true_type&) const {
501
+ return static_cast<holder<
502
+ typename std::remove_cv<typename T::element_type>::type>*>(content)
503
+ ->held;
504
+ }
616
505
 
617
- };
506
+ template <typename T>
507
+ inline const T& _get(const std::false_type&) const {
508
+ return *(
509
+ static_cast<holder<typename std::remove_cv<T>::type>*>(content)->held);
510
+ }
618
511
 
619
- template <typename T>
620
- class holder<std::shared_ptr<T> > : public placeholder {
621
- public:
512
+ private: // types
513
+ class placeholder {
514
+ public: // structors
515
+ virtual ~placeholder() {}
622
516
 
623
- holder(const std::shared_ptr<T>& value)
624
- : held(value) { }
517
+ public: // queries
518
+ virtual std::type_index type() const noexcept = 0;
625
519
 
626
- public: // queries
520
+ virtual placeholder* clone() const = 0;
521
+ };
627
522
 
628
- virtual std::type_index type() const noexcept {
629
- return std::type_index(typeid (T));
630
- }
523
+ template <typename T>
524
+ class holder : public placeholder {
525
+ public: // structors
526
+ holder(const T& value) : held(new T(value)) {}
631
527
 
632
- virtual placeholder* clone() const {
633
- // This copies a std::shared_ptr!
634
- return new holder(held);
635
- }
528
+ holder(T&& value) : held(new T(static_cast<T&&>(value))) {}
636
529
 
637
- holder& operator=(const holder&) = delete;
530
+ public: // queries
531
+ virtual std::type_index type() const noexcept {
532
+ return std::type_index(typeid(T));
533
+ }
638
534
 
639
- public: // representation
535
+ virtual placeholder* clone() const {
536
+ // This copies a std::shared_ptr!
537
+ return new holder(*held);
538
+ }
640
539
 
641
- std::shared_ptr<T> held;
642
- };
540
+ holder& operator=(const holder&) = delete;
643
541
 
644
- placeholder* content;
542
+ public: // representation
543
+ std::shared_ptr<T> held;
645
544
  };
646
545
 
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() { }
546
+ template <typename T>
547
+ class holder<std::shared_ptr<T>> : public placeholder {
548
+ public:
549
+ holder(const std::shared_ptr<T>& value) : held(value) {}
655
550
 
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));
551
+ public: // queries
552
+ virtual std::type_index type() const noexcept {
553
+ return std::type_index(typeid(T));
661
554
  }
662
555
 
663
- void call_function(vrpc::json& json) {
664
- this->do_call_function(json);
556
+ virtual placeholder* clone() const {
557
+ // This copies a std::shared_ptr!
558
+ return new holder(held);
665
559
  }
666
560
 
667
- std::shared_ptr<Function> clone() {
668
- return this->do_clone();
669
- }
561
+ holder& operator=(const holder&) = delete;
670
562
 
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;
563
+ public: // representation
564
+ std::shared_ptr<T> held;
676
565
  };
677
566
 
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:
567
+ placeholder* content;
568
+ };
684
569
 
685
- MemberFunction(
686
- const Lambda& lambda
687
- ) : m_lambda(lambda) { }
570
+ inline bool operator==(const Value& lhs, const char& rhs) {
571
+ return lhs.get<char>() == rhs;
572
+ }
688
573
 
689
- virtual ~MemberFunction() = default;
574
+ class Function {
575
+ public:
576
+ Function() {}
690
577
 
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
- }
578
+ virtual ~Function() {}
695
579
 
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
- }
580
+ template <typename T>
581
+ void bind_instance(const std::shared_ptr<T>& instance) {
582
+ this->do_bind_instance(Value(instance));
583
+ }
706
584
 
707
- virtual void do_bind_instance(const Value& instance) {
708
- m_ptr = instance.get<std::shared_ptr<Klass> >();
709
- }
710
- };
585
+ void call_function(json& json) { this->do_call_function(json); }
711
586
 
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;
587
+ std::shared_ptr<Function> clone() { return this->do_clone(); }
716
588
 
717
- public:
589
+ protected:
590
+ virtual void do_bind_instance(const Value& instance) = 0;
591
+ virtual void do_call_function(json& json) = 0;
592
+ virtual std::shared_ptr<Function> do_clone() = 0;
593
+ };
718
594
 
719
- MemberFunction(
720
- const Lambda& lambda
721
- ) : m_lambda(lambda) { }
595
+ template <typename Klass, typename Lambda, typename Ret, typename... Args>
596
+ class MemberFunction : public Function {
597
+ Lambda _lambda;
598
+ std::shared_ptr<Klass> _ptr;
722
599
 
723
- virtual ~MemberFunction() = default;
600
+ public:
601
+ MemberFunction(const Lambda& lambda) : _lambda(lambda) {}
724
602
 
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
- }
603
+ virtual ~MemberFunction() = default;
729
604
 
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
- }
605
+ virtual std::shared_ptr<Function> do_clone() {
606
+ auto ptr = std::make_shared<MemberFunction>(_lambda);
607
+ return std::static_pointer_cast<Function>(ptr);
608
+ }
738
609
 
739
- virtual void do_bind_instance(const Value& instance) {
740
- m_ptr = instance.get<std::shared_ptr<Klass> >();
610
+ virtual void do_call_function(json& json) {
611
+ try {
612
+ json["r"] = vrpc::call(_lambda(_ptr), vrpc::unpack<Args...>(json));
613
+ } catch (const std::exception& e) {
614
+ json["e"] = std::string(e.what());
741
615
  }
742
- };
743
-
744
- template <typename Lambda, typename Ret, typename ...Args>
745
- class StaticFunction : public Function {
746
- Lambda m_lambda;
616
+ }
747
617
 
748
- public:
618
+ virtual void do_bind_instance(const Value& instance) {
619
+ _ptr = instance.get<std::shared_ptr<Klass>>();
620
+ }
621
+ };
749
622
 
750
- StaticFunction(
751
- const Lambda& lambda
752
- ) : m_lambda(lambda) { }
623
+ template <typename Klass, typename Lambda, typename... Args>
624
+ class MemberFunction<Klass, Lambda, void, Args...> : public Function {
625
+ Lambda _lambda;
626
+ std::shared_ptr<Klass> _ptr;
753
627
 
754
- virtual ~StaticFunction() = default;
628
+ public:
629
+ MemberFunction(const Lambda& lambda) : _lambda(lambda) {}
755
630
 
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
- }
631
+ virtual ~MemberFunction() = default;
760
632
 
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
- }
633
+ virtual std::shared_ptr<Function> do_clone() {
634
+ auto ptr = std::make_shared<MemberFunction>(_lambda);
635
+ return std::static_pointer_cast<Function>(ptr);
636
+ }
768
637
 
769
- virtual void do_bind_instance(const Value&) {
770
- // Nothing to bind, static function
638
+ virtual void do_call_function(json& json) {
639
+ try {
640
+ vrpc::call(_lambda(_ptr), vrpc::unpack<Args...>(json));
641
+ json["r"] = nullptr;
642
+ } catch (const std::exception& e) {
643
+ json["e"] = std::string(e.what());
771
644
  }
772
- };
773
-
774
- template <typename Lambda, typename ...Args>
775
- class StaticFunction<Lambda, void, Args...> : public Function {
776
- Lambda m_lambda;
645
+ }
777
646
 
778
- public:
647
+ virtual void do_bind_instance(const Value& instance) {
648
+ _ptr = instance.get<std::shared_ptr<Klass>>();
649
+ }
650
+ };
779
651
 
780
- StaticFunction(
781
- const Lambda& lambda
782
- ) : m_lambda(lambda) { }
652
+ template <typename Lambda, typename Ret, typename... Args>
653
+ class StaticFunction : public Function {
654
+ Lambda _lambda;
783
655
 
784
- virtual ~StaticFunction() = default;
656
+ public:
657
+ StaticFunction(const Lambda& lambda) : _lambda(lambda) {}
785
658
 
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
- }
659
+ virtual ~StaticFunction() = default;
790
660
 
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
- }
661
+ virtual std::shared_ptr<Function> do_clone() {
662
+ auto ptr = std::make_shared<StaticFunction>(_lambda);
663
+ return std::static_pointer_cast<Function>(ptr);
664
+ }
799
665
 
800
- virtual void do_bind_instance(const Value&) {
801
- // Nothing to bind, static function
666
+ virtual void do_call_function(json& json) {
667
+ try {
668
+ json["r"] = vrpc::call(_lambda(), vrpc::unpack<Args...>(json));
669
+ } catch (const std::exception& e) {
670
+ json["e"] = std::string(e.what());
802
671
  }
803
- };
804
-
805
- template <typename Lambda, typename ...Args>
806
- class ConstructorFunction : public Function {
807
- Lambda m_lambda;
672
+ }
808
673
 
809
- public:
674
+ virtual void do_bind_instance(const Value&) {
675
+ // Nothing to bind, static function
676
+ }
677
+ };
810
678
 
811
- ConstructorFunction(
812
- const Lambda& lambda
813
- ) : m_lambda(lambda) { }
679
+ template <typename Lambda, typename... Args>
680
+ class StaticFunction<Lambda, void, Args...> : public Function {
681
+ Lambda _lambda;
814
682
 
815
- virtual ~ConstructorFunction() = default;
683
+ public:
684
+ StaticFunction(const Lambda& lambda) : _lambda(lambda) {}
816
685
 
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
- }
686
+ virtual ~StaticFunction() = default;
821
687
 
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
- }
688
+ virtual std::shared_ptr<Function> do_clone() {
689
+ auto ptr = std::make_shared<StaticFunction>(_lambda);
690
+ return std::static_pointer_cast<Function>(ptr);
691
+ }
829
692
 
830
- virtual void do_bind_instance(const Value&) {
831
- // Nothing to bind
693
+ virtual void do_call_function(json& json) {
694
+ try {
695
+ vrpc::call(_lambda(), vrpc::unpack<Args...>(json));
696
+ json["r"] = nullptr;
697
+ } catch (const std::exception& e) {
698
+ json["e"] = std::string(e.what());
832
699
  }
833
- };
700
+ }
834
701
 
835
- struct required {};
702
+ virtual void do_bind_instance(const Value&) {
703
+ // Nothing to bind, static function
704
+ }
705
+ };
836
706
 
707
+ template <typename Lambda, typename... Args>
708
+ class ConstructorFunction : public Function {
709
+ Lambda _lambda;
837
710
 
711
+ public:
712
+ ConstructorFunction(const Lambda& lambda) : _lambda(lambda) {}
838
713
 
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
- };
714
+ virtual ~ConstructorFunction() = default;
864
715
 
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
- };
716
+ virtual std::shared_ptr<Function> do_clone() {
717
+ auto ptr = std::make_shared<ConstructorFunction>(_lambda);
718
+ return std::static_pointer_cast<Function>(ptr);
881
719
  }
882
720
 
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);
721
+ virtual void do_call_function(json& json) {
722
+ try {
723
+ json["r"] = vrpc::call(_lambda, vrpc::unpack<Args...>(json));
724
+ } catch (const std::exception& e) {
725
+ json["e"] = std::string(e.what());
913
726
  }
727
+ }
914
728
 
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
- }
729
+ virtual void do_bind_instance(const Value&) {
730
+ // Nothing to bind
731
+ }
732
+ };
733
+
734
+ struct required {};
735
+
736
+ namespace detail {
737
+ struct param {
738
+ json j;
739
+ template <typename DefaultType>
740
+ param(const std::string& name,
741
+ const DefaultType& default_value,
742
+ const std::string& description) {
743
+ // json tmp{{"t", type()}};
744
+ // j["type"] = tmp["t"].type_name();
745
+ j["name"] = name;
746
+ j["optional"] = true;
747
+ j["default"] = default_value;
748
+ j["description"] = description;
749
+ }
750
+ param(const std::string& name,
751
+ const required& default_value,
752
+ const std::string& description) {
753
+ // json tmp{{"t", type()}};
754
+ // j["type"] = tmp["t"].type_name();
755
+ j["name"] = name;
756
+ j["optional"] = false;
757
+ j["default"] = nullptr;
758
+ j["description"] = description;
759
+ }
760
+ };
761
+
762
+ template <typename ValueType>
763
+ struct ret {
764
+ json j;
765
+ ret(const std::string& description) {
766
+ j["type"] = json(ValueType()).type_name();
767
+ j["description"] = description;
768
+ }
769
+ };
770
+ template <>
771
+ struct ret<void> {
772
+ json j;
773
+ ret(const std::string& description) {
774
+ j["type"] = "void";
775
+ j["description"] = description;
776
+ }
777
+ };
778
+ } // namespace detail
779
+
780
+ class LocalFactory {
781
+ friend LocalFactory& detail::init<LocalFactory>();
782
+ friend class Proxy;
783
+ friend class MqttClient;
784
+
785
+ typedef std::unordered_map<std::string, Value> StringAnyMap;
786
+ typedef std::unordered_map<std::string, std::shared_ptr<Function>>
787
+ StringFunctionMap;
788
+ typedef std::unordered_map<std::string, StringFunctionMap> FunctionRegistry;
789
+ typedef std::unordered_map<std::string, std::string> SharedInstances;
790
+ typedef std::unordered_map<std::string, json> MetaData;
791
+
792
+ // Maps: class_name => function_name => functionCallback
793
+ FunctionRegistry _class_function_registry;
794
+ // Maps: instanceId => function_name => functionCallback
795
+ FunctionRegistry _function_registry;
796
+ // Maps: instanceId => instanceObj
797
+ StringAnyMap _instances;
798
+ // Maps: instanceId => class_name
799
+ SharedInstances _shared_instances;
800
+ // Optional schema information
801
+ MetaData _meta_data;
802
+
803
+ public:
804
+ template <typename Klass, typename... Args>
805
+ static void register_constructor(const std::string& class_name) {
806
+ LocalFactory::inject_create_isolated_function<Klass, Args...>(class_name);
807
+ LocalFactory::inject_create_shared_function<Klass, Args...>(class_name);
808
+ LocalFactory::inject_delete_function<Klass>(class_name);
809
+ }
934
810
 
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
- }
811
+ template <typename Klass,
812
+ typename Func,
813
+ Func f,
814
+ typename Ret,
815
+ typename... Args>
816
+ static void register_member_function(const std::string& class_name,
817
+ const std::string& function_name) {
818
+ auto func = [](const std::shared_ptr<Klass>& ptr) {
819
+ return vrpc::variadic_bind_member<Klass, Func, Args...>(f, ptr);
820
+ };
821
+ auto funcT =
822
+ std::make_shared<MemberFunction<Klass, decltype(func), Ret, Args...>>(
823
+ func);
824
+ detail::init<LocalFactory>()
825
+ ._class_function_registry[class_name][function_name] =
826
+ std::static_pointer_cast<Function>(funcT);
827
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << function_name
828
+ << std::endl;
829
+ }
946
830
 
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
- }
831
+ template <typename Func, Func f, typename Ret, typename... Args>
832
+ static void register_static_function(const std::string& class_name,
833
+ const std::string& function_name) {
834
+ auto func = []() { return vrpc::variadic_bind<Func, Args...>(f); };
835
+ auto funcT =
836
+ std::make_shared<StaticFunction<decltype(func), Ret, Args...>>(func);
837
+ detail::init<LocalFactory>()._function_registry[class_name][function_name] =
838
+ std::static_pointer_cast<Function>(funcT);
839
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << function_name
840
+ << std::endl;
841
+ }
958
842
 
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
- }
843
+ static void register_meta_data(const std::string& class_name,
844
+ const std::string& function_name,
845
+ const std::string& description,
846
+ const json& params,
847
+ const json& ret) {
848
+ LocalFactory& rf = detail::init<LocalFactory>();
849
+ json& j = rf._meta_data[class_name];
850
+ j[function_name]["description"] = description;
851
+ j[function_name]["params"] = params;
852
+ j[function_name]["ret"] = ret;
853
+ }
966
854
 
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;
855
+ static std::vector<std::string> get_instances(const std::string& class_name) {
856
+ std::vector<std::string> instances;
857
+ for (const auto& kv : detail::init<LocalFactory>()._shared_instances) {
858
+ if (kv.second == class_name)
859
+ instances.push_back(kv.first);
976
860
  }
861
+ return instances;
862
+ }
977
863
 
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
- }
864
+ static std::vector<std::string> get_member_functions(
865
+ const std::string& class_name) {
866
+ std::vector<std::string> functions;
867
+ const auto& it =
868
+ detail::init<LocalFactory>()._class_function_registry.find(class_name);
869
+ if (it != detail::init<LocalFactory>()._class_function_registry.end()) {
870
+ for (const auto& kv : it->second) {
871
+ functions.push_back(kv.first);
987
872
  }
988
- return functions;
989
873
  }
874
+ return functions;
875
+ }
990
876
 
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);
877
+ static std::vector<std::string> get_static_functions(
878
+ const std::string& class_name) {
879
+ std::vector<std::string> functions;
880
+ const auto& it =
881
+ detail::init<LocalFactory>()._function_registry.find(class_name);
882
+ if (it != detail::init<LocalFactory>()._function_registry.end()) {
883
+ for (const auto& kv : it->second) {
884
+ functions.push_back(kv.first);
995
885
  }
996
- return classes;
997
886
  }
887
+ return functions;
888
+ }
998
889
 
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];
890
+ static std::vector<std::string> get_classes() {
891
+ std::vector<std::string> classes;
892
+ for (const auto& kv :
893
+ detail::init<LocalFactory>()._class_function_registry) {
894
+ classes.push_back(kv.first);
1002
895
  }
896
+ return classes;
897
+ }
1003
898
 
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
- }
899
+ static json get_meta_data(const std::string& class_name) {
900
+ LocalFactory& rf = detail::init<LocalFactory>();
901
+ return rf._meta_data[class_name];
902
+ }
1010
903
 
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;
904
+ static std::string call(const std::string& jsonString) {
905
+ json json;
906
+ json = json::parse(jsonString);
907
+ LocalFactory::call(json);
908
+ return json.dump();
909
+ }
910
+
911
+ static void call(json& json) {
912
+ const std::string context = json["c"].get<std::string>();
913
+ std::string function = json["f"].get<std::string>();
914
+ function += vrpc::get_signature(json["a"]);
915
+ _VRPC_DEBUG << "Calling function: " << function
916
+ << " with payload: " << json["a"] << std::endl;
917
+ auto it_t = detail::init<LocalFactory>()._function_registry.find(context);
918
+ if (it_t != detail::init<LocalFactory>()._function_registry.end()) {
919
+ auto it_f = it_t->second.find(function);
920
+ if (it_f != it_t->second.end()) {
921
+ it_f->second->call_function(json);
1026
922
  return;
1027
923
  }
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
924
+ json["e"] = "Could not find function: " + function;
925
+ return;
1041
926
  }
927
+ json["e"] = "Could not find context: " + context;
928
+ }
1042
929
 
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();
930
+ static void load_bindings(const std::string& path) {
931
+ #if defined(VRPC_WITH_DL) && !defined(_WIN32)
932
+ void* libHandle = dlopen(path.c_str(), RTLD_LAZY);
933
+ if (libHandle == 0) {
934
+ throw std::runtime_error("Problem loading bindings: " +
935
+ std::string(dlerror()));
1058
936
  }
937
+ #else
938
+ _VRPC_DEBUG << "Ignored call, dynamic loading is disabled" << std::endl;
939
+ #endif
940
+ }
1059
941
 
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
- };
942
+ private:
943
+ LocalFactory() {}
1177
944
 
1178
- template <class Klass, typename ...Args>
1179
- struct RegisterCtorX {
1180
- static const CtorXRegistrar<Klass, Args...> registerAs;
1181
- };
945
+ LocalFactory(const LocalFactory&) = default;
1182
946
 
947
+ virtual ~LocalFactory() = default;
1183
948
 
1184
- template <class Klass, typename Func, Func f, typename Ret, typename ...Args>
1185
- struct MemberFunctionRegistrar {
949
+ template <typename Klass>
950
+ static std::string create_instance_id(
951
+ const std::shared_ptr<Klass>& ptr) noexcept {
952
+ std::ostringstream ss;
953
+ ss << reinterpret_cast<std::uintptr_t>(ptr.get());
954
+ return ss.str();
955
+ }
1186
956
 
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
- );
957
+ template <typename Klass, typename... Args>
958
+ static void inject_create_isolated_function(const std::string& class_name) {
959
+ auto func = [=](const std::string& instance_id, Args... args) {
960
+ LocalFactory& rf = detail::init<LocalFactory>();
961
+ const auto& it = rf._instances.find(instance_id);
962
+ if (it != rf._instances.end())
963
+ return instance_id;
964
+ // Create instance
965
+ auto ptr = std::shared_ptr<Klass>(new Klass(args...));
966
+ // Bind member functions
967
+ for (auto& i : rf._class_function_registry[class_name]) {
968
+ auto functionCallback = i.second->clone();
969
+ functionCallback->bind_instance(ptr);
970
+ rf._function_registry[instance_id][i.first] = functionCallback;
1197
971
  }
972
+ // Keep instance alive by saving the shared_ptr
973
+ rf._instances[instance_id] = Value(ptr);
974
+ return instance_id;
1198
975
  };
976
+ auto funcT = std::make_shared<
977
+ ConstructorFunction<decltype(func), const std::string&, Args...>>(func);
978
+ const std::string func_name("__createIsolated__" +
979
+ vrpc::get_signature<std::string, Args...>());
980
+ detail::init<LocalFactory>()._function_registry[class_name][func_name] =
981
+ std::static_pointer_cast<Function>(funcT);
982
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name
983
+ << std::endl;
984
+ }
1199
985
 
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);
986
+ template <typename Klass, typename... Args>
987
+ static void inject_create_shared_function(const std::string& class_name) {
988
+ auto func = [=](const std::string& instance_id, Args... args) {
989
+ LocalFactory& rf = detail::init<LocalFactory>();
990
+ const auto& it = rf._instances.find(instance_id);
991
+ if (it != rf._instances.end())
992
+ return instance_id;
993
+ // Create instance
994
+ auto ptr = std::shared_ptr<Klass>(new Klass(args...));
995
+ // Bind member functions
996
+ for (auto& i : rf._class_function_registry[class_name]) {
997
+ auto functionCallback = i.second->clone();
998
+ functionCallback->bind_instance(ptr);
999
+ rf._function_registry[instance_id][i.first] = functionCallback;
1221
1000
  }
1001
+ // Keep instance alive by saving the shared_ptr
1002
+ rf._instances[instance_id] = Value(ptr);
1003
+ // Store shared instance
1004
+ rf._shared_instances.insert({instance_id, class_name});
1005
+ return instance_id;
1222
1006
  };
1007
+ auto funcT = std::make_shared<
1008
+ ConstructorFunction<decltype(func), const std::string&, Args...>>(func);
1009
+ const std::string func_name("__createShared__" +
1010
+ vrpc::get_signature<std::string, Args...>());
1011
+ detail::init<LocalFactory>()._function_registry[class_name][func_name] =
1012
+ std::static_pointer_cast<Function>(funcT);
1013
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name
1014
+ << std::endl;
1015
+ }
1223
1016
 
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
- }
1017
+ template <typename Klass>
1018
+ static void inject_delete_function(const std::string& class_name) {
1019
+ auto func = [=](const std::string& instance_id) {
1020
+ LocalFactory& rf = detail::init<LocalFactory>();
1021
+ const auto& it = rf._instances.find(instance_id);
1022
+ if (it == rf._instances.end())
1023
+ return false;
1024
+ rf._function_registry.erase(instance_id);
1025
+ rf._instances.erase(instance_id);
1026
+ rf._shared_instances.erase(instance_id);
1027
+ return true;
1243
1028
  };
1029
+ auto funcT = std::make_shared<
1030
+ ConstructorFunction<decltype(func), const std::string&>>(func);
1031
+ const std::string func_name("__delete__" +
1032
+ vrpc::get_signature<std::string>());
1033
+ detail::init<LocalFactory>()._function_registry[class_name][func_name] =
1034
+ std::static_pointer_cast<Function>(funcT);
1035
+ _VRPC_DEBUG << "Registered: " << class_name << "::" << func_name
1036
+ << std::endl;
1037
+ }
1038
+ };
1244
1039
 
1245
- template <typename Func, Func f, typename Ret, typename... Args>
1246
- struct RegisterStaticFunction {
1247
- static const StaticFunctionRegistrar<Func, f, Ret, Args...> registerAs;
1248
- };
1040
+ namespace detail {
1249
1041
 
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
- };
1042
+ template <class Klass, typename... Args>
1043
+ struct CtorRegistrar {
1044
+ CtorRegistrar(const std::string& class_name) {
1045
+ LocalFactory::register_constructor<Klass, Args...>(class_name);
1046
+ }
1047
+ };
1048
+
1049
+ template <class Klass, typename... Args>
1050
+ struct RegisterCtor {
1051
+ static const CtorRegistrar<Klass, Args...> registerAs;
1052
+ };
1053
+
1054
+ template <class Klass, typename... Args>
1055
+ struct CtorXRegistrar {
1056
+ CtorXRegistrar(const std::string& class_name,
1057
+ const std::string& ctor_description,
1058
+ const ret<std::string>& ret,
1059
+ const std::vector<param> params = {}) {
1060
+ LocalFactory::register_constructor<Klass, Args...>(class_name);
1061
+ const std::string ctor_name("__createShared__" +
1062
+ vrpc::get_signature<std::string, Args...>());
1063
+ json jp;
1064
+ for (const auto& param : params) {
1065
+ jp.push_back(param.j);
1066
+ }
1067
+ LocalFactory::register_meta_data(class_name, ctor_name, ctor_description,
1068
+ jp, ret.j);
1069
+ }
1070
+ };
1071
+
1072
+ template <class Klass, typename... Args>
1073
+ struct RegisterCtorX {
1074
+ static const CtorXRegistrar<Klass, Args...> registerAs;
1075
+ };
1076
+
1077
+ template <class Klass, typename Func, Func f, typename Ret, typename... Args>
1078
+ struct MemberFunctionRegistrar {
1079
+ MemberFunctionRegistrar(const std::string& class_name,
1080
+ const std::string& function_name) {
1081
+ const std::string full_function_name(function_name +
1082
+ vrpc::get_signature<Args...>());
1083
+ LocalFactory::register_member_function<Klass, Func, f, Ret, Args...>(
1084
+ class_name, full_function_name);
1085
+ }
1086
+ };
1087
+
1088
+ template <class Klass, typename Func, Func f, typename Ret, typename... Args>
1089
+ struct MemberFunctionXRegistrar {
1090
+ MemberFunctionXRegistrar(const std::string& class_name,
1091
+ const std::string& function_name,
1092
+ const std::string& function_description,
1093
+ const ret<Ret>& ret,
1094
+ const std::vector<param> params = {}) {
1095
+ const std::string full_function_name(function_name +
1096
+ vrpc::get_signature<Args...>());
1097
+ LocalFactory::register_member_function<Klass, Func, f, Ret, Args...>(
1098
+ class_name, full_function_name);
1099
+ json jp;
1100
+ for (const auto& param : params) {
1101
+ jp.push_back(param.j);
1102
+ }
1103
+ LocalFactory::register_meta_data(class_name, full_function_name,
1104
+ function_description, jp, ret.j);
1105
+ }
1106
+ };
1107
+
1108
+ template <class Klass, typename Func, Func f, typename Ret, typename... Args>
1109
+ struct RegisterMemberFunction {
1110
+ static const MemberFunctionRegistrar<Klass, Func, f, Ret, Args...> registerAs;
1111
+ };
1112
+
1113
+ template <class Klass, typename Func, Func f, typename Ret, typename... Args>
1114
+ struct RegisterMemberFunctionX {
1115
+ static const MemberFunctionXRegistrar<Klass, Func, f, Ret, Args...>
1116
+ registerAs;
1117
+ };
1118
+
1119
+ template <typename Func, Func f, typename Ret, typename... Args>
1120
+ struct StaticFunctionRegistrar {
1121
+ StaticFunctionRegistrar(const std::string& class_name,
1122
+ const std::string& function_name) {
1123
+ const std::string full_function_name(function_name +
1124
+ vrpc::get_signature<Args...>());
1125
+ LocalFactory::register_static_function<Func, f, Ret, Args...>(
1126
+ class_name, full_function_name);
1127
+ }
1128
+ };
1129
+
1130
+ template <typename Func, Func f, typename Ret, typename... Args>
1131
+ struct RegisterStaticFunction {
1132
+ static const StaticFunctionRegistrar<Func, f, Ret, Args...> registerAs;
1133
+ };
1134
+
1135
+ template <typename Func, Func f, typename Ret, typename... Args>
1136
+ struct StaticFunctionXRegistrar {
1137
+ StaticFunctionXRegistrar(const std::string& class_name,
1138
+ const std::string& function_name,
1139
+ const std::string& function_description,
1140
+ const ret<Ret>& ret,
1141
+ const std::vector<param> params = {}) {
1142
+ const std::string full_function_name(function_name +
1143
+ vrpc::get_signature<Args...>());
1144
+ LocalFactory::register_static_function<Func, f, Ret, Args...>(
1145
+ class_name, full_function_name);
1146
+ json jp;
1147
+ for (const auto& param : params) {
1148
+ jp.push_back(param.j);
1149
+ }
1150
+ LocalFactory::register_meta_data(class_name, full_function_name,
1151
+ function_description, jp, ret.j);
1152
+ }
1153
+ };
1269
1154
 
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
1155
+ template <typename Func, Func f, typename Ret, typename... Args>
1156
+ struct RegisterStaticFunctionX {
1157
+ static const StaticFunctionXRegistrar<Func, f, Ret, Args...> registerAs;
1158
+ };
1159
+ } // namespace detail
1275
1160
 
1276
- // ####################### Macro utility #######################
1161
+ // ####################### Macro utility #######################
1277
1162
 
1278
1163
  #define CAT(A, B) A##B
1279
1164
  #define SELECT(NAME, NUM) CAT(_##NAME##_, NUM)
@@ -1298,7 +1183,7 @@ namespace vrpc {
1298
1183
  #define VRPC_STATIC_FUNCTION_X(...) \
1299
1184
  VA_SELECT(VRPC_STATIC_FUNCTION_X, __VA_ARGS__)
1300
1185
 
1301
- // deprecate
1186
+ // deprecate
1302
1187
  #define VRPC_MEMBER_FUNCTION_CONST(...) \
1303
1188
  VA_SELECT(VRPC_CONST_MEMBER_FUNCTION, __VA_ARGS__)
1304
1189
  #define VRPC_VOID_MEMBER_FUNCTION(...) \
@@ -1308,17 +1193,18 @@ namespace vrpc {
1308
1193
  #define VRPC_VOID_STATIC_FUNCTION(...) \
1309
1194
  VA_SELECT(VRPC_VOID_STATIC_FUNCTION, __VA_ARGS__)
1310
1195
 
1311
- // ####################### Callbacks #######################
1196
+ // ####################### Callbacks #######################
1312
1197
 
1313
- #define VRPC_CALLBACK( ... ) const std::function<void (__VA_ARGS__)>&
1198
+ #define VRPC_CALLBACK(...) const std::function<void(__VA_ARGS__)>&
1314
1199
 
1315
- // ####################### Constructors #######################
1200
+ // ####################### Constructors #######################
1316
1201
 
1317
1202
  #define _VRPC_CTOR_RET_DESC "returns the id of the created instance"
1318
1203
 
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);
1204
+ #define _VRPC_CTOR_VA_ARGS(Klass, ...) \
1205
+ template <> \
1206
+ const vrpc::detail::CtorRegistrar<Klass, __VA_ARGS__> \
1207
+ vrpc::detail::RegisterCtor<Klass, __VA_ARGS__>::registerAs(#Klass);
1322
1208
 
1323
1209
  #define _VRPC_CTOR_1(Klass) \
1324
1210
  template <> \
@@ -1408,13 +1294,13 @@ namespace vrpc {
1408
1294
  {A5Name, A5Default, A5Desc}, \
1409
1295
  {A6Name, A6Default, A6Desc}});
1410
1296
 
1411
- // deprecate
1297
+ // deprecate
1412
1298
  #define VRPC_VOID_CTOR(Klass) \
1413
1299
  template <> \
1414
1300
  const vrpc::detail::CtorRegistrar<Klass> \
1415
1301
  vrpc::detail::RegisterCtor<Klass>::registerAs(#Klass);
1416
1302
 
1417
- // ####################### Zero arguments #######################
1303
+ // ####################### Zero arguments #######################
1418
1304
 
1419
1305
  #define _VRPC_MEMBER_FUNCTION_3(Klass, Ret, Function) \
1420
1306
  template <> \
@@ -1476,7 +1362,7 @@ namespace vrpc {
1476
1362
  Ret>::registerAs(#Klass, #Function, FunctionDesc, {RetDesc});
1477
1363
 
1478
1364
  #define _VRPC_VOID_MEMBER_FUNCTION_2(Klass, Function) \
1479
- _VRPC_MEMBER_FUNCTION_3(Klass, Ret, Function)
1365
+ _VRPC_MEMBER_FUNCTION_3(Klass, void, Function)
1480
1366
 
1481
1367
  #define _VRPC_VOID_MEMBER_FUNCTION_CONST_2(Klass, Function) \
1482
1368
  _VRPC_CONST_MEMBER_FUNCTION_3(Klass, void, Function)
@@ -1484,7 +1370,7 @@ namespace vrpc {
1484
1370
  #define _VRPC_VOID_STATIC_FUNCTION_2(Klass, Function) \
1485
1371
  _VRPC_STATIC_FUNCTION_3(Klass, void, Function)
1486
1372
 
1487
- // ####################### One argument #######################
1373
+ // ####################### One argument #######################
1488
1374
 
1489
1375
  #define _VRPC_MEMBER_FUNCTION_4(Klass, Ret, Function, A1) \
1490
1376
  template <> \
@@ -1566,7 +1452,7 @@ namespace vrpc {
1566
1452
  #define _VRPC_VOID_STATIC_FUNCTION_3(Klass, Function, A1) \
1567
1453
  _VRPC_STATIC_FUNCTION_4(Klass, void, Function, A1)
1568
1454
 
1569
- // ####################### Two arguments #######################
1455
+ // ####################### Two arguments #######################
1570
1456
 
1571
1457
  #define _VRPC_MEMBER_FUNCTION_5(Klass, Ret, Function, A1, A2) \
1572
1458
  template <> \
@@ -1586,8 +1472,8 @@ namespace vrpc {
1586
1472
  &Klass::Function, Ret, A1, A2> \
1587
1473
  vrpc::detail::RegisterMemberFunction< \
1588
1474
  Klass, \
1589
- decltype( \
1590
- static_cast<Ret (Klass::*)(A1, A2) const>(&Klass::Function)), \
1475
+ decltype(static_cast<Ret (Klass::*)(A1, A2) const>( \
1476
+ &Klass::Function)), \
1591
1477
  &Klass::Function, Ret, A1, A2>::registerAs(#Klass, #Function);
1592
1478
 
1593
1479
  #define _VRPC_STATIC_FUNCTION_5(Klass, Ret, Function, A1, A2) \
@@ -1626,8 +1512,8 @@ namespace vrpc {
1626
1512
  &Klass::Function, Ret, A1, A2> \
1627
1513
  vrpc::detail::RegisterMemberFunctionX< \
1628
1514
  Klass, \
1629
- decltype( \
1630
- static_cast<Ret (Klass::*)(A1, A2) const>(&Klass::Function)), \
1515
+ decltype(static_cast<Ret (Klass::*)(A1, A2) const>( \
1516
+ &Klass::Function)), \
1631
1517
  &Klass::Function, Ret, A1, A2>::registerAs(#Klass, #Function, \
1632
1518
  FunctionDesc, {RetDesc}, \
1633
1519
  {{A1Name, A1Default, \
@@ -1660,7 +1546,7 @@ namespace vrpc {
1660
1546
  #define _VRPC_VOID_STATIC_FUNCTION_4(Klass, Function, A1, A2) \
1661
1547
  _VRPC_STATIC_FUNCTION_5(Klass, void, Function, A1, A2)
1662
1548
 
1663
- // ####################### Three arguments #######################
1549
+ // ####################### Three arguments #######################
1664
1550
 
1665
1551
  #define _VRPC_MEMBER_FUNCTION_6(Klass, Ret, Function, A1, A2, A3) \
1666
1552
  template <> \
@@ -1673,17 +1559,17 @@ namespace vrpc {
1673
1559
  decltype(static_cast<Ret (Klass::*)(A1, A2, A3)>(&Klass::Function)), \
1674
1560
  &Klass::Function, Ret, A1, A2, A3>::registerAs(#Klass, #Function);
1675
1561
 
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)), \
1562
+ #define _VRPC_CONST_MEMBER_FUNCTION_6(Klass, Ret, Function, A1, A2, A3) \
1563
+ template <> \
1564
+ const vrpc::detail::MemberFunctionRegistrar< \
1565
+ Klass, \
1566
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1567
+ &Klass::Function)), \
1568
+ &Klass::Function, Ret, A1, A2, A3> \
1569
+ vrpc::detail::RegisterMemberFunction< \
1570
+ Klass, \
1571
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1572
+ &Klass::Function)), \
1687
1573
  &Klass::Function, Ret, A1, A2, A3>::registerAs(#Klass, #Function);
1688
1574
 
1689
1575
  #define _VRPC_STATIC_FUNCTION_6(Klass, Ret, Function, A1, A2, A3) \
@@ -1712,23 +1598,23 @@ namespace vrpc {
1712
1598
  {A2Name, A2Default, A2Desc}, \
1713
1599
  {A3Name, A3Default, A3Desc}});
1714
1600
 
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}, \
1601
+ #define _VRPC_CONST_MEMBER_FUNCTION_X_17( \
1602
+ Klass, Ret, RetDesc, Function, FunctionDesc, A1, A1Name, A1Default, \
1603
+ A1Desc, A2, A2Name, A2Default, A2Desc, A3, A3Name, A3Default, A3Desc) \
1604
+ template <> \
1605
+ const vrpc::detail::MemberFunctionXRegistrar< \
1606
+ Klass, \
1607
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1608
+ &Klass::Function)), \
1609
+ &Klass::Function, Ret, A1, A2, A3> \
1610
+ vrpc::detail::RegisterMemberFunctionX< \
1611
+ Klass, \
1612
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3) const>( \
1613
+ &Klass::Function)), \
1614
+ &Klass::Function, Ret, A1, A2, \
1615
+ A3>::registerAs(#Klass, #Function, FunctionDesc, {RetDesc}, \
1616
+ {{A1Name, A1Default, A1Desc}, \
1617
+ {A2Name, A2Default, A2Desc}, \
1732
1618
  {A3Name, A3Default, A3Desc}});
1733
1619
 
1734
1620
  #define _VRPC_STATIC_FUNCTION_X_17( \
@@ -1755,7 +1641,7 @@ namespace vrpc {
1755
1641
  #define _VRPC_VOID_STATIC_FUNCTION_5(Klass, Function, A1, A2, A3) \
1756
1642
  _VRPC_STATIC_FUNCTION_6(Klass, void, Function, A1, A2, A3)
1757
1643
 
1758
- // ####################### Four arguments #######################
1644
+ // ####################### Four arguments #######################
1759
1645
 
1760
1646
  #define _VRPC_MEMBER_FUNCTION_7(Klass, Ret, Function, A1, A2, A3, A4) \
1761
1647
  template <> \
@@ -1765,8 +1651,8 @@ namespace vrpc {
1765
1651
  &Klass::Function, Ret, A1, A2, A3, A4> \
1766
1652
  vrpc::detail::RegisterMemberFunction< \
1767
1653
  Klass, \
1768
- decltype( \
1769
- static_cast<Ret (Klass::*)(A1, A2, A3, A4)>(&Klass::Function)), \
1654
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4)>( \
1655
+ &Klass::Function)), \
1770
1656
  &Klass::Function, Ret, A1, A2, A3, A4>::registerAs(#Klass, \
1771
1657
  #Function);
1772
1658
 
@@ -1805,8 +1691,8 @@ namespace vrpc {
1805
1691
  &Klass::Function, Ret, A1, A2, A3, A4> \
1806
1692
  vrpc::detail::RegisterMemberFunctionX< \
1807
1693
  Klass, \
1808
- decltype( \
1809
- static_cast<Ret (Klass::*)(A1, A2, A3, A4)>(&Klass::Function)), \
1694
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4)>( \
1695
+ &Klass::Function)), \
1810
1696
  &Klass::Function, Ret, A1, A2, A3, \
1811
1697
  A4>::registerAs(#Klass, #Function, FunctionDesc, {RetDesc}, \
1812
1698
  {{A1Name, A1Default, A1Desc}, \
@@ -1861,20 +1747,20 @@ namespace vrpc {
1861
1747
  #define _VRPC_VOID_STATIC_FUNCTION_6(Klass, Function, A1, A2, A3, A4) \
1862
1748
  _VRPC_STATIC_FUNCTION_7(Klass, void, Function, A1, A2, A3, A4)
1863
1749
 
1864
- // ####################### Five arguments #######################
1750
+ // ####################### Five arguments #######################
1865
1751
 
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, \
1752
+ #define _VRPC_MEMBER_FUNCTION_8(Klass, Ret, Function, A1, A2, A3, A4, A5) \
1753
+ template <> \
1754
+ const vrpc::detail::MemberFunctionRegistrar< \
1755
+ Klass, \
1756
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>( \
1757
+ &Klass::Function)), \
1758
+ &Klass::Function, Ret, A1, A2, A3, A4, A5> \
1759
+ vrpc::detail::RegisterMemberFunction< \
1760
+ Klass, \
1761
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>( \
1762
+ &Klass::Function)), \
1763
+ &Klass::Function, Ret, A1, A2, A3, A4, A5>::registerAs(#Klass, \
1878
1764
  #Function);
1879
1765
 
1880
1766
  #define _VRPC_CONST_MEMBER_FUNCTION_8(Klass, Ret, Function, A1, A2, A3, A4, \
@@ -1909,8 +1795,8 @@ namespace vrpc {
1909
1795
  template <> \
1910
1796
  const vrpc::detail::MemberFunctionXRegistrar< \
1911
1797
  Klass, \
1912
- decltype( \
1913
- static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>(&Klass::Function)), \
1798
+ decltype(static_cast<Ret (Klass::*)(A1, A2, A3, A4, A5)>( \
1799
+ &Klass::Function)), \
1914
1800
  &Klass::Function, Ret, A1, A2, A3, A4, A5> \
1915
1801
  vrpc::detail::RegisterMemberFunctionX< \
1916
1802
  Klass, \
@@ -1974,7 +1860,7 @@ namespace vrpc {
1974
1860
  #define _VRPC_VOID_STATIC_FUNCTION_7(Klass, Function, A1, A2, A3, A4, A5) \
1975
1861
  _VRPC_STATIC_FUNCTION_8(Klass, void, Function, A1, A2, A3, A4, A5)
1976
1862
 
1977
- // ####################### Six arguments #######################
1863
+ // ####################### Six arguments #######################
1978
1864
 
1979
1865
  #define _VRPC_MEMBER_FUNCTION_9(Klass, Ret, Function, A1, A2, A3, A4, A5, A6) \
1980
1866
  template <> \
@@ -2011,8 +1897,8 @@ namespace vrpc {
2011
1897
  decltype(static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>(Klass::Function)), \
2012
1898
  &Klass::Function, Ret, A1, A2, A3, A4, A5, A6> \
2013
1899
  vrpc::detail::RegisterStaticFunction< \
2014
- decltype( \
2015
- static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>(Klass::Function)), \
1900
+ decltype(static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>( \
1901
+ Klass::Function)), \
2016
1902
  &Klass::Function, Ret, A1, A2, A3, A4, A5, \
2017
1903
  A6>::registerAs(#Klass, #Function);
2018
1904
 
@@ -2074,8 +1960,8 @@ namespace vrpc {
2074
1960
  decltype(static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>(Klass::Function)), \
2075
1961
  &Klass::Function, Ret, A1, A2, A3, A4, A5, A6> \
2076
1962
  vrpc::detail::RegisterStaticFunctionX< \
2077
- decltype( \
2078
- static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>(Klass::Function)), \
1963
+ decltype(static_cast<Ret (*)(A1, A2, A3, A4, A5, A6)>( \
1964
+ Klass::Function)), \
2079
1965
  &Klass::Function, Ret, A1, A2, A3, A4, A5, \
2080
1966
  A6>::registerAs(#Klass, #Function, FunctionDesc, {RetDesc}, \
2081
1967
  {{A1Name, A1Default, A1Desc}, \
@@ -2095,6 +1981,6 @@ namespace vrpc {
2095
1981
  #define _VRPC_VOID_STATIC_FUNCTION_8(Klass, Function, A1, A2, A3, A4, A5, A6) \
2096
1982
  _VRPC_STATIC_FUNCTION_9(Klass, void, Function, A1, A2, A3, A4, A5, A6)
2097
1983
 
2098
- } // namespace vrpc
1984
+ } // namespace vrpc
2099
1985
 
2100
1986
  #endif