sdbus-c++  1.3.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 <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
45 namespace 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 
61 namespace 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.
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 <>
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 <>
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 <>
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 <>
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>
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>
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>
572  {
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>
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>
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>
610  {
611  static const std::string str()
612  {
614  }
615  };
616 
617  template <typename _Function>
619  {
620  static const std::string str()
621  {
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_ */
Definition: TypeTraits.h:87
Definition: TypeTraits.h:99
Definition: TypeTraits.h:81
Definition: TypeTraits.h:75
Definition: Types.h:53
Definition: Error.h:42
Definition: TypeTraits.h:627
Definition: TypeTraits.h:94
Definition: Types.h:159
Definition: TypeTraits.h:580
Definition: TypeTraits.h:474
Definition: Message.h:51
Definition: TypeTraits.h:91
Definition: TypeTraits.h:448
Definition: Types.h:206
Definition: MethodResult.h:49
Definition: TypeTraits.h:78
Definition: TypeTraits.h:433
Definition: Types.h:180
Definition: TypeTraits.h:589
Definition: TypeTraits.h:84
Definition: TypeTraits.h:571
Definition: AdaptorInterfaces.h:36