sdbus-c++ 1.2.0
High-level C++ D-Bus library based on systemd D-Bus implementation
TypeTraits.h
Go to the documentation of this file.
1
27#ifndef SDBUS_CXX_TYPETRAITS_H_
28#define SDBUS_CXX_TYPETRAITS_H_
29
30#include <type_traits>
31#include <string>
32#include <vector>
33#include <map>
34#include <cstdint>
35#include <functional>
36#include <memory>
37#include <tuple>
38
39// Forward declarations
40namespace sdbus {
41 class Variant;
42 template <typename... _ValueTypes> class Struct;
43 class ObjectPath;
44 class Signature;
45 class UnixFd;
46 class MethodCall;
47 class MethodReply;
48 class Signal;
49 class Message;
50 class PropertySetCall;
51 class PropertyGetReply;
52 template <typename... _Results> class Result;
53 class Error;
54}
55
56namespace sdbus {
57
58 // Callbacks from sdbus-c++
59 using method_callback = std::function<void(MethodCall msg)>;
60 using async_reply_handler = std::function<void(MethodReply& reply, const Error* error)>;
61 using signal_handler = std::function<void(Signal& signal)>;
62 using message_handler = std::function<void(Message& msg)>;
63 using property_set_callback = std::function<void(PropertySetCall& msg)>;
64 using property_get_callback = std::function<void(PropertyGetReply& reply)>;
65
66 // Type-erased RAII-style handle to callbacks/subscriptions registered to sdbus-c++
67 using Slot = std::unique_ptr<void, std::function<void(void*)>>;
68
69 // Tag specifying that an owning slot handle shall be returned from the function
70 struct request_slot_t { explicit request_slot_t() = default; };
71 inline constexpr request_slot_t request_slot{};
72 // Tag specifying that the library shall own the slot resulting from the call of the function (so-called floating slot)
73 struct floating_slot_t { explicit floating_slot_t() = default; };
74 inline constexpr floating_slot_t floating_slot{};
75 // Deprecated name for the above -- a floating slot
76 struct dont_request_slot_t { explicit dont_request_slot_t() = default; };
77 [[deprecated("Replaced by floating_slot")]] inline constexpr dont_request_slot_t dont_request_slot{};
78 // Tag denoting the assumption that the caller has already obtained message ownership
79 struct adopt_message_t { explicit adopt_message_t() = default; };
80 inline constexpr adopt_message_t adopt_message{};
81 // Tag denoting the assumption that the caller has already obtained fd ownership
82 struct adopt_fd_t { explicit adopt_fd_t() = default; };
83 inline constexpr adopt_fd_t adopt_fd{};
84
85 // Template specializations for getting D-Bus signatures from C++ types
86 template <typename _T>
88 {
89 static constexpr bool is_valid = false;
90
91 static const std::string str()
92 {
93 // sizeof(_T) < 0 is here to make compiler not being able to figure out
94 // the assertion expression before the template instantiation takes place.
95 static_assert(sizeof(_T) < 0, "Unknown DBus type");
96 return "";
97 }
98 };
99
100 template <>
101 struct signature_of<void>
102 {
103 static constexpr bool is_valid = true;
104
105 static const std::string str()
106 {
107 return "";
108 }
109 };
110
111 template <>
112 struct signature_of<bool>
113 {
114 static constexpr bool is_valid = true;
115
116 static const std::string str()
117 {
118 return "b";
119 }
120 };
121
122 template <>
123 struct signature_of<uint8_t>
124 {
125 static constexpr bool is_valid = true;
126
127 static const std::string str()
128 {
129 return "y";
130 }
131 };
132
133 template <>
134 struct signature_of<int16_t>
135 {
136 static constexpr bool is_valid = true;
137
138 static const std::string str()
139 {
140 return "n";
141 }
142 };
143
144 template <>
145 struct signature_of<uint16_t>
146 {
147 static constexpr bool is_valid = true;
148
149 static const std::string str()
150 {
151 return "q";
152 }
153 };
154
155 template <>
156 struct signature_of<int32_t>
157 {
158 static constexpr bool is_valid = true;
159
160 static const std::string str()
161 {
162 return "i";
163 }
164 };
165
166 template <>
167 struct signature_of<uint32_t>
168 {
169 static constexpr bool is_valid = true;
170
171 static const std::string str()
172 {
173 return "u";
174 }
175 };
176
177 template <>
178 struct signature_of<int64_t>
179 {
180 static constexpr bool is_valid = true;
181
182 static const std::string str()
183 {
184 return "x";
185 }
186 };
187
188 template <>
189 struct signature_of<uint64_t>
190 {
191 static constexpr bool is_valid = true;
192
193 static const std::string str()
194 {
195 return "t";
196 }
197 };
198
199 template <>
200 struct signature_of<double>
201 {
202 static constexpr bool is_valid = true;
203
204 static const std::string str()
205 {
206 return "d";
207 }
208 };
209
210 template <>
211 struct signature_of<char*>
212 {
213 static constexpr bool is_valid = true;
214
215 static const std::string str()
216 {
217 return "s";
218 }
219 };
220
221 template <>
222 struct signature_of<const char*>
223 {
224 static constexpr bool is_valid = true;
225
226 static const std::string str()
227 {
228 return "s";
229 }
230 };
231
232 template <std::size_t _N>
233 struct signature_of<char[_N]>
234 {
235 static constexpr bool is_valid = true;
236
237 static const std::string str()
238 {
239 return "s";
240 }
241 };
242
243 template <std::size_t _N>
244 struct signature_of<const char[_N]>
245 {
246 static constexpr bool is_valid = true;
247
248 static const std::string str()
249 {
250 return "s";
251 }
252 };
253
254 template <>
255 struct signature_of<std::string>
256 {
257 static constexpr bool is_valid = true;
258
259 static const std::string str()
260 {
261 return "s";
262 }
263 };
264
265 template <typename... _ValueTypes>
266 struct signature_of<Struct<_ValueTypes...>>
267 {
268 static constexpr bool is_valid = true;
269
270 static const std::string str()
271 {
272 std::string signature;
273 signature += "(";
274 (signature += ... += signature_of<_ValueTypes>::str());
275 signature += ")";
276 return signature;
277 }
278 };
279
280 template <>
282 {
283 static constexpr bool is_valid = true;
284
285 static const std::string str()
286 {
287 return "v";
288 }
289 };
290
291 template <>
293 {
294 static constexpr bool is_valid = true;
295
296 static const std::string str()
297 {
298 return "o";
299 }
300 };
301
302 template <>
304 {
305 static constexpr bool is_valid = true;
306
307 static const std::string str()
308 {
309 return "g";
310 }
311 };
312
313 template <>
315 {
316 static constexpr bool is_valid = true;
317
318 static const std::string str()
319 {
320 return "h";
321 }
322 };
323
324 template <typename _Element>
325 struct signature_of<std::vector<_Element>>
326 {
327 static constexpr bool is_valid = true;
328
329 static const std::string str()
330 {
331 return "a" + signature_of<_Element>::str();
332 }
333 };
334
335 template <typename _Key, typename _Value>
336 struct signature_of<std::map<_Key, _Value>>
337 {
338 static constexpr bool is_valid = true;
339
340 static const std::string str()
341 {
342 return "a{" + signature_of<_Key>::str() + signature_of<_Value>::str() + "}";
343 }
344 };
345
346
347 // Function traits implementation inspired by (c) kennytm,
348 // https://github.com/kennytm/utils/blob/master/traits.hpp
349 template <typename _Type>
351 : public function_traits<decltype(&_Type::operator())>
352 {};
353
354 template <typename _Type>
355 struct function_traits<const _Type>
356 : public function_traits<_Type>
357 {};
358
359 template <typename _Type>
360 struct function_traits<_Type&>
362 {};
363
364 template <typename _ReturnType, typename... _Args>
366 {
367 typedef _ReturnType result_type;
368 typedef std::tuple<_Args...> arguments_type;
369 typedef std::tuple<std::decay_t<_Args>...> decayed_arguments_type;
370
371 typedef _ReturnType function_type(_Args...);
372
373 static constexpr std::size_t arity = sizeof...(_Args);
374
375// template <size_t _Idx, typename _Enabled = void>
376// struct arg;
377//
378// template <size_t _Idx>
379// struct arg<_Idx, std::enable_if_t<(_Idx < arity)>>
380// {
381// typedef std::tuple_element_t<_Idx, arguments_type> type;
382// };
383//
384// template <size_t _Idx>
385// struct arg<_Idx, std::enable_if_t<!(_Idx < arity)>>
386// {
387// typedef void type;
388// };
389
390 template <size_t _Idx>
391 struct arg
392 {
393 typedef std::tuple_element_t<_Idx, std::tuple<_Args...>> type;
394 };
395
396 template <size_t _Idx>
397 using arg_t = typename arg<_Idx>::type;
398 };
399
400 template <typename _ReturnType, typename... _Args>
401 struct function_traits<_ReturnType(_Args...)>
402 : public function_traits_base<_ReturnType, _Args...>
403 {
404 static constexpr bool is_async = false;
405 static constexpr bool has_error_param = false;
406 };
407
408 template <typename... _Args>
409 struct function_traits<void(const Error*, _Args...)>
410 : public function_traits_base<void, _Args...>
411 {
412 static constexpr bool has_error_param = true;
413 };
414
415 template <typename... _Args, typename... _Results>
416 struct function_traits<void(Result<_Results...>, _Args...)>
417 : public function_traits_base<std::tuple<_Results...>, _Args...>
418 {
419 static constexpr bool is_async = true;
420 using async_result_t = Result<_Results...>;
421 };
422
423 template <typename... _Args, typename... _Results>
424 struct function_traits<void(Result<_Results...>&&, _Args...)>
425 : public function_traits_base<std::tuple<_Results...>, _Args...>
426 {
427 static constexpr bool is_async = true;
428 using async_result_t = Result<_Results...>;
429 };
430
431 template <typename _ReturnType, typename... _Args>
432 struct function_traits<_ReturnType(*)(_Args...)>
433 : public function_traits<_ReturnType(_Args...)>
434 {};
435
436 template <typename _ClassType, typename _ReturnType, typename... _Args>
437 struct function_traits<_ReturnType(_ClassType::*)(_Args...)>
438 : public function_traits<_ReturnType(_Args...)>
439 {
440 typedef _ClassType& owner_type;
441 };
442
443 template <typename _ClassType, typename _ReturnType, typename... _Args>
444 struct function_traits<_ReturnType(_ClassType::*)(_Args...) const>
445 : public function_traits<_ReturnType(_Args...)>
446 {
447 typedef const _ClassType& owner_type;
448 };
449
450 template <typename _ClassType, typename _ReturnType, typename... _Args>
451 struct function_traits<_ReturnType(_ClassType::*)(_Args...) volatile>
452 : public function_traits<_ReturnType(_Args...)>
453 {
454 typedef volatile _ClassType& owner_type;
455 };
456
457 template <typename _ClassType, typename _ReturnType, typename... _Args>
458 struct function_traits<_ReturnType(_ClassType::*)(_Args...) const volatile>
459 : public function_traits<_ReturnType(_Args...)>
460 {
461 typedef const volatile _ClassType& owner_type;
462 };
463
464 template <typename FunctionType>
465 struct function_traits<std::function<FunctionType>>
466 : public function_traits<FunctionType>
467 {};
468
469 template <class _Function>
470 constexpr auto is_async_method_v = function_traits<_Function>::is_async;
471
472 template <class _Function>
473 constexpr auto has_error_param_v = function_traits<_Function>::has_error_param;
474
475 template <typename _FunctionType>
476 using function_arguments_t = typename function_traits<_FunctionType>::arguments_type;
477
478 template <typename _FunctionType, size_t _Idx>
479 using function_argument_t = typename function_traits<_FunctionType>::template arg_t<_Idx>;
480
481 template <typename _FunctionType>
482 constexpr auto function_argument_count_v = function_traits<_FunctionType>::arity;
483
484 template <typename _FunctionType>
485 using function_result_t = typename function_traits<_FunctionType>::result_type;
486
487 template <typename _Function>
489 {
491 };
492
493 template <typename _Function>
494 using tuple_of_function_input_arg_types_t = typename tuple_of_function_input_arg_types<_Function>::type;
495
496 template <typename _Function>
498 {
499 typedef typename function_traits<_Function>::result_type type;
500 };
501
502 template <typename _Function>
503 using tuple_of_function_output_arg_types_t = typename tuple_of_function_output_arg_types<_Function>::type;
504
505 template <typename _Type>
507 {
508 static const std::string str()
509 {
511 }
512 };
513
514 template <typename... _Types>
515 struct aggregate_signature<std::tuple<_Types...>>
516 {
517 static const std::string str()
518 {
519 std::string signature;
520 (void)(signature += ... += signature_of<std::decay_t<_Types>>::str());
521 return signature;
522 }
523 };
524
525 template <typename _Function>
527 {
528 static const std::string str()
529 {
531 }
532 };
533
534 template <typename _Function>
536 {
537 static const std::string str()
538 {
540 }
541 };
542
543 namespace detail
544 {
545 template <class _Function, class _Tuple, typename... _Args, std::size_t... _I>
546 constexpr decltype(auto) apply_impl( _Function&& f
547 , Result<_Args...>&& r
548 , _Tuple&& t
549 , std::index_sequence<_I...> )
550 {
551 return std::forward<_Function>(f)(std::move(r), std::get<_I>(std::forward<_Tuple>(t))...);
552 }
553
554 template <class _Function, class _Tuple, std::size_t... _I>
555 constexpr decltype(auto) apply_impl( _Function&& f
556 , const Error* e
557 , _Tuple&& t
558 , std::index_sequence<_I...> )
559 {
560 return std::forward<_Function>(f)(e, std::get<_I>(std::forward<_Tuple>(t))...);
561 }
562
563 // For non-void returning functions, apply_impl simply returns function return value (a tuple of values).
564 // For void-returning functions, apply_impl returns an empty tuple.
565 template <class _Function, class _Tuple, std::size_t... _I>
566 constexpr decltype(auto) apply_impl( _Function&& f
567 , _Tuple&& t
568 , std::index_sequence<_I...> )
569 {
570 if constexpr (!std::is_void_v<function_result_t<_Function>>)
571 return std::forward<_Function>(f)(std::get<_I>(std::forward<_Tuple>(t))...);
572 else
573 return std::forward<_Function>(f)(std::get<_I>(std::forward<_Tuple>(t))...), std::tuple<>{};
574 }
575 }
576
577 // Convert tuple `t' of values into a list of arguments
578 // and invoke function `f' with those arguments.
579 template <class _Function, class _Tuple>
580 constexpr decltype(auto) apply(_Function&& f, _Tuple&& t)
581 {
582 return detail::apply_impl( std::forward<_Function>(f)
583 , std::forward<_Tuple>(t)
584 , std::make_index_sequence<std::tuple_size<std::decay_t<_Tuple>>::value>{} );
585 }
586
587 // Convert tuple `t' of values into a list of arguments
588 // and invoke function `f' with those arguments.
589 template <class _Function, class _Tuple, typename... _Args>
590 constexpr decltype(auto) apply(_Function&& f, Result<_Args...>&& r, _Tuple&& t)
591 {
592 return detail::apply_impl( std::forward<_Function>(f)
593 , std::move(r)
594 , std::forward<_Tuple>(t)
595 , std::make_index_sequence<std::tuple_size<std::decay_t<_Tuple>>::value>{} );
596 }
597
598 // Convert tuple `t' of values into a list of arguments
599 // and invoke function `f' with those arguments.
600 template <class _Function, class _Tuple>
601 constexpr decltype(auto) apply(_Function&& f, const Error* e, _Tuple&& t)
602 {
603 return detail::apply_impl( std::forward<_Function>(f)
604 , e
605 , std::forward<_Tuple>(t)
606 , std::make_index_sequence<std::tuple_size<std::decay_t<_Tuple>>::value>{} );
607 }
608}
609
610#endif /* SDBUS_CXX_TYPETRAITS_H_ */
Definition: Error.h:44
Definition: Types.h:153
Definition: MethodResult.h:50
Definition: Types.h:174
Definition: Types.h:111
Definition: Types.h:200
Definition: Types.h:54
Definition: TypeTraits.h:82
Definition: TypeTraits.h:79
Definition: TypeTraits.h:507
Definition: TypeTraits.h:76
Definition: TypeTraits.h:73
Definition: TypeTraits.h:392
Definition: TypeTraits.h:366
Definition: TypeTraits.h:352
Definition: TypeTraits.h:70
Definition: TypeTraits.h:88
Definition: TypeTraits.h:489
Definition: TypeTraits.h:498