-
Notifications
You must be signed in to change notification settings - Fork 17
/
type_traits.hpp
133 lines (107 loc) · 7.14 KB
/
type_traits.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#ifndef MXX_EXPERIMENTAL_TYPE_TRAITS
#define MXX_EXPERIMENTAL_TYPE_TRAITS
#include <type_traits>
#include <tuple> // for all_are tuple specializations
#define MXX_GENERATE_HAS_STATIC_MEMBER_OBJECT(MEMBER_NAME) \
template <typename T, typename Enable = void> \
struct has_static_member_object_ ## MEMBER_NAME : std::false_type {}; \
\
template <typename T> \
struct has_static_member_object_ ## MEMBER_NAME <T, typename std::enable_if< \
!std::is_member_pointer<decltype(&T:: MEMBER_NAME )>::value \
&& !std::is_function<decltype(T :: MEMBER_NAME )>::value>::type> \
: std::true_type {}; \
#define MXX_GENERATE_HAS_MEMBER_OBJECT(MEMBER_NAME) \
template <typename T, typename Enable = void> \
struct has_member_object_ ## MEMBER_NAME : std::false_type {}; \
\
template <typename T> \
struct has_member_object_ ## MEMBER_NAME <T, typename std::enable_if< \
std::is_member_object_pointer<decltype(&T:: MEMBER_NAME )>::value>::type> \
: std::true_type {}; \
\
#define MXX_GENERATE_HAS_STATIC_MEMBER_FUNCTION(MEMBER_NAME) \
template <typename T, typename Sig = std::false_type, typename Enable = void> \
struct has_static_member_function_ ## MEMBER_NAME : std::false_type {}; \
\
template <typename T> \
struct has_static_member_function_ ## MEMBER_NAME \
<T, std::false_type, typename std::enable_if< \
std::is_function<decltype(T:: MEMBER_NAME )>::value>::type> \
: std::true_type {}; \
\
template <typename T, typename R, typename... Args> \
struct has_static_member_function_ ## MEMBER_NAME \
<T, R(Args...), typename std::enable_if< \
std::is_same<decltype(static_cast<R(*)(Args...)>(&T:: MEMBER_NAME )), \
R(*)(Args...)>::value>::type> \
: std::true_type {}; \
#define MXX_GENERATE_HAS_MEMBER_FUNCTION(MEMBER_NAME) \
template <typename T, typename Sig = std::false_type, typename Enable = void> \
struct has_member_function_ ## MEMBER_NAME : std::false_type {}; \
\
template <typename T> \
struct has_member_function_ ## MEMBER_NAME \
<T, std::false_type, typename std::enable_if< \
std::is_member_function_pointer<decltype(&T:: MEMBER_NAME )>::value>::type>\
: std::true_type {}; \
\
template <typename T, typename Func> \
struct has_member_function_ ## MEMBER_NAME <T, Func, typename std::enable_if< \
std::is_member_function_pointer< \
decltype(static_cast<Func T::*>(&T:: MEMBER_NAME ))>::value>::type> \
: std::true_type {}; \
\
#define MXX_GENERATE_HAS_MEMBER_TYPEDEF(TYPE_NAME) \
template <typename T, typename Enable = void> \
struct has_member_typedef_ ## TYPE_NAME : std::false_type {}; \
\
template <typename T> \
struct has_member_typedef_ ## TYPE_NAME <T, typename std::enable_if< \
!std::is_same<typename T:: TYPE_NAME ,void>::value>::type> \
: std::true_type {}; \
#define MXX_GENERATE_MEMBER_TRAITS(MEMBER_NAME) \
MXX_GENERATE_HAS_MEMBER_OBJECT(MEMBER_NAME) \
MXX_GENERATE_HAS_STATIC_MEMBER_OBJECT(MEMBER_NAME) \
MXX_GENERATE_HAS_MEMBER_FUNCTION(MEMBER_NAME) \
MXX_GENERATE_HAS_STATIC_MEMBER_FUNCTION(MEMBER_NAME) \
MXX_GENERATE_HAS_MEMBER_TYPEDEF(MEMBER_NAME) \
/*
template <typename T, typename Enable = void>
struct has_datatype_constexpr : std::false_type {};
template <typename T>
struct has_datatype_constexpr<T,typename std::enable_if<
std::is_member_object_pointer<typename std::tuple_element<0,decltype(T::datatype)>::type>::value
// the standard § 4.11 [conv.mem]:
// guarantuees that `valid` pointer-to-member are always distinct from the
// `null pointer to member`
&& std::get<0>(T::datatype) != nullptr
>::type> : std::true_type {};
*/
template <template <typename> class Trait, typename... Types>
struct all_are;
template <template<typename> class Trait, typename Type, typename... Types>
struct all_are<Trait, Type, Types...> : std::integral_constant<bool,
Trait<Type>::value && all_are<Trait, Types...>::value> {};
template <template<typename> class Trait, typename Type>
struct all_are<Trait, Type> : std::integral_constant<bool,
Trait<Type>::value> {};
template <template <typename> class Trait, typename... Types>
struct any_are;
template <template<typename> class Trait, typename Type, typename... Types>
struct any_are<Trait, Type, Types...> : std::integral_constant<bool,
Trait<Type>::value || any_are<Trait, Types...>::value> {};
template <template<typename> class Trait, typename Type>
struct any_are<Trait, Type> : std::integral_constant<bool,
Trait<Type>::value> {};
// specialization for std::tuple
template <template<typename> class Trait, typename... Types>
struct all_are<Trait, std::tuple<Types...>> : std::integral_constant<bool,
all_are<Trait, Types...>::value> {};
template <typename... T>
struct are_all_member_pointer : std::false_type {};
template <typename... Types>
struct are_all_member_pointer<std::tuple<Types...>> : all_are<std::is_member_pointer, Types...> {};
template <typename... Types>
struct are_all_member_pointer<const std::tuple<Types...>> : all_are<std::is_member_pointer, Types...> {};
#endif // MXX_EXPERIMENTAL_TYPE_TRAITS