sdbus-c++ 1.6.0
High-level C++ D-Bus library based on systemd D-Bus implementation
Loading...
Searching...
No Matches
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 <array>
34#include <variant>
35#if __cplusplus >= 202002L
36#include <span>
37#endif
38#include <map>
39#include <unordered_map>
40#include <cstdint>
41#include <functional>
42#include <memory>
43#include <tuple>
44
45// Forward declarations
46namespace sdbus {
47 class Variant;
48 template <typename... _ValueTypes> class Struct;
49 class ObjectPath;
50 class Signature;
51 class UnixFd;
52 class MethodCall;
53 class MethodReply;
54 class Signal;
55 class Message;
56 class PropertySetCall;
57 class PropertyGetReply;
58 template <typename... _Results> class Result;
59 class Error;
60}
61
62namespace sdbus {
63
64 // Callbacks from sdbus-c++
65 using method_callback = std::function<void(MethodCall msg)>;
66 using async_reply_handler = std::function<void(MethodReply& reply, const Error* error)>;
67 using signal_handler = std::function<void(Signal& signal)>;
68 using message_handler = std::function<void(Message& msg)>;
69 using property_set_callback = std::function<void(PropertySetCall& msg)>;
70 using property_get_callback = std::function<void(PropertyGetReply& reply)>;
71
72 // Type-erased RAII-style handle to callbacks/subscriptions registered to sdbus-c++
73 using Slot = std::unique_ptr<void, std::function<void(void*)>>;
74
75 // Tag specifying that an owning slot handle shall be returned from the function
76 struct request_slot_t { explicit request_slot_t() = default; };
77 inline constexpr request_slot_t request_slot{};
78 // Tag specifying that the library shall own the slot resulting from the call of the function (so-called floating slot)
79 struct floating_slot_t { explicit floating_slot_t() = default; };
80 inline constexpr floating_slot_t floating_slot{};
81 // Deprecated name for the above -- a floating slot
82 struct dont_request_slot_t { explicit dont_request_slot_t() = default; };
83 [[deprecated("Replaced by floating_slot")]] inline constexpr dont_request_slot_t dont_request_slot{};
84 // Tag denoting the assumption that the caller has already obtained message ownership
85 struct adopt_message_t { explicit adopt_message_t() = default; };
86 inline constexpr adopt_message_t adopt_message{};
87 // Tag denoting the assumption that the caller has already obtained fd ownership
88 struct adopt_fd_t { explicit adopt_fd_t() = default; };
89 inline constexpr adopt_fd_t adopt_fd{};
90 // Tag specifying that the proxy shall not run an event loop thread on its D-Bus connection.
91 // Such proxies are typically created to carry out a simple synchronous D-Bus call(s) and then are destroyed.
93 inline constexpr dont_run_event_loop_thread_t dont_run_event_loop_thread{};
94 // Tag denoting an asynchronous call that returns std::future as a handle
95 struct with_future_t { explicit with_future_t() = default; };
96 inline constexpr with_future_t with_future{};
97 // Tag denoting a call where the reply shouldn't be waited for
98 struct dont_expect_reply_t { explicit dont_expect_reply_t() = default; };
99 inline constexpr dont_expect_reply_t dont_expect_reply{};
100
101 // Helper for static assert
102 template <class... _T> constexpr bool always_false = false;
103
104 // Template specializations for getting D-Bus signatures from C++ types
105 template <typename _T, typename _Enable = void>
107 {
108 static constexpr bool is_valid = false;
109 static constexpr bool is_trivial_dbus_type = false;
110
111 static const std::string str()
112 {
113 // See using-sdbus-c++.md, section "Extending sdbus-c++ type system",
114 // on how to teach sdbus-c++ about your custom types
115 static_assert(always_false<_T>, "Unsupported DBus type (template specializations are needed for your custom types)");
116 return "";
117 }
118 };
119
120 template <typename _T>
121 struct signature_of<const _T>
122 : public signature_of<_T>
123 {};
124
125 template <typename _T>
126 struct signature_of<_T&>
127 : public signature_of<_T>
128 {};
129
130 template <>
131 struct signature_of<void>
132 {
133 static constexpr bool is_valid = true;
134 static constexpr bool is_trivial_dbus_type = false;
135
136 static const std::string str()
137 {
138 return "";
139 }
140 };
141
142 template <>
143 struct signature_of<bool>
144 {
145 static constexpr bool is_valid = true;
146 static constexpr bool is_trivial_dbus_type = true;
147
148 static const std::string str()
149 {
150 return "b";
151 }
152 };
153
154 template <>
155 struct signature_of<uint8_t>
156 {
157 static constexpr bool is_valid = true;
158 static constexpr bool is_trivial_dbus_type = true;
159
160 static const std::string str()
161 {
162 return "y";
163 }
164 };
165
166 template <>
167 struct signature_of<int16_t>
168 {
169 static constexpr bool is_valid = true;
170 static constexpr bool is_trivial_dbus_type = true;
171
172 static const std::string str()
173 {
174 return "n";
175 }
176 };
177
178 template <>
179 struct signature_of<uint16_t>
180 {
181 static constexpr bool is_valid = true;
182 static constexpr bool is_trivial_dbus_type = true;
183
184 static const std::string str()
185 {
186 return "q";
187 }
188 };
189
190 template <>
191 struct signature_of<int32_t>
192 {
193 static constexpr bool is_valid = true;
194 static constexpr bool is_trivial_dbus_type = true;
195
196 static const std::string str()
197 {
198 return "i";
199 }
200 };
201
202 template <>
203 struct signature_of<uint32_t>
204 {
205 static constexpr bool is_valid = true;
206 static constexpr bool is_trivial_dbus_type = true;
207
208 static const std::string str()
209 {
210 return "u";
211 }
212 };
213
214 template <>
215 struct signature_of<int64_t>
216 {
217 static constexpr bool is_valid = true;
218 static constexpr bool is_trivial_dbus_type = true;
219
220 static const std::string str()
221 {
222 return "x";
223 }
224 };
225
226 template <>
227 struct signature_of<uint64_t>
228 {
229 static constexpr bool is_valid = true;
230 static constexpr bool is_trivial_dbus_type = true;
231
232 static const std::string str()
233 {
234 return "t";
235 }
236 };
237
238 template <>
239 struct signature_of<double>
240 {
241 static constexpr bool is_valid = true;
242 static constexpr bool is_trivial_dbus_type = true;
243
244 static const std::string str()
245 {
246 return "d";
247 }
248 };
249
250 template <>
251 struct signature_of<char*>
252 {
253 static constexpr bool is_valid = true;
254 static constexpr bool is_trivial_dbus_type = false;
255
256 static const std::string str()
257 {
258 return "s";
259 }
260 };
261
262 template <>
263 struct signature_of<const char*>
264 {
265 static constexpr bool is_valid = true;
266 static constexpr bool is_trivial_dbus_type = false;
267
268 static const std::string str()
269 {
270 return "s";
271 }
272 };
273
274 template <std::size_t _N>
275 struct signature_of<char[_N]>
276 {
277 static constexpr bool is_valid = true;
278 static constexpr bool is_trivial_dbus_type = false;
279
280 static const std::string str()
281 {
282 return "s";
283 }
284 };
285
286 template <std::size_t _N>
287 struct signature_of<const char[_N]>
288 {
289 static constexpr bool is_valid = true;
290 static constexpr bool is_trivial_dbus_type = false;
291
292 static const std::string str()
293 {
294 return "s";
295 }
296 };
297
298 template <>
299 struct signature_of<std::string>
300 {
301 static constexpr bool is_valid = true;
302 static constexpr bool is_trivial_dbus_type = false;
303
304 static const std::string str()
305 {
306 return "s";
307 }
308 };
309
310 template <typename... _ValueTypes>
311 struct signature_of<Struct<_ValueTypes...>>
312 {
313 static constexpr bool is_valid = true;
314 static constexpr bool is_trivial_dbus_type = false;
315
316 static const std::string str()
317 {
318 std::string signature;
319 signature += "(";
320 (signature += ... += signature_of<_ValueTypes>::str());
321 signature += ")";
322 return signature;
323 }
324 };
325
326 template <>
328 {
329 static constexpr bool is_valid = true;
330 static constexpr bool is_trivial_dbus_type = false;
331
332 static const std::string str()
333 {
334 return "v";
335 }
336 };
337
338 template <typename... Elements>
339 struct signature_of<std::variant<Elements...>> : signature_of<Variant>
340 {};
341
342 template <>
344 {
345 static constexpr bool is_valid = true;
346 static constexpr bool is_trivial_dbus_type = false;
347
348 static const std::string str()
349 {
350 return "o";
351 }
352 };
353
354 template <>
356 {
357 static constexpr bool is_valid = true;
358 static constexpr bool is_trivial_dbus_type = false;
359
360 static const std::string str()
361 {
362 return "g";
363 }
364 };
365
366 template <>
368 {
369 static constexpr bool is_valid = true;
370 static constexpr bool is_trivial_dbus_type = false;
371
372 static const std::string str()
373 {
374 return "h";
375 }
376 };
377
378 template <typename _Element, typename _Allocator>
379 struct signature_of<std::vector<_Element, _Allocator>>
380 {
381 static constexpr bool is_valid = true;
382 static constexpr bool is_trivial_dbus_type = false;
383
384 static const std::string str()
385 {
386 return "a" + signature_of<_Element>::str();
387 }
388 };
389
390 template <typename _Element, std::size_t _Size>
391 struct signature_of<std::array<_Element, _Size>>
392 {
393 static constexpr bool is_valid = true;
394 static constexpr bool is_trivial_dbus_type = false;
395
396 static const std::string str()
397 {
398 return "a" + signature_of<_Element>::str();
399 }
400 };
401
402#if __cplusplus >= 202002L
403 template <typename _Element, std::size_t _Extent>
404 struct signature_of<std::span<_Element, _Extent>>
405 {
406 static constexpr bool is_valid = true;
407 static constexpr bool is_trivial_dbus_type = false;
408
409 static const std::string str()
410 {
411 return "a" + signature_of<_Element>::str();
412 }
413 };
414#endif
415
416 template <typename _Enum>
417 struct signature_of<_Enum, typename std::enable_if_t<std::is_enum_v<_Enum>>>
418 : public signature_of<std::underlying_type_t<_Enum>>
419 {};
420
421
422 template <typename _Key, typename _Value, typename _Compare, typename _Allocator>
423 struct signature_of<std::map<_Key, _Value, _Compare, _Allocator>>
424 {
425 static constexpr bool is_valid = true;
426 static constexpr bool is_trivial_dbus_type = false;
427
428 static const std::string str()
429 {
430 return "a{" + signature_of<_Key>::str() + signature_of<_Value>::str() + "}";
431 }
432 };
433
434 template <typename _Key, typename _Value, typename _Hash, typename _KeyEqual, typename _Allocator>
435 struct signature_of<std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>>
436 {
437 static constexpr bool is_valid = true;
438 static constexpr bool is_trivial_dbus_type = false;
439
440 static const std::string str()
441 {
442 return "a{" + signature_of<_Key>::str() + signature_of<_Value>::str() + "}";
443 }
444 };
445
446 // Function traits implementation inspired by (c) kennytm,
447 // https://github.com/kennytm/utils/blob/master/traits.hpp
448 template <typename _Type>
450 : public function_traits<decltype(&_Type::operator())>
451 {};
452
453 template <typename _Type>
454 struct function_traits<const _Type>
455 : public function_traits<_Type>
456 {};
457
458 template <typename _Type>
459 struct function_traits<_Type&>
461 {};
462
463 template <typename _ReturnType, typename... _Args>
465 {
466 typedef _ReturnType result_type;
467 typedef std::tuple<_Args...> arguments_type;
468 typedef std::tuple<std::decay_t<_Args>...> decayed_arguments_type;
469
470 typedef _ReturnType function_type(_Args...);
471
472 static constexpr std::size_t arity = sizeof...(_Args);
473
474// template <size_t _Idx, typename _Enabled = void>
475// struct arg;
476//
477// template <size_t _Idx>
478// struct arg<_Idx, std::enable_if_t<(_Idx < arity)>>
479// {
480// typedef std::tuple_element_t<_Idx, arguments_type> type;
481// };
482//
483// template <size_t _Idx>
484// struct arg<_Idx, std::enable_if_t<!(_Idx < arity)>>
485// {
486// typedef void type;
487// };
488
489 template <size_t _Idx>
490 struct arg
491 {
492 typedef std::tuple_element_t<_Idx, std::tuple<_Args...>> type;
493 };
494
495 template <size_t _Idx>
496 using arg_t = typename arg<_Idx>::type;
497 };
498
499 template <typename _ReturnType, typename... _Args>
500 struct function_traits<_ReturnType(_Args...)>
501 : public function_traits_base<_ReturnType, _Args...>
502 {
503 static constexpr bool is_async = false;
504 static constexpr bool has_error_param = false;
505 };
506
507 template <typename... _Args>
508 struct function_traits<void(const Error*, _Args...)>
509 : public function_traits_base<void, _Args...>
510 {
511 static constexpr bool has_error_param = true;
512 };
513
514 template <typename... _Args, typename... _Results>
515 struct function_traits<void(Result<_Results...>, _Args...)>
516 : public function_traits_base<std::tuple<_Results...>, _Args...>
517 {
518 static constexpr bool is_async = true;
519 using async_result_t = Result<_Results...>;
520 };
521
522 template <typename... _Args, typename... _Results>
523 struct function_traits<void(Result<_Results...>&&, _Args...)>
524 : public function_traits_base<std::tuple<_Results...>, _Args...>
525 {
526 static constexpr bool is_async = true;
527 using async_result_t = Result<_Results...>;
528 };
529
530 template <typename _ReturnType, typename... _Args>
531 struct function_traits<_ReturnType(*)(_Args...)>
532 : public function_traits<_ReturnType(_Args...)>
533 {};
534
535 template <typename _ClassType, typename _ReturnType, typename... _Args>
536 struct function_traits<_ReturnType(_ClassType::*)(_Args...)>
537 : public function_traits<_ReturnType(_Args...)>
538 {
539 typedef _ClassType& owner_type;
540 };
541
542 template <typename _ClassType, typename _ReturnType, typename... _Args>
543 struct function_traits<_ReturnType(_ClassType::*)(_Args...) const>
544 : public function_traits<_ReturnType(_Args...)>
545 {
546 typedef const _ClassType& owner_type;
547 };
548
549 template <typename _ClassType, typename _ReturnType, typename... _Args>
550 struct function_traits<_ReturnType(_ClassType::*)(_Args...) volatile>
551 : public function_traits<_ReturnType(_Args...)>
552 {
553 typedef volatile _ClassType& owner_type;
554 };
555
556 template <typename _ClassType, typename _ReturnType, typename... _Args>
557 struct function_traits<_ReturnType(_ClassType::*)(_Args...) const volatile>
558 : public function_traits<_ReturnType(_Args...)>
559 {
560 typedef const volatile _ClassType& owner_type;
561 };
562
563 template <typename FunctionType>
564 struct function_traits<std::function<FunctionType>>
565 : public function_traits<FunctionType>
566 {};
567
568 template <class _Function>
569 constexpr auto is_async_method_v = function_traits<_Function>::is_async;
570
571 template <class _Function>
572 constexpr auto has_error_param_v = function_traits<_Function>::has_error_param;
573
574 template <typename _FunctionType>
575 using function_arguments_t = typename function_traits<_FunctionType>::arguments_type;
576
577 template <typename _FunctionType, size_t _Idx>
578 using function_argument_t = typename function_traits<_FunctionType>::template arg_t<_Idx>;
579
580 template <typename _FunctionType>
581 constexpr auto function_argument_count_v = function_traits<_FunctionType>::arity;
582
583 template <typename _FunctionType>
584 using function_result_t = typename function_traits<_FunctionType>::result_type;
585
586 template <typename _Function>
591
592 template <typename _Function>
593 using tuple_of_function_input_arg_types_t = typename tuple_of_function_input_arg_types<_Function>::type;
594
595 template <typename _Function>
600
601 template <typename _Function>
602 using tuple_of_function_output_arg_types_t = typename tuple_of_function_output_arg_types<_Function>::type;
603
604 template <typename _Type>
606 {
607 static const std::string str()
608 {
610 }
611 };
612
613 template <typename... _Types>
614 struct aggregate_signature<std::tuple<_Types...>>
615 {
616 static const std::string str()
617 {
618 std::string signature;
619 (void)(signature += ... += signature_of<std::decay_t<_Types>>::str());
620 return signature;
621 }
622 };
623
624 template <typename _Function>
626 {
627 static const std::string str()
628 {
630 }
631 };
632
633 template <typename _Function>
635 {
636 static const std::string str()
637 {
639 }
640 };
641
642
643 template <typename... _Args> struct future_return
644 {
645 typedef std::tuple<_Args...> type;
646 };
647
648 template <> struct future_return<>
649 {
650 typedef void type;
651 };
652
653 template <typename _Type> struct future_return<_Type>
654 {
655 typedef _Type type;
656 };
657
658 template <typename... _Args>
659 using future_return_t = typename future_return<_Args...>::type;
660
661
662 namespace detail
663 {
664 template <class _Function, class _Tuple, typename... _Args, std::size_t... _I>
665 constexpr decltype(auto) apply_impl( _Function&& f
666 , Result<_Args...>&& r
667 , _Tuple&& t
668 , std::index_sequence<_I...> )
669 {
670 return std::forward<_Function>(f)(std::move(r), std::get<_I>(std::forward<_Tuple>(t))...);
671 }
672
673 template <class _Function, class _Tuple, std::size_t... _I>
674 constexpr decltype(auto) apply_impl( _Function&& f
675 , const Error* e
676 , _Tuple&& t
677 , std::index_sequence<_I...> )
678 {
679 return std::forward<_Function>(f)(e, std::get<_I>(std::forward<_Tuple>(t))...);
680 }
681
682 // For non-void returning functions, apply_impl simply returns function return value (a tuple of values).
683 // For void-returning functions, apply_impl returns an empty tuple.
684 template <class _Function, class _Tuple, std::size_t... _I>
685 constexpr decltype(auto) apply_impl( _Function&& f
686 , _Tuple&& t
687 , std::index_sequence<_I...> )
688 {
689 if constexpr (!std::is_void_v<function_result_t<_Function>>)
690 return std::forward<_Function>(f)(std::get<_I>(std::forward<_Tuple>(t))...);
691 else
692 return std::forward<_Function>(f)(std::get<_I>(std::forward<_Tuple>(t))...), std::tuple<>{};
693 }
694 }
695
696 // Convert tuple `t' of values into a list of arguments
697 // and invoke function `f' with those arguments.
698 template <class _Function, class _Tuple>
699 constexpr decltype(auto) apply(_Function&& f, _Tuple&& t)
700 {
701 return detail::apply_impl( std::forward<_Function>(f)
702 , std::forward<_Tuple>(t)
703 , std::make_index_sequence<std::tuple_size<std::decay_t<_Tuple>>::value>{} );
704 }
705
706 // Convert tuple `t' of values into a list of arguments
707 // and invoke function `f' with those arguments.
708 template <class _Function, class _Tuple, typename... _Args>
709 constexpr decltype(auto) apply(_Function&& f, Result<_Args...>&& r, _Tuple&& t)
710 {
711 return detail::apply_impl( std::forward<_Function>(f)
712 , std::move(r)
713 , std::forward<_Tuple>(t)
714 , std::make_index_sequence<std::tuple_size<std::decay_t<_Tuple>>::value>{} );
715 }
716
717 // Convert tuple `t' of values into a list of arguments
718 // and invoke function `f' with those arguments.
719 template <class _Function, class _Tuple>
720 constexpr decltype(auto) apply(_Function&& f, const Error* e, _Tuple&& t)
721 {
722 return detail::apply_impl( std::forward<_Function>(f)
723 , e
724 , std::forward<_Tuple>(t)
725 , std::make_index_sequence<std::tuple_size<std::decay_t<_Tuple>>::value>{} );
726 }
727}
728
729#endif /* SDBUS_CXX_TYPETRAITS_H_ */
Definition Error.h:44
Definition Message.h:79
Definition Message.h:242
Definition Message.h:270
Definition Types.h:177
Definition Message.h:300
Definition Message.h:291
Definition TypeTraits.h:58
Definition Message.h:280
Definition Types.h:198
Definition TypeTraits.h:48
Definition Types.h:224
Definition Types.h:54
Definition TypeTraits.h:88
Definition TypeTraits.h:85
Definition TypeTraits.h:606
Definition TypeTraits.h:98
Definition TypeTraits.h:82
Definition TypeTraits.h:92
Definition TypeTraits.h:79
Definition TypeTraits.h:491
Definition TypeTraits.h:465
Definition TypeTraits.h:451
Definition TypeTraits.h:644
Definition TypeTraits.h:76
Definition TypeTraits.h:107
Definition TypeTraits.h:588
Definition TypeTraits.h:95