sdbus-c++  1.6.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 #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
46 namespace 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 
62 namespace 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&>
460  : public 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>
588  {
590  };
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>
597  {
598  typedef typename function_traits<_Function>::result_type type;
599  };
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  {
609  return signature_of<std::decay_t<_Type>>::str();
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: Types.h:177
Definition: MethodResult.h:50
Definition: Types.h:198
Definition: Types.h:132
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:597
Definition: TypeTraits.h:95