-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontainer_traits.hpp
146 lines (111 loc) · 4.01 KB
/
container_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
134
135
136
137
138
139
140
141
142
143
144
145
146
#pragma once
#include <type_traits>
#include <utility>
namespace traits::container {
template <class Ty, class = void>
struct is_iterable : std::false_type {};
template <class Ty>
struct is_iterable<Ty,
std::void_t<decltype(std::declval<Ty>().begin()),
decltype(std::declval<Ty>().end())>>
: std::true_type {};
template <class Ty>
inline constexpr bool is_iterable_v = is_iterable<Ty>::value;
template <class Ty>
struct range_based_for_supporting {
static constexpr bool value{
std::disjunction_v<std::is_array<Ty>, is_iterable<Ty>>};
};
template <class Ty>
inline constexpr bool range_based_for_supporting_v =
range_based_for_supporting<Ty>::value;
template <class Ty, class = void>
struct has_traits : std::false_type {};
template <class Ty>
struct has_traits<Ty, std::void_t<typename Ty::traits_type>> : std::true_type {
};
template <class Ty>
inline constexpr bool has_traits_v = has_traits<Ty>::value;
template <class Ty, class = void>
struct has_value_type : std::false_type {};
template <class Ty>
struct has_value_type<Ty, std::void_t<typename Ty::value_type>>
: std::true_type {};
template <class Ty>
inline constexpr bool has_value_type_v = has_value_type<Ty>::value;
template <class Ty, class = void>
struct has_key_type : std::false_type {};
template <class Ty>
struct has_key_type<Ty, std::void_t<typename Ty::key_type>> : std::true_type {};
template <class Ty>
inline constexpr bool has_key_type_v = has_key_type<Ty>::value;
template <class Ty, class = void>
struct has_mapped_type : std::false_type {};
template <class Ty>
struct has_mapped_type<Ty, std::void_t<typename Ty::mapped_type>>
: std::true_type {};
template <class Ty>
inline constexpr bool has_mapped_type_v = has_mapped_type<Ty>::value;
template <class Ty>
struct is_container {
static constexpr bool value{
std::conjunction_v<has_value_type<Ty>, std::negation<has_traits<Ty>>>};
};
template <class Ty>
inline constexpr bool is_container_v = is_container<Ty>::value;
template <class Ty>
struct is_set {
static constexpr bool value{
std::conjunction_v<is_container<Ty>,
has_key_type<Ty>,
std::negation<has_mapped_type<Ty>>>};
};
template <class Ty>
inline constexpr bool is_set_v = is_set<Ty>::value;
template <class Ty>
struct is_map {
static constexpr bool value{std::conjunction_v<is_container<Ty>,
has_key_type<Ty>,
has_mapped_type<Ty>>};
};
template <class Ty>
inline constexpr bool is_map_v = is_map<Ty>::value;
template <class Ty, class = void>
struct has_reserve : std::false_type {};
template <class Ty>
struct has_reserve<
Ty,
std::void_t<decltype(std::declval<Ty>().reserve(std::declval<size_t>()))>>
: std::true_type {};
template <class Ty>
inline constexpr bool has_reserve_v = has_reserve<Ty>::value;
template <class Ty, class = void>
struct is_linear : std::false_type {};
template <class Ty>
struct is_linear<Ty,
std::void_t<decltype(std::declval<Ty>().push_back(
std::declval<typename Ty::value_type>()))>>
: std::true_type {};
template <class Ty>
inline constexpr bool is_linear_v = is_linear<Ty>::value;
template <class Ty, class = void>
struct is_associative : std::false_type {};
template <class Ty>
struct is_associative<Ty,
std::void_t<decltype(std::declval<Ty>().insert(
std::declval<typename Ty::value_type>()))>>
: std::true_type {};
template <class Ty>
inline constexpr bool is_associative_v = is_associative<Ty>::value;
template <class Ty, class = void>
struct data_type {
using type = typename Ty::value_type;
};
template <class Ty>
struct data_type<Ty,
std::void_t<typename Ty::key_type, typename Ty::mapped_type>> {
using type = std::pair<typename Ty::key_type, typename Ty::mapped_type>;
};
template <class Ty>
using data_type_t = typename data_type<Ty>::type;
} // namespace traits::container