blob: a94a21d9184e2bfae4a9741042eecf851d554abc [file] [log] [blame]
Marco Poletti0c35fac2014-12-26 11:05:07 +01001/*
2 * Copyright 2014 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Marco Poletti1b959ab2017-12-27 09:23:44 +00007 *
Marco Poletti0c35fac2014-12-26 11:05:07 +01008 * http://www.apache.org/licenses/LICENSE-2.0
Marco Poletti1b959ab2017-12-27 09:23:44 +00009 *
Marco Poletti0c35fac2014-12-26 11:05:07 +010010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef FRUIT_META_VECTOR_H
18#define FRUIT_META_VECTOR_H
19
Marco Polettif2895102016-01-30 13:38:37 +000020#include <fruit/impl/meta/basics.h>
Marco Polettif2895102016-01-30 13:38:37 +000021#include <fruit/impl/meta/eval.h>
22#include <fruit/impl/meta/fold.h>
Marco Poletti1b959ab2017-12-27 09:23:44 +000023#include <fruit/impl/meta/logical_operations.h>
24#include <fruit/impl/meta/numeric_operations.h>
Marco Poletti0c35fac2014-12-26 11:05:07 +010025#include <functional>
26
Marco Poletti0c35fac2014-12-26 11:05:07 +010027namespace fruit {
28namespace impl {
29namespace meta {
30
31// Used to pass around a Vector<Types...>, no meaning per se.
32template <typename... Types>
Marco Poletti010daa62015-07-06 01:15:12 +010033struct Vector {};
34
35// Using ConsVector(MetaExpr...) instead of Vector<MetaExpr...> in a meta-expression allows the
36// types to be evaluated. Avoid using Vector<...> directly in a meta-expression, unless you're sure
37// that the arguments have already been evaluated (e.g. if Args... are arguments of a metafunction,
38// Vector<Args...> is ok but Vector<MyFunction(Args)...> is wrong.
39struct ConsVector {
40 template <typename... Types>
41 struct apply {
42 using type = Vector<Types...>;
43 };
44};
Marco Poletti0c35fac2014-12-26 11:05:07 +010045
Marco Poletti36253c92015-07-19 17:12:47 +010046struct GenerateIntSequenceEvenHelper {
47 template <typename Half>
48 struct apply;
Marco Poletti1b959ab2017-12-27 09:23:44 +000049
Marco Poletti36253c92015-07-19 17:12:47 +010050 template <int... ns>
51 struct apply<Vector<Int<ns>...>> {
52 using type = Vector<Int<ns>..., Int<sizeof...(ns) + ns>...>;
53 };
54};
55
56struct GenerateIntSequenceOddHelper {
57 template <typename Half>
58 struct apply;
Marco Poletti1b959ab2017-12-27 09:23:44 +000059
Marco Poletti36253c92015-07-19 17:12:47 +010060 template <int... ns>
61 struct apply<Vector<Int<ns>...>> {
62 using type = Vector<Int<ns>..., Int<sizeof...(ns)>, Int<sizeof...(ns) + 1 + ns>...>;
63 };
64};
65
66struct GenerateIntSequence {
67 template <typename N>
68 struct apply {
Marco Poletti1b959ab2017-12-27 09:23:44 +000069 using type = If(Bool<(N::value % 2) == 0>, GenerateIntSequenceEvenHelper(GenerateIntSequence(Int<N::value / 2>)),
70 GenerateIntSequenceOddHelper(GenerateIntSequence(Int<N::value / 2>)));
Marco Poletti36253c92015-07-19 17:12:47 +010071 };
72};
73
74template <>
75struct GenerateIntSequence::apply<Int<0>> {
76 using type = Vector<>;
77};
78
79template <>
80struct GenerateIntSequence::apply<Int<1>> {
81 using type = Vector<Int<0>>;
82};
Marco Poletti0c35fac2014-12-26 11:05:07 +010083
Marco Poletti0c35fac2014-12-26 11:05:07 +010084struct IsInVector {
Marco Poletti09547542015-07-25 12:13:24 +010085 template <typename T>
86 struct AlwaysFalseBool {
87 constexpr static bool value = false;
88 };
Marco Poletti1b959ab2017-12-27 09:23:44 +000089
Marco Poletti09547542015-07-25 12:13:24 +010090 template <bool... bs>
91 struct BoolVector;
Marco Poletti1b959ab2017-12-27 09:23:44 +000092
Marco Poletti0c35fac2014-12-26 11:05:07 +010093 template <typename T, typename V>
94 struct apply;
95
96 template <typename T, typename... Ts>
97 struct apply<T, Vector<Ts...>> {
Marco Poletti1b959ab2017-12-27 09:23:44 +000098 using type = Bool<
99 !std::is_same<BoolVector<AlwaysFalseBool<Ts>::value...>, BoolVector<std::is_same<T, Ts>::value...>>::value>;
Marco Poletti0c35fac2014-12-26 11:05:07 +0100100 };
101};
102
Marco Polettiec5c5202015-07-26 11:18:44 +0100103struct IsVectorContained {
104 template <typename V1, typename V2>
105 struct apply;
106
107 template <typename T>
108 struct AlwaysTrueBool {
109 constexpr static bool value = true;
110 };
Marco Poletti1b959ab2017-12-27 09:23:44 +0000111
Marco Polettiec5c5202015-07-26 11:18:44 +0100112 template <bool... bs>
113 struct BoolVector;
Marco Poletti1b959ab2017-12-27 09:23:44 +0000114
Marco Polettiec5c5202015-07-26 11:18:44 +0100115 template <typename... Ts, typename V2>
116 struct apply<Vector<Ts...>, V2> {
Marco Poletti1b959ab2017-12-27 09:23:44 +0000117 using type = Bool<std::is_same<BoolVector<AlwaysTrueBool<Ts>::value...>,
118 BoolVector<Id<typename IsInVector::template apply<Ts, V2>::type>::value...>>::value>;
Marco Polettiec5c5202015-07-26 11:18:44 +0100119 };
120};
121
Marco Poletti0c35fac2014-12-26 11:05:07 +0100122struct VectorSize {
123 template <typename V>
124 struct apply;
125
126 template <typename... Ts>
127 struct apply<Vector<Ts...>> {
Marco Polettia19fd1e2015-03-07 18:50:37 +0000128 using type = Int<sizeof...(Ts)>;
Marco Poletti0c35fac2014-12-26 11:05:07 +0100129 };
130};
131
Marco Polettif6335ae2015-01-01 15:13:04 +0100132struct PushFront {
133 template <typename V, typename T>
Marco Poletti0c35fac2014-12-26 11:05:07 +0100134 struct apply;
135
136 template <typename T, typename... Ts>
Marco Polettif6335ae2015-01-01 15:13:04 +0100137 struct apply<Vector<Ts...>, T> {
Marco Poletti0c35fac2014-12-26 11:05:07 +0100138 using type = Vector<T, Ts...>;
139 };
140};
141
Marco Polettid8943a82015-01-01 15:57:16 +0100142struct PushBack {
143 template <typename V, typename T>
144 struct apply;
145
146 template <typename T, typename... Ts>
147 struct apply<Vector<Ts...>, T> {
148 using type = Vector<Ts..., T>;
149 };
150};
151
Marco Poletti0c35fac2014-12-26 11:05:07 +0100152struct ConcatVectors {
153 template <typename V1, typename V2>
154 struct apply;
155
156 template <typename... Ts, typename... Us>
157 struct apply<Vector<Ts...>, Vector<Us...>> {
158 using type = Vector<Ts..., Us...>;
159 };
160};
161
Marco Polettiebc33122015-07-11 14:41:40 +0100162struct TransformVector {
163 template <typename V, typename F>
164 struct apply;
Marco Poletti1b959ab2017-12-27 09:23:44 +0000165
Marco Polettiebc33122015-07-11 14:41:40 +0100166 template <typename... Ts, typename F>
167 struct apply<Vector<Ts...>, F> {
Marco Poletti36253c92015-07-19 17:12:47 +0100168 using type = Vector<Eval<typename F::template apply<Ts>::type>...>;
Marco Polettiebc33122015-07-11 14:41:40 +0100169 };
170};
171
Marco Poletti36253c92015-07-19 17:12:47 +0100172struct ReplaceInVectorHelper {
173 template <typename ToReplace, typename NewElem, typename T>
Marco Polettiebc33122015-07-11 14:41:40 +0100174 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100175 using type = T;
Marco Polettidaf62222015-07-11 14:57:41 +0100176 };
Marco Poletti1b959ab2017-12-27 09:23:44 +0000177
Marco Poletti36253c92015-07-19 17:12:47 +0100178 template <typename ToReplace, typename NewElem>
179 struct apply<ToReplace, NewElem, ToReplace> {
180 using type = NewElem;
Marco Polettiebc33122015-07-11 14:41:40 +0100181 };
182};
183
Marco Poletti36253c92015-07-19 17:12:47 +0100184struct ReplaceInVector {
185 template <typename V, typename ToReplace, typename NewElem>
Marco Polettiebc33122015-07-11 14:41:40 +0100186 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100187 using type = TransformVector(V, PartialCall(ReplaceInVectorHelper, ToReplace, NewElem));
188 };
189};
190
191// If V is Vector<T1, ..., Tn> this calculates F(InitialValue, F(T1, F(..., F(Tn) ...))).
192// If V is Vector<> this returns InitialValue.
193struct FoldVector {
194 template <typename V, typename F, typename InitialValue>
195 struct apply;
Marco Poletti1b959ab2017-12-27 09:23:44 +0000196
Marco Poletti36253c92015-07-19 17:12:47 +0100197 template <typename... Ts, typename F, typename InitialValue>
198 struct apply<Vector<Ts...>, F, InitialValue> {
199 using type = Fold(F, InitialValue, Ts...);
200 };
201};
202
203template <typename Unused>
204using AlwaysVoidPtr = void*;
205
206// Returns a copy of V but without the first N elements.
207// N must be at least 0 and at most VectorSize(V).
208struct VectorRemoveFirstN {
209 template <typename V, typename N, typename Indexes = Eval<GenerateIntSequence(N)>>
210 struct apply;
Marco Poletti905dc092017-03-12 15:54:31 +0000211
212 template <typename... Types, typename N, typename... Indexes>
213 struct apply<Vector<Types...>, N, Vector<Indexes...>> {
Marco Poletti36253c92015-07-19 17:12:47 +0100214 template <typename... RemainingTypes>
Marco Poletti905dc092017-03-12 15:54:31 +0000215 static Vector<RemainingTypes...> f(AlwaysVoidPtr<Indexes>..., RemainingTypes*...);
Marco Poletti1b959ab2017-12-27 09:23:44 +0000216
Marco Poletti36253c92015-07-19 17:12:47 +0100217 using type = decltype(f((Types*)nullptr...));
218 };
219};
220
221struct VectorEndsWith {
222 template <typename V, typename T>
223 struct apply {
Marco Poletti905dc092017-03-12 15:54:31 +0000224 using N = Int<Eval<VectorSize(V)>::value - 1>;
Marco Poletti1b959ab2017-12-27 09:23:44 +0000225 using type = IsSame(VectorRemoveFirstN(V, N), Vector<T>);
Marco Poletti36253c92015-07-19 17:12:47 +0100226 };
Marco Poletti1b959ab2017-12-27 09:23:44 +0000227
Marco Poletti36253c92015-07-19 17:12:47 +0100228 template <typename T>
229 struct apply<Vector<>, T> {
230 using type = Bool<false>;
Marco Poletti0c35fac2014-12-26 11:05:07 +0100231 };
232};
233
Marco Poletti58525082016-02-21 14:11:59 +0000234// Removes all None elements from the vector.
235// O(n) instantiations.
236struct VectorRemoveNone {
237 template <typename V>
238 struct apply {
239 using type = Vector<>;
240 };
Marco Poletti1b959ab2017-12-27 09:23:44 +0000241
Marco Poletti58525082016-02-21 14:11:59 +0000242 template <typename T, typename... Ts>
243 struct apply<Vector<T, Ts...>> {
244 using type = PushFront(VectorRemoveNone(Vector<Ts...>), T);
245 };
Marco Poletti1b959ab2017-12-27 09:23:44 +0000246
Marco Poletti58525082016-02-21 14:11:59 +0000247 template <typename... Ts>
248 struct apply<Vector<None, Ts...>> {
249 using type = VectorRemoveNone(Vector<Ts...>);
250 };
251};
252
253struct ConstructErrorWithArgVectorHelper {
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000254 template <typename ErrorTag, typename ArgsVector, typename... OtherArgs>
255 struct apply;
Marco Poletti1b959ab2017-12-27 09:23:44 +0000256
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000257 template <typename ErrorTag, typename... Args, typename... OtherArgs>
258 struct apply<ErrorTag, Vector<Args...>, OtherArgs...> {
259 using type = ConstructError(ErrorTag, OtherArgs..., Args...);
260 };
261};
262
Marco Poletti58525082016-02-21 14:11:59 +0000263struct ConstructErrorWithArgVector {
264 template <typename ErrorTag, typename ArgsVector, typename... OtherArgs>
265 struct apply {
266 using type = ConstructErrorWithArgVectorHelper(ErrorTag, VectorRemoveNone(ArgsVector), OtherArgs...);
267 };
268};
269
Marco Poletti0c35fac2014-12-26 11:05:07 +0100270} // namespace meta
271} // namespace impl
272} // namespace fruit
273
Marco Poletti0c35fac2014-12-26 11:05:07 +0100274#endif // FRUIT_META_VECTOR_H