sdbus-c++ 2.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
26
27#ifndef SDBUS_CXX_TYPETRAITS_H_
28#define SDBUS_CXX_TYPETRAITS_H_
29
30#include <sdbus-c++/Error.h>
31
32#include <array>
33#include <cstdint>
34#include <functional>
35#include <map>
36#include <memory>
37#include <optional>
38#ifdef __has_include
39# if __has_include(<span>)
40# include <span>
41# endif
42#endif
43#include <string>
44#include <string_view>
45#include <tuple>
46#include <type_traits>
47#include <unordered_map>
48#include <utility>
49#include <variant>
50#include <vector>
51
52// Forward declarations
53namespace sdbus {
54 class Variant;
55 template <typename... ValueTypes> class Struct;
56 class ObjectPath;
57 class Signature;
58 class UnixFd;
59 template<typename T1, typename T2> using DictEntry = std::pair<T1, T2>;
60 class BusName;
61 class InterfaceName;
62 class MemberName;
63 class MethodCall;
64 class MethodReply;
65 class Signal;
66 class Message;
67 class PropertySetCall;
68 class PropertyGetReply;
69 template <typename... Results> class Result;
70 class Error;
71 template <typename T, typename Enable = void> struct signature_of;
72} // namespace sdbus
73
74namespace sdbus {
75
76 // Callbacks from sdbus-c++
77 using method_callback = std::function<void(MethodCall msg)>;
78 using async_reply_handler = std::function<void(MethodReply reply, std::optional<Error> error)>;
79 using signal_handler = std::function<void(Signal signal)>;
80 using message_handler = std::function<void(Message msg)>;
81 using property_set_callback = std::function<void(PropertySetCall msg)>;
82 using property_get_callback = std::function<void(PropertyGetReply& reply)>;
83
84 // Type-erased RAII-style handle to callbacks/subscriptions registered to sdbus-c++
85 using Slot = std::unique_ptr<void, std::function<void(void*)>>;
86
87 // Tag specifying that an owning handle (so-called slot) of the logical resource shall be provided to the client
88 struct return_slot_t { explicit return_slot_t() = default; };
89 inline constexpr return_slot_t return_slot{};
90 // Tag specifying that the library shall own the slot resulting from the call of the function (so-called floating slot)
91 struct floating_slot_t { explicit floating_slot_t() = default; };
92 inline constexpr floating_slot_t floating_slot{};
93 // Tag denoting the assumption that the caller has already obtained message ownership
94 struct adopt_message_t { explicit adopt_message_t() = default; };
95 inline constexpr adopt_message_t adopt_message{};
96 // Tag denoting the assumption that the caller has already obtained fd ownership
97 struct adopt_fd_t { explicit adopt_fd_t() = default; };
98 inline constexpr adopt_fd_t adopt_fd{};
99 // Tag specifying that the proxy shall not run an event loop thread on its D-Bus connection.
100 // Such proxies are typically created to carry out a simple synchronous D-Bus call(s) and then are destroyed.
101 struct dont_run_event_loop_thread_t { explicit dont_run_event_loop_thread_t() = default; };
102 inline constexpr dont_run_event_loop_thread_t dont_run_event_loop_thread{};
103 // Tag denoting an asynchronous call that returns std::future as a handle
104 struct with_future_t { explicit with_future_t() = default; };
105 inline constexpr with_future_t with_future{};
106 // Tag denoting a call where the reply shouldn't be waited for
107 struct dont_expect_reply_t { explicit dont_expect_reply_t() = default; };
108 inline constexpr dont_expect_reply_t dont_expect_reply{};
109 // Tag denoting that the variant shall embed the other variant as its value, instead of creating a copy
110 struct embed_variant_t { explicit embed_variant_t() = default; };
111 inline constexpr embed_variant_t embed_variant{};
112 // Tag denoting an asynchronous call that returns an awaitable as a handle
113 struct with_awaitable_t { explicit with_awaitable_t() = default; };
114 inline constexpr with_awaitable_t with_awaitable{};
115
116 // Helper for static assert
117 template <class... T> constexpr bool always_false = false;
118
119 // Helper operator+ for concatenation of `std::array`s
120 template <typename T, std::size_t N1, std::size_t N2>
121 constexpr std::array<T, N1 + N2> operator+(std::array<T, N1> lhs, std::array<T, N2> rhs);
122
123 // Template specializations for getting D-Bus signatures from C++ types
124 template <typename T>
125 constexpr auto signature_of_v = signature_of<T>::value;
126
127 template <typename T, typename Enable>
129 {
130 static constexpr bool is_valid = false;
131 static constexpr bool is_trivial_dbus_type = false;
132
133 static constexpr void* value = []
134 {
135 // See using-sdbus-c++.md, section "Extending sdbus-c++ type system",
136 // on how to teach sdbus-c++ about your custom types
137 static_assert(always_false<T>, "Unsupported D-Bus type (specialize `signature_of` for your custom types)");
138 };
139 };
140
141 template <typename T>
142 struct signature_of<const T> : signature_of<T>
143 {};
144
145 template <typename T>
146 struct signature_of<volatile T> : signature_of<T>
147 {};
148
149 template <typename T>
150 struct signature_of<const volatile T> : signature_of<T>
151 {};
152
153 template <typename T>
155 {};
156
157 template <typename T>
159 {};
160
161 template <>
162 struct signature_of<void>
163 {
164 static constexpr std::array<char, 0> value{};
165 static constexpr bool is_valid = true;
166 static constexpr bool is_trivial_dbus_type = false;
167 };
168
169 template <>
170 struct signature_of<bool>
171 {
172 static constexpr std::array value{'b'};
173 static constexpr bool is_valid = true;
174 static constexpr bool is_trivial_dbus_type = true;
175 };
176
177 template <>
178 struct signature_of<uint8_t>
179 {
180 static constexpr std::array value{'y'};
181 static constexpr bool is_valid = true;
182 static constexpr bool is_trivial_dbus_type = true;
183 };
184
185 template <>
186 struct signature_of<int16_t>
187 {
188 static constexpr std::array value{'n'};
189 static constexpr bool is_valid = true;
190 static constexpr bool is_trivial_dbus_type = true;
191 };
192
193 template <>
194 struct signature_of<uint16_t>
195 {
196 static constexpr std::array value{'q'};
197 static constexpr bool is_valid = true;
198 static constexpr bool is_trivial_dbus_type = true;
199 };
200
201 template <>
202 struct signature_of<int32_t>
203 {
204 static constexpr std::array value{'i'};
205 static constexpr bool is_valid = true;
206 static constexpr bool is_trivial_dbus_type = true;
207 };
208
209 template <>
210 struct signature_of<uint32_t>
211 {
212 static constexpr std::array value{'u'};
213 static constexpr bool is_valid = true;
214 static constexpr bool is_trivial_dbus_type = true;
215 };
216
217 template <>
218 struct signature_of<int64_t>
219 {
220 static constexpr std::array value{'x'};
221 static constexpr bool is_valid = true;
222 static constexpr bool is_trivial_dbus_type = true;
223 };
224
225 template <>
226 struct signature_of<uint64_t>
227 {
228 static constexpr std::array value{'t'};
229 static constexpr bool is_valid = true;
230 static constexpr bool is_trivial_dbus_type = true;
231 };
232
233 template <>
234 struct signature_of<double>
235 {
236 static constexpr std::array value{'d'};
237 static constexpr bool is_valid = true;
238 static constexpr bool is_trivial_dbus_type = true;
239 };
240
241 template <>
242 struct signature_of<std::string>
243 {
244 static constexpr std::array value{'s'};
245 static constexpr bool is_valid = true;
246 static constexpr bool is_trivial_dbus_type = false;
247 };
248
249 template <>
250 struct signature_of<std::string_view> : signature_of<std::string>
251 {};
252
253 template <>
256
257 template <>
259 {};
260
261 template <std::size_t N>
262 struct signature_of<char[N]> : signature_of<std::string>
263 {};
264
265 template <std::size_t N>
266 struct signature_of<const char[N]> : signature_of<std::string>
267 {};
268
269 template <>
270 struct signature_of<BusName> : signature_of<std::string>
271 {};
272
273 template <>
275 {};
276
277 template <>
278 struct signature_of<MemberName> : signature_of<std::string>
279 {};
280
281 template <typename... ValueTypes>
282 struct signature_of<Struct<ValueTypes...>>
283 {
284 static constexpr std::array contents = (signature_of_v<ValueTypes> + ...);
285 static constexpr std::array value = std::array{'('} + contents + std::array{')'};
286 static constexpr char type_value{'r'}; /* Not actually used in signatures on D-Bus, see specs */
287 static constexpr bool is_valid = true;
288 static constexpr bool is_trivial_dbus_type = false;
289 };
290
291 template <>
293 {
294 static constexpr std::array value{'v'};
295 static constexpr bool is_valid = true;
296 static constexpr bool is_trivial_dbus_type = false;
297 };
298
299 template <typename... Elements>
300 struct signature_of<std::variant<Elements...>> : signature_of<Variant>
301 {};
302
303 template <>
305 {
306 static constexpr std::array value{'o'};
307 static constexpr bool is_valid = true;
308 static constexpr bool is_trivial_dbus_type = false;
309 };
310
311 template <>
313 {
314 static constexpr std::array value{'g'};
315 static constexpr bool is_valid = true;
316 static constexpr bool is_trivial_dbus_type = false;
317 };
318
319 template <>
321 {
322 static constexpr std::array value{'h'};
323 static constexpr bool is_valid = true;
324 static constexpr bool is_trivial_dbus_type = false;
325 };
326
327 template <typename T1, typename T2>
328 struct signature_of<DictEntry<T1, T2>>
329 {
330 static constexpr std::array value = std::array{'{'} + signature_of_v<std::tuple<T1, T2>> + std::array{'}'};
331 static constexpr char type_value{'e'}; /* Not actually used in signatures on D-Bus, see specs */
332 static constexpr bool is_valid = true;
333 static constexpr bool is_trivial_dbus_type = false;
334 };
335
336 template <typename Element, typename Allocator>
337 struct signature_of<std::vector<Element, Allocator>>
338 {
339 static constexpr std::array value = std::array{'a'} + signature_of_v<Element>;
340 static constexpr bool is_valid = true;
341 static constexpr bool is_trivial_dbus_type = false;
342 };
343
344 template <typename Element, std::size_t Size>
345 struct signature_of<std::array<Element, Size>> : signature_of<std::vector<Element>>
346 {
347 };
348
349#ifdef __cpp_lib_span
350 template <typename Element, std::size_t Extent>
351 struct signature_of<std::span<Element, Extent>> : signature_of<std::vector<Element>>
352 {
353 };
354#endif
355
356 template <typename Enum> // is_const_v and is_volatile_v to avoid ambiguity conflicts with const and volatile specializations of signature_of
357 struct signature_of<Enum, std::enable_if_t<std::is_enum_v<Enum> && !std::is_const_v<Enum> && !std::is_volatile_v<Enum>>>
358 : signature_of<std::underlying_type_t<Enum>>
359 {};
360
361 template <typename Key, typename Value, typename Compare, typename Allocator>
362 struct signature_of<std::map<Key, Value, Compare, Allocator>>
363 {
364 static constexpr std::array value = std::array{'a'} + signature_of_v<DictEntry<Key, Value>>;
365 static constexpr bool is_valid = true;
366 static constexpr bool is_trivial_dbus_type = false;
367 };
368
369 template <typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator>
370 struct signature_of<std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>>
371 : signature_of<std::map<Key, Value>>
372 {
373 };
374
375 template <typename... Types>
376 struct signature_of<std::tuple<Types...>> // A simple concatenation of signatures of _Types
377 {
378 static constexpr std::array value = (std::array<char, 0>{} + ... + signature_of_v<Types>);
379 static constexpr bool is_valid = false;
380 static constexpr bool is_trivial_dbus_type = false;
381 };
382
383 // To simplify conversions of arrays to C strings
384 template <typename T, std::size_t N>
385 constexpr auto as_null_terminated(std::array<T, N> arr)
386 {
387 return arr + std::array<T, 1>{0};
388 }
389
390 // Function traits implementation inspired by (c) kennytm,
391 // https://github.com/kennytm/utils/blob/master/traits.hpp
392 template <typename Type>
393 struct function_traits : function_traits<decltype(&Type::operator())>
394 {};
395
396 template <typename Type>
397 struct function_traits<const Type> : function_traits<Type>
398 {};
399
400 template <typename Type>
402 {};
403
404 template <typename ReturnType, typename... Args>
406 {
407 using result_type = ReturnType;
408 using arguments_type = std::tuple<Args...>;
409 using decayed_arguments_type = std::tuple<std::decay_t<Args>...>;
410
411 using function_type = ReturnType (Args...);
412
413 static constexpr std::size_t arity = sizeof...(Args);
414
415// template <size_t _Idx, typename _Enabled = void>
416// struct arg;
417//
418// template <size_t _Idx>
419// struct arg<_Idx, std::enable_if_t<(_Idx < arity)>>
420// {
421// typedef std::tuple_element_t<_Idx, arguments_type> type;
422// };
423//
424// template <size_t _Idx>
425// struct arg<_Idx, std::enable_if_t<!(_Idx < arity)>>
426// {
427// typedef void type;
428// };
429
430 template <size_t Idx>
431 struct arg
432 {
433 using type = std::tuple_element_t<Idx, std::tuple<Args...>>;
434 };
435
436 template <size_t Idx>
437 using arg_t = typename arg<Idx>::type;
438 };
439
440 template <typename ReturnType, typename... Args>
441 struct function_traits<ReturnType(Args...)> : function_traits_base<ReturnType, Args...>
442 {
443 static constexpr bool is_async = false;
444 static constexpr bool has_error_param = false;
445 };
446
447 template <typename... Args>
448 struct function_traits<void(std::optional<Error>, Args...)> : function_traits_base<void, Args...>
449 {
450 static constexpr bool has_error_param = true;
451 };
452
453 template <typename... Args>
454 struct function_traits<void(std::optional<Error>&&, Args...)> : function_traits_base<void, Args...>
455 {
456 static constexpr bool has_error_param = true;
457 };
458
459 template <typename... Args>
460 struct function_traits<void(const std::optional<Error>&, Args...)> : function_traits_base<void, Args...>
461 {
462 static constexpr bool has_error_param = true;
463 };
464
465 template <typename... Args, typename... Results>
466 struct function_traits<void(Result<Results...>, Args...)> : function_traits_base<std::tuple<Results...>, Args...>
467 {
468 static constexpr bool is_async = true;
469 using async_result_t = Result<Results...>;
470 };
471
472 template <typename... Args, typename... Results>
473 struct function_traits<void(Result<Results...>&&, Args...)> : function_traits_base<std::tuple<Results...>, Args...>
474 {
475 static constexpr bool is_async = true;
476 using async_result_t = Result<Results...>;
477 };
478
479 template <typename ReturnType, typename... Args>
480 struct function_traits<ReturnType(*)(Args...)> : function_traits<ReturnType(Args...)>
481 {};
482
483 template <typename ClassType, typename ReturnType, typename... Args>
484 struct function_traits<ReturnType(ClassType::*)(Args...)> : function_traits<ReturnType(Args...)>
485 {
486 using owner_type = ClassType &;
487 };
488
489 template <typename ClassType, typename ReturnType, typename... Args>
490 struct function_traits<ReturnType(ClassType::*)(Args...) const> : function_traits<ReturnType(Args...)>
491 {
492 using owner_type = const ClassType &;
493 };
494
495 template <typename ClassType, typename ReturnType, typename... Args>
496 struct function_traits<ReturnType(ClassType::*)(Args...) volatile> : function_traits<ReturnType(Args...)>
497 {
498 using owner_type = volatile ClassType &;
499 };
500
501 template <typename ClassType, typename ReturnType, typename... Args>
502 struct function_traits<ReturnType(ClassType::*)(Args...) const volatile> : function_traits<ReturnType(Args...)>
503 {
504 using owner_type = const volatile ClassType &;
505 };
506
507 template <typename FunctionType>
508 struct function_traits<std::function<FunctionType>> : function_traits<FunctionType>
509 {};
510
511 template <class Function>
512 constexpr auto is_async_method_v = function_traits<Function>::is_async;
513
514 template <class Function>
515 constexpr auto has_error_param_v = function_traits<Function>::has_error_param;
516
517 template <typename FunctionType>
518 using function_arguments_t = typename function_traits<FunctionType>::arguments_type;
519
520 template <typename FunctionType, size_t Idx>
521 using function_argument_t = typename function_traits<FunctionType>::template arg_t<Idx>;
522
523 template <typename FunctionType>
524 constexpr auto function_argument_count_v = function_traits<FunctionType>::arity;
525
526 template <typename FunctionType>
527 using function_result_t = typename function_traits<FunctionType>::result_type;
528
529 template <typename Function>
534
535 template <typename Function>
536 using tuple_of_function_input_arg_types_t = typename tuple_of_function_input_arg_types<Function>::type;
537
538 template <typename Function>
543
544 template <typename Function>
545 using tuple_of_function_output_arg_types_t = typename tuple_of_function_output_arg_types<Function>::type;
546
547 template <typename Function>
548 struct signature_of_function_input_arguments : signature_of<tuple_of_function_input_arg_types_t<Function>>
549 {
550 static std::string value_as_string()
551 {
552 constexpr auto signature = as_null_terminated(signature_of_v<tuple_of_function_input_arg_types_t<Function>>);
553 return signature.data();
554 }
555 };
556
557 template <typename Function>
558 inline const auto signature_of_function_input_arguments_v = signature_of_function_input_arguments<Function>::value_as_string();
559
560 template <typename Function>
561 struct signature_of_function_output_arguments : signature_of<tuple_of_function_output_arg_types_t<Function>>
562 {
563 static std::string value_as_string()
564 {
565 constexpr auto signature = as_null_terminated(signature_of_v<tuple_of_function_output_arg_types_t<Function>>);
566 return signature.data();
567 }
568 };
569
570 template <typename Function>
571 inline const auto signature_of_function_output_arguments_v = signature_of_function_output_arguments<Function>::value_as_string();
572
573 // std::future stuff for return values of async calls
574 template <typename... Args> struct future_return
575 {
576 using type = std::tuple<Args...>;
577 };
578
579 template <> struct future_return<>
580 {
581 using type = void;
582 };
583
584 template <typename Type> struct future_return<Type>
585 {
586 using type = Type;
587 };
588
589 template <typename... Args>
590 using future_return_t = typename future_return<Args...>::type;
591
592 // For awaitable return types, the same scheme from futures can be reused
593 // so just provide an alias for visual distinction between the two
594 template <typename... Args>
595 using awaitable_return_t = typename future_return<Args...>::type;
596
597 // Credit: Piotr Skotnicki (https://stackoverflow.com/a/57639506)
598 template <typename, typename>
599 constexpr bool is_one_of_variants_types = false;
600
601 template <typename... VariantTypes, typename QueriedType>
602 constexpr bool is_one_of_variants_types<std::variant<VariantTypes...>, QueriedType>
603 = (std::is_same_v<QueriedType, VariantTypes> || ...);
604
605 // Wrapper (tag) denoting we want to serialize user-defined struct
606 // into a D-Bus message as a dictionary of strings to variants.
607 template <typename Struct>
608 struct as_dictionary
609 {
610 explicit as_dictionary(const Struct& strct) : m_struct(strct) {}
611 const Struct& m_struct; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members)
612 };
613
614 template <typename Type>
615 const Type& as_dictionary_if_struct(const Type& object)
616 {
617 return object; // identity in case _Type is not struct (user-defined structs shall provide an overload)
618 }
619
620 // By default, the dict-as-struct deserialization strategy is strict.
621 // Strict means that every key of the deserialized dictionary must have its counterpart member in the struct, otherwise an exception is thrown.
622 // Relaxed means that a key that does not have a matching struct member is silently ignored.
623 // The behavior can be overridden for user-defined struct by specializing this variable template.
624 template <typename Struct>
625 constexpr auto strict_dict_as_struct_deserialization_v = true;
626
627 // By default, the struct-as-dict serialization strategy is single-level only (as opposed to nested).
628 // Single-level means that only the specific struct is serialized as a dictionary, serializing members that are structs always as structs.
629 // Nested means that the struct *and* its members that are structs are all serialized as a dictionary. If nested strategy is also
630 // defined for the nested struct, then the same behavior applies for that struct, recursively.
631 // The behavior can be overridden for user-defined struct by specializing this variable template.
632 template <typename Struct>
633 constexpr auto nested_struct_as_dict_serialization_v = false;
634
635 namespace detail
636 {
637 template <class Function, class Tuple, typename... Args, std::size_t... I>
638 constexpr decltype(auto) apply_impl( Function&& fun
639 , Result<Args...>&& res
640 , Tuple&& tuple
641 , std::index_sequence<I...> )
642 {
643 return std::forward<Function>(fun)(std::move(res), std::get<I>(std::forward<Tuple>(tuple))...);
644 }
645
646 template <class Function, class Tuple, std::size_t... I>
647 decltype(auto) apply_impl( Function&& fun
648 , std::optional<Error> err
649 , Tuple&& tuple
650 , std::index_sequence<I...> )
651 {
652 return std::forward<Function>(fun)(std::move(err), std::get<I>(std::forward<Tuple>(tuple))...);
653 }
654
655 // For non-void returning functions, apply_impl simply returns function return value (a tuple of values).
656 // For void-returning functions, apply_impl returns an empty tuple.
657 template <class Function, class Tuple, std::size_t... I>
658 constexpr decltype(auto) apply_impl( Function&& fun
659 , Tuple&& tuple
660 , std::index_sequence<I...> )
661 {
662 if constexpr (!std::is_void_v<function_result_t<Function>>)
663 return std::forward<Function>(fun)(std::get<I>(std::forward<Tuple>(tuple))...);
664 else
665 return std::forward<Function>(fun)(std::get<I>(std::forward<Tuple>(tuple))...), std::tuple<>{};
666 }
667 } // namespace detail
668
669 // Convert tuple `t' of values into a list of arguments
670 // and invoke function `f' with those arguments.
671 template <class Function, class Tuple>
672 constexpr decltype(auto) apply(Function&& fun, Tuple&& tuple)
673 {
674 return detail::apply_impl( std::forward<Function>(fun)
675 , std::forward<Tuple>(tuple)
676 , std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>{} );
677 }
678
679 // Convert tuple `t' of values into a list of arguments
680 // and invoke function `f' with those arguments.
681 template <class Function, class Tuple, typename... Args>
682 constexpr decltype(auto) apply(Function&& fun, Result<Args...>&& res, Tuple&& tuple)
683 {
684 return detail::apply_impl( std::forward<Function>(fun)
685 , std::move(res)
686 , std::forward<Tuple>(tuple)
687 , std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>{} );
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>
693 decltype(auto) apply(Function&& fun, std::optional<Error> err, Tuple&& tuple)
694 {
695 return detail::apply_impl( std::forward<Function>(fun)
696 , std::move(err)
697 , std::forward<Tuple>(tuple)
698 , std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>{} );
699 }
700
701 // Convenient concatenation of arrays
702 template <typename T, std::size_t N1, std::size_t N2>
703 constexpr std::array<T, N1 + N2> operator+(std::array<T, N1> lhs, std::array<T, N2> rhs)
704 {
705 std::array<T, N1 + N2> result{};
706
707 std::move(lhs.begin(), lhs.end(), result.begin());
708 std::move(rhs.begin(), rhs.end(), result.begin() + N1);
709
710 // std::size_t index = 0;
711 // for (auto& item : lhs) {
712 // result[index] = std::move(item);
713 // ++index;
714 // }
715 // for (auto& item : rhs) {
716 // result[index] = std::move(item);
717 // ++index;
718 // }
719
720 return result;
721 }
722
723} // namespace sdbus
724
725#endif /* SDBUS_CXX_TYPETRAITS_H_ */
std::pair< T1, T2 > DictEntry
Definition Types.h:415
Definition Types.h:228
Definition Error.h:44
Definition Types.h:251
Definition Types.h:271
Definition Message.h:81
Definition Message.h:278
Definition Message.h:303
Definition Types.h:208
Definition Message.h:335
Definition Message.h:326
Definition MethodResult.h:51
Definition Message.h:314
Definition Types.h:295
Definition Types.h:160
Definition Types.h:320
Definition Types.h:56
Definition TypeTraits.h:97
Definition TypeTraits.h:94
Definition TypeTraits.h:107
Definition TypeTraits.h:101
Definition TypeTraits.h:110
Definition TypeTraits.h:91
Definition TypeTraits.h:432
Definition TypeTraits.h:406
Definition TypeTraits.h:394
Definition TypeTraits.h:575
Definition TypeTraits.h:88
Definition TypeTraits.h:129
Definition TypeTraits.h:531
Definition TypeTraits.h:113
Definition TypeTraits.h:104