-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathtypelist.hpp
More file actions
155 lines (125 loc) · 3.49 KB
/
Copy pathtypelist.hpp
File metadata and controls
155 lines (125 loc) · 3.49 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
#pragma once
#include <cstdint>
#include <tuple>
namespace tl {
// forward
template<typename... TS>
struct type_list;
// type_list_item
template<typename Type, uint64_t index_>
struct type_list_item
{
using type = Type;
static constexpr const uint64_t index = index_;
};
// get
template<uint64_t index, typename T, typename... TS>
struct _get_nth_type_inner;
template<typename T, typename... TS>
struct _get_nth_type_inner<0, T, TS...>
{
using type = T;
};
template<uint64_t index, typename T, typename... TS>
struct _get_nth_type_inner
{
using type = typename _get_nth_type_inner<index - 1, TS...>::type;
};
template<uint64_t index, typename... TS>
struct _get_nth_type
{
using type = typename _get_nth_type_inner<index, TS...>::type;
};
template<uint64_t index>
struct _get_nth_type<index>
{};
// enumerate
template<uint64_t index, typename T, typename... TS>
struct _enumerate_impl_inner;
template<uint64_t index, typename... TS>
struct _enumerate_impl
{
using type = typename _enumerate_impl_inner<index, TS...>::type;
};
template<uint64_t index>
struct _enumerate_impl<index>
{
using type = type_list<>;
};
template<uint64_t index, typename T, typename... TS>
struct _enumerate_impl_inner
{
using type =
typename _enumerate_impl<index + 1, TS...>::type::template prepend<
type_list_item<T, index>>;
};
// keep
template<typename L, uint64_t i, uint64_t... indices>
struct _keep_impl_inner;
template<typename L, uint64_t... indices>
struct _keep_impl
{
using type = typename _keep_impl_inner<L, indices...>::type;
};
template<typename L>
struct _keep_impl<L>
{
using type = type_list<>;
};
template<typename L, uint64_t i, uint64_t... indices>
struct _keep_impl_inner
{
using _tail_type = typename _keep_impl<L, indices...>::type;
using _ith_type = typename L::template get<i>;
using type = typename _tail_type::template prepend<_ith_type>;
};
template<typename... TS>
struct type_list
{
// Compile time operations
template<template<typename> class W>
using wrap = type_list<W<TS>...>;
template<template<typename> class M>
using map = type_list<typename M<TS>::type...>;
template<typename T>
using append = type_list<TS..., T>;
template<typename T>
using prepend = type_list<T, TS...>;
template<uint64_t index>
using get = typename _get_nth_type<index, TS...>::type;
using enumerate = typename _enumerate_impl<0, TS...>::type;
template<uint64_t... indices>
using keep = typename _keep_impl<type_list<TS...>, indices...>::type;
// Runtime operations
template<typename Func>
static void _for_each_helper(const Func& func)
{
// FIXME: so ugly :(
auto wrapper = [&](auto t) {
func(t);
return 1;
};
std::make_tuple(wrapper(TS())...);
}
template<typename Func>
static void for_each(const Func& func)
{
enumerate::template _for_each_helper<Func>(func);
}
template<template<typename...> class U, typename Func>
static auto _for_each_and_collect_helper(const Func& func)
-> U<decltype(func(TS()))...>
{
return U<decltype(func(TS()))...>(func(TS())...);
}
template<template<typename...> class U, typename Func>
static auto for_each_and_collect(const Func& func)
{
return enumerate::template _for_each_and_collect_helper<U, Func>(func);
}
// Conversion
template<template<typename...> class U>
using to = U<TS...>;
using to_tuple = to<std::tuple>;
};
}