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

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