qb  2.0.0.0
C++17 Actor Framework
qb Issue Watch Star Fork Follow @isndev
Loading...
Searching...
No Matches
type_traits.h
Go to the documentation of this file.
1
19
20#ifndef QB_TYPE_TRAITS_H
21#define QB_TYPE_TRAITS_H
22#include <string_view>
23#include <type_traits>
24#include <utility>
25#include <valarray>
26
34template <typename T>
35inline std::remove_reference_t<T> &&
36mv(T &&t) noexcept {
37 return static_cast<std::remove_reference_t<T> &&>(t);
38}
39
47template <typename T>
48inline T &&
49fwd(std::remove_reference_t<T> &t) noexcept {
50 return std::forward<T>(t);
51}
52
60template <typename T>
61inline T &&
62fwd(std::remove_reference_t<T> &&t) noexcept {
63 return std::forward<T>(t);
64}
65
66namespace qb {
67
79template <typename T>
80struct crtp {
86 inline T &
87 impl() noexcept {
88 return static_cast<T &>(*this);
89 }
90
96 inline T const &
97 impl() const noexcept {
98 return static_cast<T &>(*this);
99 }
100};
101
102namespace detail {
104struct sfinae_base {
105 using yes = char;
106 using no = yes[2];
107};
108
114template <typename T>
115struct has_const_iterator : private sfinae_base {
116private:
117 template <typename C>
118 static yes &test(typename C::const_iterator *);
119 template <typename C>
120 static no &test(...);
121
122public:
123 static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
124 using type = T;
125};
126
134template <typename T>
135struct has_begin_end : private sfinae_base {
136private:
137 template <typename C>
138 static yes &
139 f(typename std::enable_if<std::is_same<
140 decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::begin)),
141 typename C::const_iterator (C::*)() const>::value>::type *);
142
143 template <typename C>
144 static no &f(...);
145
146 template <typename C>
147 static yes &
148 g(typename std::enable_if<
149 std::is_same<
150 decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::end)),
151 typename C::const_iterator (C::*)() const>::value,
152 void>::type *);
153
154 template <typename C>
155 static no &g(...);
156
157public:
159 static bool const beg_value = sizeof(f<T>(nullptr)) == sizeof(yes);
160
162 static bool const end_value = sizeof(g<T>(nullptr)) == sizeof(yes);
163};
164
171template <typename T, typename U = void>
172struct is_mappish_impl : std::false_type {};
173
179template <typename T>
181 T, std::void_t<
182 typename T::key_type, typename T::mapped_type,
183 decltype(std::declval<T &>()[std::declval<const typename T::key_type &>()])>>
184 : std::true_type {};
185
186} // namespace detail
187
198template <typename T>
200 : public std::integral_constant<bool, detail::has_const_iterator<T>::value &&
201 detail::has_begin_end<T>::beg_value &&
202 detail::has_begin_end<T>::end_value> {};
203
210template <typename T, std::size_t N>
211struct is_container<T[N]> : std::true_type {};
212
218template <std::size_t N>
219struct is_container<char[N]> : std::false_type {};
220
226template <typename T>
227struct is_container<std::valarray<T>> : std::true_type {};
228
235template <typename T1, typename T2>
236struct is_container<std::pair<T1, T2>> : std::true_type {};
237
243template <typename... Args>
244struct is_container<std::tuple<Args...>> : std::true_type {};
245
255template <typename T, bool cond>
258 typedef T type;
260 constexpr static bool value = false;
261};
262
268template <typename T>
269struct remove_reference_if<T, true> {
271 typedef typename std::remove_reference<T>::type type;
273 constexpr static bool value = true;
274};
275
285template <typename T>
287
295template <typename...>
296struct is_pair : std::false_type {};
297
304template <typename T, typename U>
305struct is_pair<std::pair<T, U>> : std::true_type {};
306
314template <typename...>
315using Void = void;
316
326template <typename T, typename U = Void<>>
327struct is_inserter : std::false_type {};
328
334template <typename T>
336 T, typename std::enable_if<!std::is_void<typename T::container_type>::value>::type>
337 : std::true_type {};
338
349template <typename Iter, typename T = Void<>>
352 using type = typename std::iterator_traits<Iter>::value_type;
353};
354
362template <typename Iter>
363struct iterator_type<Iter, typename std::enable_if<is_inserter<Iter>::value>::type> {
365 using type = typename std::decay<typename Iter::container_type::value_type>::type;
366};
367
378template <typename Iter, typename T = Void<>>
379struct is_terator : std::false_type {};
380
386template <typename Iter>
387struct is_terator<Iter, typename std::enable_if<is_inserter<Iter>::value>::type>
388 : std::true_type {};
389
397template <typename Iter>
398struct is_terator<Iter,
399 typename std::enable_if<!std::is_void<
400 typename std::iterator_traits<Iter>::value_type>::value>::type>
401 : std::integral_constant<bool, !std::is_convertible<Iter, std::string_view>::value> {
402};
403
411template <typename T>
412struct is_map_iterator : is_pair<typename iterator_type<T>::type> {};
413
421template <typename T, typename = Void<>>
422struct has_push_back : std::false_type {};
423
429template <typename T>
431 T, typename std::enable_if<std::is_void<decltype(std::declval<T>().push_back(
432 std::declval<typename T::value_type>()))>::value>::type> : std::true_type {};
433
441template <typename T, typename = Void<>>
442struct has_insert : std::false_type {};
443
449template <typename T>
451 T, typename std::enable_if<std::is_same<
452 decltype(std::declval<T>().insert(std::declval<typename T::const_iterator>(),
453 std::declval<typename T::value_type>())),
454 typename T::iterator>::value>::type> : std::true_type {};
455
463template <typename T>
465 : std::integral_constant<
466 bool, has_push_back<T>::value &&
467 !std::is_same<typename std::decay<T>::type, std::string>::value> {};
468
476template <typename T>
478 : std::integral_constant<bool, has_insert<T>::value && !has_push_back<T>::value> {};
479
488template <size_t num, typename... T>
489struct nth_type;
490
501template <size_t num, typename T, typename... Y>
502struct nth_type<num, T, Y...> : nth_type<num - 1, Y...> {};
503
513template <typename T, typename... Y>
514struct nth_type<0, T, Y...> {
515 typedef T type;
516};
517
526template <size_t... Indexes>
528 enum { size = sizeof...(Indexes) };
529};
530
539template <size_t num, typename tp = indexes_tuple<>>
541
550template <size_t num, size_t... Indexes>
551struct index_builder<num, indexes_tuple<Indexes...>>
552 : index_builder<num - 1, indexes_tuple<Indexes..., sizeof...(Indexes)>> {};
553
561template <size_t... Indexes>
562struct index_builder<0, indexes_tuple<Indexes...>> {
563 typedef indexes_tuple<Indexes...> type;
564 enum { size = sizeof...(Indexes) };
565};
566
581struct expand {
591 template <typename... U>
592 expand(U const &...) {}
593};
594
595} // namespace qb
596
604template <typename... Args>
605struct ambiguate : public Args... {};
606
615template <typename A, typename = void>
616struct got_type : std::false_type {};
617
623template <typename A>
624struct got_type<A> : std::true_type {
626 typedef A type;
627};
628
635template <typename T, T>
636struct sig_check : std::true_type {};
637
644template <typename Alias, typename AmbiguitySeed>
646 template <typename C>
647 static char (&f(decltype(&C::value)))[1];
648 template <typename C>
649 static char (&f(...))[2];
650
651 // Make sure the member name is consistently spelled the same.
652 static_assert(
653 (sizeof(f<AmbiguitySeed>(0)) == 1),
654 "Member name specified in AmbiguitySeed is different from member name specified "
655 "in Alias, or wrong Alias/AmbiguitySeed has been specified.");
656
658 static bool const value = sizeof(f<Alias>(0)) == 2;
659};
660
669#define CREATE_MEMBER_CHECK(member) \
670 \
671 template <typename T, typename = std::true_type> \
672 struct Alias_##member; \
673 \
674 template <typename T> \
675 struct Alias_##member< \
676 T, std::integral_constant<bool, got_type<decltype(&T::member)>::value>> { \
677 static const decltype(&T::member) value; \
678 }; \
679 \
680 struct AmbiguitySeed_##member { \
681 char member; \
682 }; \
683 \
684 template <typename T> \
685 struct has_member_##member { \
686 static const bool value = \
687 has_member<Alias_##member<ambiguate<T, AmbiguitySeed_##member>>, \
688 Alias_##member<AmbiguitySeed_##member>>::value; \
689 }
690
698#define CREATE_MEMBER_VAR_CHECK(var_name) \
699 \
700 template <typename T, typename = std::true_type> \
701 struct has_member_var_##var_name : std::false_type {}; \
702 \
703 template <typename T> \
704 struct has_member_var_##var_name< \
705 T, std::integral_constant< \
706 bool, !std::is_member_function_pointer<decltype(&T::var_name)>::value>> \
707 : std::true_type {}
708
716#define CREATE_MEMBER_CLASS_CHECK(class_name) \
717 \
718 template <typename T, typename = std::true_type> \
719 struct has_member_class_##class_name : std::false_type {}; \
720 \
721 template <typename T> \
722 struct has_member_class_##class_name< \
723 T, std::integral_constant<bool, std::is_class<typename got_type< \
724 typename T::class_name>::type>::value>> \
725 : std::true_type {}
726
734#define CREATE_MEMBER_UNION_CHECK(union_name) \
735 \
736 template <typename T, typename = std::true_type> \
737 struct has_member_union_##union_name : std::false_type {}; \
738 \
739 template <typename T> \
740 struct has_member_union_##union_name< \
741 T, std::integral_constant<bool, std::is_union<typename got_type< \
742 typename T::union_name>::type>::value>> \
743 : std::true_type {}
744
752#define CREATE_MEMBER_ENUM_CHECK(enum_name) \
753 \
754 template <typename T, typename = std::true_type> \
755 struct has_member_enum_##enum_name : std::false_type {}; \
756 \
757 template <typename T> \
758 struct has_member_enum_##enum_name< \
759 T, \
760 std::integral_constant< \
761 bool, std::is_enum<typename got_type<typename T::enum_name>::type>::value>> \
762 : std::true_type {}
763
772#define CREATE_MEMBER_FUNC_CHECK(func) \
773 template <typename T> \
774 struct has_member_func_##func { \
775 static const bool value = \
776 has_member_##func<T>::value && !has_member_var_##func<T>::value && \
777 !has_member_class_##func<T>::value && !has_member_union_##func<T>::value && \
778 !has_member_enum_##func<T>::value; \
779 }
780
788#define CREATE_MEMBER_CHECKS(member) \
789 CREATE_MEMBER_CHECK(member); \
790 CREATE_MEMBER_VAR_CHECK(member); \
791 CREATE_MEMBER_CLASS_CHECK(member); \
792 CREATE_MEMBER_UNION_CHECK(member); \
793 CREATE_MEMBER_ENUM_CHECK(member); \
794 CREATE_MEMBER_FUNC_CHECK(member)
795
804#define GENERATE_HAS_METHOD(method) \
805 \
806 template <typename C, typename Ret, typename... Args> \
807 class has_method_##method { \
808 template <typename T> \
809 static constexpr auto check(T *) -> typename std::is_same< \
810 decltype(std::declval<T>().method(std::declval<Args>()...)), Ret>::type; \
811 \
812 template <typename> \
813 static constexpr std::false_type check(...); \
814 \
815 typedef decltype(check<C>(0)) type; \
816 \
817 public: \
818 static constexpr bool value = type::value; \
819 };
820
829#define GENERATE_HAS_MEMBER(member) \
830 \
831 template <class T> \
832 class HasMember_##member { \
833 private: \
834 using Yes = char[2]; \
835 using No = char[1]; \
836 \
837 struct Fallback { \
838 int member; \
839 }; \
840 struct Derived \
841 : T \
842 , Fallback {}; \
843 \
844 template <class U> \
845 static No &test(decltype(U::member) *); \
846 template <typename U> \
847 static Yes &test(U *); \
848 \
849 public: \
850 static constexpr bool RESULT = sizeof(test<Derived>(nullptr)) == sizeof(Yes); \
851 }; \
852 \
853 template <class T> \
854 struct has_member_##member \
855 : public std::integral_constant<bool, HasMember_##member<T>::RESULT> {};
856
865#define GENERATE_HAS_MEMBER_TYPE(Type) \
866 \
867 template <class T> \
868 class HasMemberType_##Type { \
869 private: \
870 using Yes = char[2]; \
871 using No = char[1]; \
872 \
873 struct Fallback { \
874 struct Type {}; \
875 }; \
876 struct Derived \
877 : T \
878 , Fallback {}; \
879 \
880 template <class U> \
881 static No &test(typename U::Type *); \
882 template <typename U> \
883 static Yes &test(U *); \
884 \
885 public: \
886 static constexpr bool RESULT = sizeof(test<Derived>(nullptr)) == sizeof(Yes); \
887 }; \
888 \
889 template <class T> \
890 struct has_member_type_##Type \
891 : public std::integral_constant<bool, HasMemberType_##Type<T>::RESULT> {};
892
893// Create member check traits for commonly used members
894CREATE_MEMBER_CHECKS(is_alive);
895CREATE_MEMBER_CHECKS(is_broadcast);
896CREATE_MEMBER_CHECKS(is_valid);
897CREATE_MEMBER_CHECKS(disconnect);
898
899// Create method check traits for commonly used methods
903
904#endif // QB_TYPE_TRAITS_H
T && fwd(std::remove_reference_t< T > &t) noexcept
Alias for std::forward with a concise syntax (lvalue overload).
Definition type_traits.h:49
std::remove_reference_t< T > && mv(T &&t) noexcept
Alias for std::move with a concise syntax.
Definition type_traits.h:36
void Void
Helper alias to void for SFINAE purposes.
Definition type_traits.h:315
Helper class to force ambiguity of class members.
Definition type_traits.h:605
A type
The type that was found.
Definition type_traits.h:626
Type trait to check if a type exists.
Definition type_traits.h:616
Type trait to check if a type has a specific member.
Definition type_traits.h:645
static bool const value
Whether the member exists.
Definition type_traits.h:658
Base class for implementing the Curiously Recurring Template Pattern (CRTP).
Definition type_traits.h:80
T & impl() noexcept
Access the derived class instance.
Definition type_traits.h:87
T const & impl() const noexcept
Access the derived class instance (const version)
Definition type_traits.h:97
Type trait to detect whether T has begin() and end() methods.
Definition type_traits.h:135
static bool const beg_value
Whether the type has a valid begin() method.
Definition type_traits.h:159
static bool const end_value
Whether the type has a valid end() method.
Definition type_traits.h:162
Type trait to detect whether T has a const_iterator type.
Definition type_traits.h:115
Internal implementation to detect map-like types.
Definition type_traits.h:172
expand(U const &...)
Constructor that expands a parameter pack.
Definition type_traits.h:592
Type trait to check if a type T has an insert(T::const_iterator, T::value_type) member function.
Definition type_traits.h:442
Type trait to check if a type T has a push_back(T::value_type) member function.
Definition type_traits.h:422
indexes_tuple< Indexes... > type
The final tuple type with all indices.
Definition type_traits.h:563
Generates a compile-time sequence of indices as an indexes_tuple.
Definition type_traits.h:540
Represents a compile-time tuple of size_t indexes.
Definition type_traits.h:527
Type trait to check if type T is an associative container.
Definition type_traits.h:478
Type trait to check if a type T is a container.
Definition type_traits.h:202
Type trait to check if a type T is an inserter iterator (e.g., std::back_inserter).
Definition type_traits.h:327
Type trait to check if an iterator T points to map elements (i.e., std::pair).
Definition type_traits.h:412
Type trait to check if a type T is map-like.
Definition type_traits.h:286
Type trait to check if a type is a std::pair.
Definition type_traits.h:296
Type trait to check if type T is a sequence container.
Definition type_traits.h:467
Type trait to check if a type Iter is an iterator.
Definition type_traits.h:379
typename std::decay< typename Iter::container_type::value_type >::type type
The value type of the underlying container.
Definition type_traits.h:365
Type trait to extract the value_type from an iterator Iter.
Definition type_traits.h:350
typename std::iterator_traits< Iter >::value_type type
The value type of the iterator.
Definition type_traits.h:352
T type
The type at the specified index.
Definition type_traits.h:515
Metafunction for selecting the Nth type in a variadic template parameter pack.
Definition type_traits.h:489
static constexpr bool value
Whether reference was removed.
Definition type_traits.h:273
std::remove_reference< T >::type type
Resulting type with reference removed.
Definition type_traits.h:271
Conditionally removes a reference from type T if cond is true.
Definition type_traits.h:256
static constexpr bool value
Whether reference was removed.
Definition type_traits.h:260
T type
Resulting type (unchanged if condition is false)
Definition type_traits.h:258
Template struct used for type identification in the event system.
Definition Event.h:53
Helper for signature checking.
Definition type_traits.h:636
#define GENERATE_HAS_METHOD(method)
Macro to generate a type trait to check for a method with a specific signature.
Definition type_traits.h:804
#define CREATE_MEMBER_CHECKS(member)
Macro to create all member check variants for a single member name.
Definition type_traits.h:788