-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtype_utils.hpp
More file actions
196 lines (167 loc) · 4.38 KB
/
Copy pathtype_utils.hpp
File metadata and controls
196 lines (167 loc) · 4.38 KB
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#ifndef TYPE_UTILS_HPP
#define TYPE_UTILS_HPP
#include <cstddef>
#include <type_traits>
namespace FunctionalCpp
{
///
// inner type of any parametric class
template < class T >
struct inner_type
{
using type = T;
};
template < template < class > class Tt, class T >
struct inner_type< Tt< T > >
{
using type = T;
};
template < template < class, class... > class Tt, class T, class... Ts >
struct inner_type< Tt< T, Ts... > >
{
using type = T;
};
///
// rebind a context or container to another parameter
template < class Cp, class T >
struct rebind_type
{
using type = Cp;
};
template < template < class > class Cp, class U, class T >
struct rebind_type< Cp< T >, U >
{
using type = Cp< U >;
};
template < template < class... > class Cp, class U, class T, class... Ts >
struct rebind_type< Cp< T, Ts... >, U >
{
using type = Cp< U, Ts... >;
};
///
// try to find the value type from containers
template < class C >
struct value_type
{
typedef typename C::value_type type;
};
template < class T, int N >
struct value_type< T[N] >
{
typedef T type;
};
template < class T >
struct value_type< T* >
{
typedef T type;
};
///
// nth element from an template arguments pack
template < std::size_t N, class T, class... Ts >
struct get_type
{
using type = typename get_type< N - 1, Ts... >::type;
};
template < class T, class... Ts >
struct get_type< 0, T, Ts... >
{
using type = T;
};
///
// from a pack of varidic type create a type list
struct type_empty_list
{
constexpr static size_t size = 0;
};
template <class A1, class... As>
struct type_list
{
using head = A1;
using tail = type_list<As...>;
constexpr static size_t size = 1 + sizeof...(As);
};
template <class A1>
struct type_list<A1>
{
using head = A1;
using tail = type_empty_list;
constexpr static size_t size = 1;
};
///
// apppend a type to a type list
template <class Append, class TypeList, size_t N = TypeList::size>
struct append_type
{
using list = typename append_type<Append, typename TypeList::tail, N-1>::list;
using head = typename list::head;
using tail = typename list::tail;
constexpr static size_t size = 1+ TypeList::size;
};
template <class Append, class TypeList>
struct append_type<Append, TypeList, 1>
{
using list = TypeList;
using head = typename TypeList::head;
using tail = type_list<Append>;
constexpr static size_t size = 1+ TypeList::size;
};
///
// prepend a type to a type list
template <class Prepend, class TypeList>
struct prepend_type: type_list<Prepend>
{
using head = Prepend;
using tail = TypeList;
constexpr static size_t size = 1 + TypeList::size;
};
///
// drop remove the first N elements from a type list
template <size_t N, class TypeList>
struct drop_types
{
static_assert(N < TypeList::size, "drop_types<N, TypeList>: Dropping more types than the size of the list.");
using list = typename drop_types<N-1, typename TypeList::tail>::list;
using head = typename list::head;
using tail = typename list::tail;
constexpr static size_t size = list::size;
};
template <class TypeList>
struct drop_types<0, TypeList>
{
using list = TypeList;
using head = typename TypeList::head;
using tail = typename TypeList::tail;
constexpr static size_t size = TypeList::size;
};
///
// take the N first elements from a type list
template <size_t N, class TypeList>
struct take_types
{
static_assert(N < TypeList::size, "taking_types<N, TypeList>: Taking more types than the size of the list.");
using list = TypeList;
using head = typename TypeList::head;
using tail = typename take_types<N - 1, typename TypeList::tail>::list;
constexpr static size_t size = N;
};
template <class TypeList>
struct take_types<0, TypeList>
{
using head = typename TypeList::head;
using tail = type_empty_list;
constexpr static size_t size = 1;
};
///
// nth element from a type list
template < size_t N, class TypeList >
struct get_type_at
{
using type = typename get_type_at< N - 1, typename TypeList::tail >::type;
};
template < class TypeList>
struct get_type_at< 0, TypeList >
{
using type = typename TypeList::head;
};
} // end namespace FunctionalCpp
#endif // TYPE_UTILS_HPP