sdbus-c++: include/sdbus-c++/TypeTraits.h Source File

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