blob: 8cd026985a26b9f3b94a473b4aeaa346d66ac1c9 [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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * 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>
21#include <fruit/impl/meta/logical_operations.h>
22#include <fruit/impl/meta/numeric_operations.h>
23#include <fruit/impl/meta/eval.h>
24#include <fruit/impl/meta/fold.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;
49
50 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;
59
60 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 {
69 using type = If(Bool<(N::value % 2) == 0>,
70 GenerateIntSequenceEvenHelper(GenerateIntSequence(Int<N::value/2>)),
71 GenerateIntSequenceOddHelper(GenerateIntSequence(Int<N::value/2>)));
72 };
73};
74
75template <>
76struct GenerateIntSequence::apply<Int<0>> {
77 using type = Vector<>;
78};
79
80template <>
81struct GenerateIntSequence::apply<Int<1>> {
82 using type = Vector<Int<0>>;
83};
Marco Poletti0c35fac2014-12-26 11:05:07 +010084
Marco Poletti0c35fac2014-12-26 11:05:07 +010085struct IsInVector {
Marco Poletti09547542015-07-25 12:13:24 +010086 template <typename T>
87 struct AlwaysFalseBool {
88 constexpr static bool value = false;
89 };
90
91 template <bool... bs>
92 struct BoolVector;
93
Marco Poletti0c35fac2014-12-26 11:05:07 +010094 template <typename T, typename V>
95 struct apply;
96
97 template <typename T, typename... Ts>
98 struct apply<T, Vector<Ts...>> {
Marco Poletti09547542015-07-25 12:13:24 +010099 using type = Bool<!std::is_same<BoolVector<AlwaysFalseBool<Ts>::value...>,
100 BoolVector<std::is_same<T, Ts>::value...>
101 >::value>;
Marco Poletti0c35fac2014-12-26 11:05:07 +0100102 };
103};
104
Marco Polettiec5c5202015-07-26 11:18:44 +0100105struct IsVectorContained {
106 template <typename V1, typename V2>
107 struct apply;
108
109 template <typename T>
110 struct AlwaysTrueBool {
111 constexpr static bool value = true;
112 };
113
114 template <bool... bs>
115 struct BoolVector;
116
117 template <typename... Ts, typename V2>
118 struct apply<Vector<Ts...>, V2> {
119 using type = Bool<std::is_same<BoolVector<AlwaysTrueBool<Ts>::value...>,
120 BoolVector<IsInVector::template apply<Ts, V2>::type::value...>
121 >::value>;
122 };
123};
124
Marco Poletti0c35fac2014-12-26 11:05:07 +0100125struct VectorSize {
126 template <typename V>
127 struct apply;
128
129 template <typename... Ts>
130 struct apply<Vector<Ts...>> {
Marco Polettia19fd1e2015-03-07 18:50:37 +0000131 using type = Int<sizeof...(Ts)>;
Marco Poletti0c35fac2014-12-26 11:05:07 +0100132 };
133};
134
Marco Polettif6335ae2015-01-01 15:13:04 +0100135struct PushFront {
136 template <typename V, typename T>
Marco Poletti0c35fac2014-12-26 11:05:07 +0100137 struct apply;
138
139 template <typename T, typename... Ts>
Marco Polettif6335ae2015-01-01 15:13:04 +0100140 struct apply<Vector<Ts...>, T> {
Marco Poletti0c35fac2014-12-26 11:05:07 +0100141 using type = Vector<T, Ts...>;
142 };
143};
144
Marco Polettid8943a82015-01-01 15:57:16 +0100145struct PushBack {
146 template <typename V, typename T>
147 struct apply;
148
149 template <typename T, typename... Ts>
150 struct apply<Vector<Ts...>, T> {
151 using type = Vector<Ts..., T>;
152 };
153};
154
Marco Poletti0c35fac2014-12-26 11:05:07 +0100155struct ConcatVectors {
156 template <typename V1, typename V2>
157 struct apply;
158
159 template <typename... Ts, typename... Us>
160 struct apply<Vector<Ts...>, Vector<Us...>> {
161 using type = Vector<Ts..., Us...>;
162 };
163};
164
Marco Polettiebc33122015-07-11 14:41:40 +0100165struct TransformVector {
166 template <typename V, typename F>
167 struct apply;
168
169 template <typename... Ts, typename F>
170 struct apply<Vector<Ts...>, F> {
Marco Poletti36253c92015-07-19 17:12:47 +0100171 using type = Vector<Eval<typename F::template apply<Ts>::type>...>;
Marco Polettiebc33122015-07-11 14:41:40 +0100172 };
173};
174
Marco Poletti36253c92015-07-19 17:12:47 +0100175struct ReplaceInVectorHelper {
176 template <typename ToReplace, typename NewElem, typename T>
Marco Polettiebc33122015-07-11 14:41:40 +0100177 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100178 using type = T;
Marco Polettidaf62222015-07-11 14:57:41 +0100179 };
180
Marco Poletti36253c92015-07-19 17:12:47 +0100181 template <typename ToReplace, typename NewElem>
182 struct apply<ToReplace, NewElem, ToReplace> {
183 using type = NewElem;
Marco Polettiebc33122015-07-11 14:41:40 +0100184 };
185};
186
Marco Poletti36253c92015-07-19 17:12:47 +0100187struct ReplaceInVector {
188 template <typename V, typename ToReplace, typename NewElem>
Marco Polettiebc33122015-07-11 14:41:40 +0100189 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100190 using type = TransformVector(V, PartialCall(ReplaceInVectorHelper, ToReplace, NewElem));
191 };
192};
193
194// If V is Vector<T1, ..., Tn> this calculates F(InitialValue, F(T1, F(..., F(Tn) ...))).
195// If V is Vector<> this returns InitialValue.
196struct FoldVector {
197 template <typename V, typename F, typename InitialValue>
198 struct apply;
199
200 template <typename... Ts, typename F, typename InitialValue>
201 struct apply<Vector<Ts...>, F, InitialValue> {
202 using type = Fold(F, InitialValue, Ts...);
203 };
204};
205
206template <typename Unused>
207using AlwaysVoidPtr = void*;
208
209// Returns a copy of V but without the first N elements.
210// N must be at least 0 and at most VectorSize(V).
211struct VectorRemoveFirstN {
212 template <typename V, typename N, typename Indexes = Eval<GenerateIntSequence(N)>>
213 struct apply;
214
215 template <typename... Types, typename N, int... indexes>
216 struct apply<Vector<Types...>, N, Vector<Int<indexes>...>> {
217 template <typename... RemainingTypes>
218 static Vector<RemainingTypes...> f(AlwaysVoidPtr<Int<indexes>>..., RemainingTypes*...);
219
220 using type = decltype(f((Types*)nullptr...));
221 };
222};
223
224struct VectorEndsWith {
225 template <typename V, typename T>
226 struct apply {
227 using type = IsSame(VectorRemoveFirstN(V, Int<Eval<VectorSize(V)>::value - 1>),
228 Vector<T>);
229 };
230
231 template <typename T>
232 struct apply<Vector<>, T> {
233 using type = Bool<false>;
Marco Poletti0c35fac2014-12-26 11:05:07 +0100234 };
235};
236
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000237struct ConstructErrorWithArgVector {
238 template <typename ErrorTag, typename ArgsVector, typename... OtherArgs>
239 struct apply;
240
241 template <typename ErrorTag, typename... Args, typename... OtherArgs>
242 struct apply<ErrorTag, Vector<Args...>, OtherArgs...> {
243 using type = ConstructError(ErrorTag, OtherArgs..., Args...);
244 };
245};
246
Marco Poletti0c35fac2014-12-26 11:05:07 +0100247} // namespace meta
248} // namespace impl
249} // namespace fruit
250
251
252#endif // FRUIT_META_VECTOR_H