BitShares-Core  6.1.0
BitShares blockchain implementation and command-line interface software
typelist.hpp
Go to the documentation of this file.
1 #pragma once
2 
8 #include <type_traits>
9 #include <functional>
10 
11 namespace fc {
12 
14 namespace typelist {
15 
16 // Forward declare the list so impl can see it
17 template<typename...> struct list;
18 
19 namespace impl {
20 using typelist::list;
21 
22 template<typename, template<typename...> class> struct apply;
23 template<typename... Ts, template<typename...> class Delegate>
24 struct apply<list<Ts...>, Delegate> { using type = Delegate<Ts...>; };
25 
26 template<typename... Ts>
27 struct length;
28 template<> struct length<> { constexpr static std::size_t value = 0; };
29 template<typename T, typename... Ts>
30 struct length<T, Ts...> { constexpr static std::size_t value = length<Ts...>::value+1; };
31 
32 template<typename...> struct concat;
33 template<typename... OldTypes, typename... NewTypes>
34 struct concat<list<OldTypes...>, list<NewTypes...>> {
35  using type = list<OldTypes..., NewTypes...>;
36 };
37 template<typename... OldTypes, typename... NewTypes, typename NextList, typename... Lists>
38 struct concat<list<OldTypes...>, list<NewTypes...>, NextList, Lists...> {
39  using type = typename concat<list<OldTypes..., NewTypes...>, NextList, Lists...>::type;
40 };
41 
42 template<std::size_t count> struct make_sequence;
43 template<> struct make_sequence<0> { using type = list<>; };
45 template<std::size_t count>
46 struct make_sequence {
47  using type = typename concat<typename make_sequence<count-1>::type,
48  list<std::integral_constant<std::size_t, count-1>>>::type;
49 };
50 
51 template<typename, typename> struct transform;
52 template<typename... List, typename Transformer>
53 struct transform<list<List...>, Transformer> {
55 };
56 
57 template<typename Search, typename List> struct index_of;
58 template<typename Search> struct index_of<Search, list<>> { constexpr static int value = -1; };
59 template<typename Search, typename T, typename... Ts>
60 struct index_of<Search, list<T, Ts...>> {
61  constexpr static int deeper = index_of<Search, list<Ts...>>::value;
62  constexpr static int value = std::is_same<Search, T>::value? 0 : (deeper == -1? -1 : deeper + 1);
63 };
64 
65 template<typename...> struct concat_unique;
66 template<typename... Uniques>
67 struct concat_unique<list<Uniques...>, list<>> {
68  using type = list<Uniques...>;
69 };
70 template<typename... Uniques, typename T>
71 struct concat_unique<list<Uniques...>, list<T>> {
72  using type = std::conditional_t<index_of<T, list<Uniques...>>::value >= 0,
73  list<Uniques...>, list<Uniques..., T>>;
74 };
75 template<typename... Uniques, typename T1, typename T2, typename... Types>
76 struct concat_unique<list<Uniques...>, list<T1, T2, Types...>> {
77  using type = typename concat_unique<
78  typename concat_unique<list<Uniques...>, list<T1>>::type, list<T2, Types...>>::type;
79 };
80 template<typename... Uniques, typename... Lists>
81 struct concat_unique<list<Uniques...>, list<>, Lists...> {
82  using type = typename concat_unique<list<Uniques...>, Lists...>::type;
83 };
84 template<typename Uniques, typename L1a, typename... L1s, typename L2, typename... Lists>
85 struct concat_unique<Uniques, list<L1a, L1s...>, L2, Lists...> {
86  using type = typename concat_unique<typename concat_unique<Uniques, list<L1a, L1s...>>::type, L2, Lists...>::type;
87 };
88 
89 template<typename, std::size_t> struct at;
90 template<typename T, typename... Types>
91 struct at<list<T, Types...>, 0> { using type = T; };
92 template<typename T, typename... Types, std::size_t index>
93 struct at<list<T, Types...>, index> : at<list<Types...>, index-1> {};
94 
95 template<typename, typename, std::size_t> struct remove_at;
96 template<typename... Left, typename T, typename... Right>
97 struct remove_at<list<Left...>, list<T, Right...>, 0> { using type = list<Left..., Right...>; };
98 template<typename... Left, typename T, typename... Right, std::size_t index>
99 struct remove_at<list<Left...>, list<T, Right...>, index> {
100  using type = typename remove_at<list<Left..., T>, list<Right...>, index-1>::type;
101 };
102 
103 template<template<typename> class Filter, typename Filtered, typename List> struct filter;
104 template<template<typename> class Filter, typename... Filtered>
105 struct filter<Filter, list<Filtered...>, list<>> { using type = list<Filtered...>; };
106 template<template<typename> class Filter, typename... Filtered, typename T1, typename... Types>
107 struct filter<Filter, list<Filtered...>, list<T1, Types...>> {
108  using type = typename std::conditional_t<Filter<T1>::value,
109  filter<Filter, list<Filtered..., T1>, list<Types...>>,
110  filter<Filter, list<Filtered...>, list<Types...>>>::type;
111 };
112 
113 template<typename, typename, std::size_t, std::size_t, typename = void> struct slice;
114 template<typename... Results, typename... Types, std::size_t index>
115 struct slice<list<Results...>, list<Types...>, index, index, void> { using type = list<Results...>; };
116 template<typename... Results, typename T, typename... Types, std::size_t end>
117 struct slice<list<Results...>, list<T, Types...>, 0, end, std::enable_if_t<end != 0>>
118  : slice<list<Results..., T>, list<Types...>, 0, end-1> {};
119 template<typename T, typename... Types, std::size_t start, std::size_t end>
120 struct slice<list<>, list<T, Types...>, start, end, std::enable_if_t<start != 0>>
121  : slice<list<>, list<Types...>, start-1, end-1> {};
122 
123 template<typename, typename> struct zip;
124 template<>
125 struct zip<list<>, list<>> { using type = list<>; };
126 template<typename A, typename... As, typename B, typename... Bs>
127 struct zip<list<A, As...>, list<B, Bs...>> {
128  using type = typename concat<list<list<A, B>>, typename zip<list<As...>, list<Bs...>>::type>::type;
129 };
130 
131 template<typename Callable, typename Ret, typename T>
132 Ret dispatch_helper(Callable& c) { return c(T()); }
133 
134 } // namespace impl
135 
137 template<typename... Types>
138 struct list { using type = list; };
139 
141 template<typename List, template<typename...> class Delegate>
143 
145 template<typename List>
146 constexpr static std::size_t length() { return apply<List, impl::length>::value; }
147 
149 template<typename... Lists>
150 using concat = typename impl::concat<Lists...>::type;
151 
153 template<std::size_t count>
155 
160 template<typename List = list<>>
161 struct builder {
162  template<typename NewType> using add = typename builder<typename impl::concat<List, list<NewType>>::type>::type;
163  template<typename NewList> using add_list = typename builder<typename impl::concat<List, NewList>::type>::type;
164  using type = builder;
165  using finalize = List;
166 };
167 
169 template<typename List, typename Transformer>
171 
173 template<typename List, typename T>
174 constexpr static int index_of() { return impl::index_of<T, List>::value; }
175 
177 template<typename List, typename T>
178 constexpr static bool contains() { return impl::index_of<T, List>::value != -1; }
179 
181 template<typename... TypeLists>
182 using concat_unique = typename impl::concat_unique<list<>, TypeLists...>::type;
183 
185 template<typename List, std::size_t index>
187 
189 template<typename List>
192 template<typename List>
194 
196 template<typename List, std::size_t index>
197 using remove_at = typename impl::remove_at<list<>, List, index>::type;
198 
200 template<typename List, typename Remove>
202 
204 template<typename List, template<typename> class Filter>
205 using filter = typename impl::filter<Filter, list<>, List>::type;
206 
208 template<template<typename> class Filter>
210  template<typename T>
211  struct type { constexpr static bool value = !Filter<T>::value; };
212 };
213 
215 template<typename List, std::size_t start, std::size_t end = length<List>()>
216 using slice = typename impl::slice<list<>, List, start, end>::type;
217 
219 template<typename ListA, typename ListB>
221 
224 template<typename List>
225 using index = typename impl::zip<typename impl::make_sequence<length<List>()>::type, List>::type;
226 
228 namespace runtime {
230 template<typename T> struct wrapper { using type = T; };
231 
241 template<typename... Types, typename Callable, typename = std::enable_if_t<impl::length<Types...>::value != 0>,
242  typename Return = decltype(std::declval<Callable>()(wrapper<at<list<Types...>, 0>>()))>
243 Return dispatch(list<Types...>, std::size_t index, Callable c) {
244  static std::function<Return(Callable&)> call_table[] =
245  { impl::dispatch_helper<Callable, Return, wrapper<Types>>... };
246  if (index < impl::length<Types...>::value) return call_table[index](c);
247  throw std::out_of_range("Invalid index to fc::typelist::runtime::dispatch()");
248 }
249 template<typename List, typename Callable>
250 auto dispatch(List l, int64_t index, Callable c) {
251  if (index < 0) throw std::out_of_range("Negative index to fc::typelist::runtime::dispatch()");
252  return dispatch(l, std::size_t(index), std::move(c));
253 }
254 
256 template<typename... Types, typename Callable>
257 void for_each(list<Types...>, Callable c) {
258  bool trues[] = { [](Callable& c, auto t) { c(t); return true; }(c, wrapper<Types>())... };
259  (void)(trues);
260 }
261 
262 } } } // namespace fc::typelist::runtime
typename concat< list< list< A, B > >, typename zip< list< As... >, list< Bs... > >::type >::type type
Definition: typelist.hpp:128
Ret dispatch_helper(Callable &c)
Definition: typelist.hpp:132
void for_each(list< Types... >, Callable c)
Invoke the provided callable with an argument wrapper<Type>() for each type in the list...
Definition: typelist.hpp:257
Template to invert a filter, i.e. filter<mylist, filter_inverter<myfilter>::type> ...
Definition: typelist.hpp:209
typename concat_unique< typename concat_unique< list< Uniques... >, list< T1 > >::type, list< T2, Types... > >::type type
Definition: typelist.hpp:78
typename remove_at< list< Left..., T >, list< Right... >, index-1 >::type type
Definition: typelist.hpp:100
typename impl::concat_unique< list<>, TypeLists... >::type concat_unique
Remove duplicate items from one or more typelists and concatenate them all together.
Definition: typelist.hpp:182
auto dispatch(List l, int64_t index, Callable c)
Definition: typelist.hpp:250
typename impl::zip< typename impl::make_sequence< length< List >()>::type, List >::type index
Definition: typelist.hpp:225
typename impl::apply< List, Delegate >::type apply
Apply a list of types as arguments to another template.
Definition: typelist.hpp:142
typename concat< list< OldTypes..., NewTypes... >, NextList, Lists... >::type type
Definition: typelist.hpp:39
typename builder< typename impl::concat< List, NewList >::type >::type add_list
Definition: typelist.hpp:163
This namespace contains the list type, and all of the operations and queries which can be performed u...
Definition: typelist.hpp:14
typename impl::filter< Filter, list<>, List >::type filter
Get a list with all elements that do not pass a filter removed.
Definition: typelist.hpp:205
at< List, length< List >() -1 > last
Get the type at the end of the list.
Definition: typelist.hpp:193
remove_at< List, index_of< List, Remove >()> remove_element
Get the list with the given type removed.
Definition: typelist.hpp:201
typename impl::zip< ListA, ListB >::type zip
Zip two equal-length typelists together, i.e. zip<list<X, Y>, list<A, B>> == list<list<X, A>, list<Y, B>>
Definition: typelist.hpp:220
at< List, 0 > first
Get the type at the beginning of the list.
Definition: typelist.hpp:190
The actual list type.
Definition: typelist.hpp:17
typename std::conditional_t< Filter< T1 >::value, filter< Filter, list< Filtered..., T1 >, list< Types... > >, filter< Filter, list< Filtered... >, list< Types... > >>::type type
Definition: typelist.hpp:110
typename impl::remove_at< list<>, List, index >::type remove_at
Get the list with the element at the given index removed.
Definition: typelist.hpp:197
typename impl::transform< List, Transformer >::type transform
Transform elements of a typelist.
Definition: typelist.hpp:170
typename impl::at< List, index >::type at
Get the type at the specified list index.
Definition: typelist.hpp:186
typename concat_unique< list< Uniques... >, Lists... >::type type
Definition: typelist.hpp:82
Definition: api.hpp:15
typename builder< typename impl::concat< List, list< NewType > >::type >::type add
Definition: typelist.hpp:162
typename impl::slice< list<>, List, start, end >::type slice
Take the sublist at indexes [start, end)
Definition: typelist.hpp:216
typename impl::concat< Lists... >::type concat
Concatenate two or more typelists together.
Definition: typelist.hpp:150
std::conditional_t< index_of< T, list< Uniques... > >::value >=0, list< Uniques... >, list< Uniques..., T > > type
Definition: typelist.hpp:73
Type wrapper object allowing arbitrary types to be passed to functions as information rather than dat...
Definition: typelist.hpp:230
typename concat_unique< typename concat_unique< Uniques, list< L1a, L1s... > >::type, L2, Lists... >::type type
Definition: typelist.hpp:86
typename impl::make_sequence< count >::type make_sequence
Create a list of sequential integers ranging from [0, count)
Definition: typelist.hpp:154