1*a65addddSAndroid Build Coastguard Worker /*
2*a65addddSAndroid Build Coastguard Worker * Copyright 2014 Google Inc. All rights reserved.
3*a65addddSAndroid Build Coastguard Worker *
4*a65addddSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker *
8*a65addddSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker *
10*a65addddSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker * limitations under the License.
15*a65addddSAndroid Build Coastguard Worker */
16*a65addddSAndroid Build Coastguard Worker
17*a65addddSAndroid Build Coastguard Worker #ifndef FRUIT_META_BASICS_H
18*a65addddSAndroid Build Coastguard Worker #define FRUIT_META_BASICS_H
19*a65addddSAndroid Build Coastguard Worker
20*a65addddSAndroid Build Coastguard Worker #include <functional>
21*a65addddSAndroid Build Coastguard Worker
22*a65addddSAndroid Build Coastguard Worker namespace fruit {
23*a65addddSAndroid Build Coastguard Worker namespace impl {
24*a65addddSAndroid Build Coastguard Worker namespace meta {
25*a65addddSAndroid Build Coastguard Worker
26*a65addddSAndroid Build Coastguard Worker template <typename T>
27*a65addddSAndroid Build Coastguard Worker struct Type {
28*a65addddSAndroid Build Coastguard Worker using type = T;
29*a65addddSAndroid Build Coastguard Worker };
30*a65addddSAndroid Build Coastguard Worker
31*a65addddSAndroid Build Coastguard Worker template <bool b>
32*a65addddSAndroid Build Coastguard Worker struct Bool {
33*a65addddSAndroid Build Coastguard Worker static constexpr bool value = b;
34*a65addddSAndroid Build Coastguard Worker };
35*a65addddSAndroid Build Coastguard Worker
36*a65addddSAndroid Build Coastguard Worker template <int n>
37*a65addddSAndroid Build Coastguard Worker struct Int {
38*a65addddSAndroid Build Coastguard Worker static constexpr int value = n;
39*a65addddSAndroid Build Coastguard Worker };
40*a65addddSAndroid Build Coastguard Worker
41*a65addddSAndroid Build Coastguard Worker // This was added to workaround a bug in MSVC 2017 15.5, that crashes when expanding Indexes::value... in some cases
42*a65addddSAndroid Build Coastguard Worker // (where Indexes is a template parameter pack of Int<...> types).
43*a65addddSAndroid Build Coastguard Worker // TODO: Remove this once MSVC 2017 is fixed and the fix has been out for some time.
44*a65addddSAndroid Build Coastguard Worker template <typename N>
getIntValue()45*a65addddSAndroid Build Coastguard Worker constexpr int getIntValue() {
46*a65addddSAndroid Build Coastguard Worker return N::value;
47*a65addddSAndroid Build Coastguard Worker }
48*a65addddSAndroid Build Coastguard Worker
49*a65addddSAndroid Build Coastguard Worker // None is used as "the nullptr of metaprogramming". E.g. when a function has no meaningful value to
50*a65addddSAndroid Build Coastguard Worker // return, it can return None instead.
51*a65addddSAndroid Build Coastguard Worker struct None {};
52*a65addddSAndroid Build Coastguard Worker
53*a65addddSAndroid Build Coastguard Worker struct If {};
54*a65addddSAndroid Build Coastguard Worker
55*a65addddSAndroid Build Coastguard Worker // PropagateError(E, X) evaluates E then X. The result is X's result, but if E returns an error,
56*a65addddSAndroid Build Coastguard Worker // that's the result instead.
57*a65addddSAndroid Build Coastguard Worker struct PropagateError {};
58*a65addddSAndroid Build Coastguard Worker
59*a65addddSAndroid Build Coastguard Worker // Used to propagate an ErrorTag::apply<ErrorArgs...> up the instantiation chain, but without instantiating it right
60*a65addddSAndroid Build Coastguard Worker // away, to allow shorter error stacktraces.
61*a65addddSAndroid Build Coastguard Worker // Instantiating ErrorTag::apply<ErrorArgs...> must result in a static_assert error.
62*a65addddSAndroid Build Coastguard Worker template <typename ErrorTag, typename... ErrorArgs>
63*a65addddSAndroid Build Coastguard Worker struct Error {};
64*a65addddSAndroid Build Coastguard Worker
65*a65addddSAndroid Build Coastguard Worker // Use as Catch(ExpressionThatMightThrow, ErrorTag, Handler)
66*a65addddSAndroid Build Coastguard Worker // Handler(Error<ErrorTag, ErrorArgs...>) is called if ExpressionThatMightThrow throws ErrorTag.
67*a65addddSAndroid Build Coastguard Worker struct Catch {};
68*a65addddSAndroid Build Coastguard Worker
69*a65addddSAndroid Build Coastguard Worker // Use as CatchAll(ExpressionThatMightThrow, Handler)
70*a65addddSAndroid Build Coastguard Worker // Handler(Error<ErrorTag, ErrorArgs...>) is called if ExpressionThatMightThrow throws any error.
71*a65addddSAndroid Build Coastguard Worker struct CatchAll {};
72*a65addddSAndroid Build Coastguard Worker
73*a65addddSAndroid Build Coastguard Worker // Call(F, Args...) is equivalent to F(Args...) in a metaexpression, except that Call(F, Args...)
74*a65addddSAndroid Build Coastguard Worker // also works when F is a metaexpression.
75*a65addddSAndroid Build Coastguard Worker struct Call {
76*a65addddSAndroid Build Coastguard Worker template <typename F, typename... Args>
77*a65addddSAndroid Build Coastguard Worker struct apply : public F::template apply<Args...> {};
78*a65addddSAndroid Build Coastguard Worker };
79*a65addddSAndroid Build Coastguard Worker
80*a65addddSAndroid Build Coastguard Worker // UnwrapType<Type<T>> is T.
81*a65addddSAndroid Build Coastguard Worker template <typename WrappedType>
82*a65addddSAndroid Build Coastguard Worker using UnwrapType = typename WrappedType::type;
83*a65addddSAndroid Build Coastguard Worker
84*a65addddSAndroid Build Coastguard Worker // MSVC 14 has trouble specializing alias templates using expanded pack elements.
85*a65addddSAndroid Build Coastguard Worker // This is a known issue:
86*a65addddSAndroid Build Coastguard Worker // https://stackoverflow.com/questions/43411542/metaprogramming-failed-to-specialize-alias-template
87*a65addddSAndroid Build Coastguard Worker // The workaround is just to use a struct directly.
88*a65addddSAndroid Build Coastguard Worker // typename TypeUnwrapper<Type<T>>::type is T.
89*a65addddSAndroid Build Coastguard Worker template <typename WrappedType>
90*a65addddSAndroid Build Coastguard Worker struct TypeUnwrapper {
91*a65addddSAndroid Build Coastguard Worker using type = UnwrapType<WrappedType>;
92*a65addddSAndroid Build Coastguard Worker };
93*a65addddSAndroid Build Coastguard Worker
94*a65addddSAndroid Build Coastguard Worker // Logical And with short-circuit evaluation.
95*a65addddSAndroid Build Coastguard Worker struct And {
96*a65addddSAndroid Build Coastguard Worker template <typename... MetaExprs>
97*a65addddSAndroid Build Coastguard Worker struct apply {
98*a65addddSAndroid Build Coastguard Worker using type = Bool<true>;
99*a65addddSAndroid Build Coastguard Worker };
100*a65addddSAndroid Build Coastguard Worker
101*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr>
102*a65addddSAndroid Build Coastguard Worker struct apply<MetaExpr> {
103*a65addddSAndroid Build Coastguard Worker using type = MetaExpr;
104*a65addddSAndroid Build Coastguard Worker };
105*a65addddSAndroid Build Coastguard Worker
106*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr, typename MetaExpr2>
107*a65addddSAndroid Build Coastguard Worker struct apply<MetaExpr, MetaExpr2> {
108*a65addddSAndroid Build Coastguard Worker using type = If(MetaExpr, MetaExpr2, Bool<false>);
109*a65addddSAndroid Build Coastguard Worker };
110*a65addddSAndroid Build Coastguard Worker
111*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr, typename MetaExpr2, typename... MetaExprs>
112*a65addddSAndroid Build Coastguard Worker struct apply<MetaExpr, MetaExpr2, MetaExprs...> {
113*a65addddSAndroid Build Coastguard Worker using type = If(MetaExpr, If(MetaExpr2, And(MetaExprs...), Bool<false>), Bool<false>);
114*a65addddSAndroid Build Coastguard Worker };
115*a65addddSAndroid Build Coastguard Worker };
116*a65addddSAndroid Build Coastguard Worker
117*a65addddSAndroid Build Coastguard Worker // Logical Or with short-circuit evaluation.
118*a65addddSAndroid Build Coastguard Worker struct Or {
119*a65addddSAndroid Build Coastguard Worker template <typename... MetaExprs>
120*a65addddSAndroid Build Coastguard Worker struct apply {
121*a65addddSAndroid Build Coastguard Worker using type = Bool<false>;
122*a65addddSAndroid Build Coastguard Worker };
123*a65addddSAndroid Build Coastguard Worker
124*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr>
125*a65addddSAndroid Build Coastguard Worker struct apply<MetaExpr> {
126*a65addddSAndroid Build Coastguard Worker using type = MetaExpr;
127*a65addddSAndroid Build Coastguard Worker };
128*a65addddSAndroid Build Coastguard Worker
129*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr, typename MetaExpr2>
130*a65addddSAndroid Build Coastguard Worker struct apply<MetaExpr, MetaExpr2> {
131*a65addddSAndroid Build Coastguard Worker using type = If(MetaExpr, Bool<true>, MetaExpr2);
132*a65addddSAndroid Build Coastguard Worker };
133*a65addddSAndroid Build Coastguard Worker
134*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr, typename MetaExpr2, typename... MetaExprs>
135*a65addddSAndroid Build Coastguard Worker struct apply<MetaExpr, MetaExpr2, MetaExprs...> {
136*a65addddSAndroid Build Coastguard Worker using type = If(MetaExpr, Bool<true>, If(MetaExpr2, Bool<true>, Or(MetaExprs...)));
137*a65addddSAndroid Build Coastguard Worker };
138*a65addddSAndroid Build Coastguard Worker };
139*a65addddSAndroid Build Coastguard Worker
140*a65addddSAndroid Build Coastguard Worker // Call(Call(DeferArgs(F), Args...), MoreArgs...)
141*a65addddSAndroid Build Coastguard Worker //
142*a65addddSAndroid Build Coastguard Worker // is equivalent to:
143*a65addddSAndroid Build Coastguard Worker // Result = F(Args..., MoreArgs...)
144*a65addddSAndroid Build Coastguard Worker //
145*a65addddSAndroid Build Coastguard Worker // Note that you can't write:
146*a65addddSAndroid Build Coastguard Worker // DeferArgs(F)(Args...)(MoreArgs...)
147*a65addddSAndroid Build Coastguard Worker //
148*a65addddSAndroid Build Coastguard Worker // Because Call must be used to call metafunctions that are metaexpressions.
149*a65addddSAndroid Build Coastguard Worker struct DeferArgs {
150*a65addddSAndroid Build Coastguard Worker template <typename F>
151*a65addddSAndroid Build Coastguard Worker struct apply {
152*a65addddSAndroid Build Coastguard Worker struct type {
153*a65addddSAndroid Build Coastguard Worker template <typename... Args>
154*a65addddSAndroid Build Coastguard Worker struct apply {
155*a65addddSAndroid Build Coastguard Worker struct type {
156*a65addddSAndroid Build Coastguard Worker template <typename... MoreArgs>
157*a65addddSAndroid Build Coastguard Worker struct apply {
158*a65addddSAndroid Build Coastguard Worker using type = F(Args..., MoreArgs...);
159*a65addddSAndroid Build Coastguard Worker };
160*a65addddSAndroid Build Coastguard Worker };
161*a65addddSAndroid Build Coastguard Worker };
162*a65addddSAndroid Build Coastguard Worker };
163*a65addddSAndroid Build Coastguard Worker };
164*a65addddSAndroid Build Coastguard Worker };
165*a65addddSAndroid Build Coastguard Worker
166*a65addddSAndroid Build Coastguard Worker // Call(PartialCall(F, Args...), MoreArgs...)
167*a65addddSAndroid Build Coastguard Worker //
168*a65addddSAndroid Build Coastguard Worker // is equivalent to:
169*a65addddSAndroid Build Coastguard Worker // Result = F(Args..., MoreArgs...)
170*a65addddSAndroid Build Coastguard Worker //
171*a65addddSAndroid Build Coastguard Worker // Note that you can't write:
172*a65addddSAndroid Build Coastguard Worker // PartialCall(F, Args...)(MoreArgs...)
173*a65addddSAndroid Build Coastguard Worker //
174*a65addddSAndroid Build Coastguard Worker // Because Call must be used to call metafunctions that are metaexpressions.
175*a65addddSAndroid Build Coastguard Worker struct PartialCall {
176*a65addddSAndroid Build Coastguard Worker template <typename F, typename... Args>
177*a65addddSAndroid Build Coastguard Worker struct apply {
178*a65addddSAndroid Build Coastguard Worker struct type {
179*a65addddSAndroid Build Coastguard Worker template <typename... MoreArgs>
180*a65addddSAndroid Build Coastguard Worker struct apply {
181*a65addddSAndroid Build Coastguard Worker using type = F(Args..., MoreArgs...);
182*a65addddSAndroid Build Coastguard Worker };
183*a65addddSAndroid Build Coastguard Worker };
184*a65addddSAndroid Build Coastguard Worker };
185*a65addddSAndroid Build Coastguard Worker };
186*a65addddSAndroid Build Coastguard Worker
187*a65addddSAndroid Build Coastguard Worker struct IsSame {
188*a65addddSAndroid Build Coastguard Worker template <typename T, typename U>
189*a65addddSAndroid Build Coastguard Worker struct apply {
190*a65addddSAndroid Build Coastguard Worker using type = Bool<false>;
191*a65addddSAndroid Build Coastguard Worker };
192*a65addddSAndroid Build Coastguard Worker
193*a65addddSAndroid Build Coastguard Worker template <typename T>
194*a65addddSAndroid Build Coastguard Worker struct apply<T, T> {
195*a65addddSAndroid Build Coastguard Worker using type = Bool<true>;
196*a65addddSAndroid Build Coastguard Worker };
197*a65addddSAndroid Build Coastguard Worker };
198*a65addddSAndroid Build Coastguard Worker
199*a65addddSAndroid Build Coastguard Worker struct Not {
200*a65addddSAndroid Build Coastguard Worker template <typename B>
201*a65addddSAndroid Build Coastguard Worker struct apply {
202*a65addddSAndroid Build Coastguard Worker using type = Bool<!B::value>;
203*a65addddSAndroid Build Coastguard Worker };
204*a65addddSAndroid Build Coastguard Worker };
205*a65addddSAndroid Build Coastguard Worker
206*a65addddSAndroid Build Coastguard Worker struct IsNone {
207*a65addddSAndroid Build Coastguard Worker template <typename T>
208*a65addddSAndroid Build Coastguard Worker struct apply {
209*a65addddSAndroid Build Coastguard Worker using type = Bool<false>;
210*a65addddSAndroid Build Coastguard Worker };
211*a65addddSAndroid Build Coastguard Worker };
212*a65addddSAndroid Build Coastguard Worker
213*a65addddSAndroid Build Coastguard Worker template <>
214*a65addddSAndroid Build Coastguard Worker struct IsNone::apply<None> {
215*a65addddSAndroid Build Coastguard Worker using type = Bool<true>;
216*a65addddSAndroid Build Coastguard Worker };
217*a65addddSAndroid Build Coastguard Worker
218*a65addddSAndroid Build Coastguard Worker template <typename T>
219*a65addddSAndroid Build Coastguard Worker using Id = T;
220*a65addddSAndroid Build Coastguard Worker
221*a65addddSAndroid Build Coastguard Worker struct Identity {
222*a65addddSAndroid Build Coastguard Worker template <typename T>
223*a65addddSAndroid Build Coastguard Worker struct apply {
224*a65addddSAndroid Build Coastguard Worker using type = T;
225*a65addddSAndroid Build Coastguard Worker };
226*a65addddSAndroid Build Coastguard Worker };
227*a65addddSAndroid Build Coastguard Worker
228*a65addddSAndroid Build Coastguard Worker template <typename T>
229*a65addddSAndroid Build Coastguard Worker struct DebugTypeHelper {
230*a65addddSAndroid Build Coastguard Worker static_assert(sizeof(T*) * 0 != 0, "");
231*a65addddSAndroid Build Coastguard Worker using type = T;
232*a65addddSAndroid Build Coastguard Worker };
233*a65addddSAndroid Build Coastguard Worker
234*a65addddSAndroid Build Coastguard Worker template <typename T>
235*a65addddSAndroid Build Coastguard Worker using DebugType = typename DebugTypeHelper<T>::type;
236*a65addddSAndroid Build Coastguard Worker
237*a65addddSAndroid Build Coastguard Worker } // namespace meta
238*a65addddSAndroid Build Coastguard Worker } // namespace impl
239*a65addddSAndroid Build Coastguard Worker } // namespace fruit
240*a65addddSAndroid Build Coastguard Worker
241*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_META_BASICS_H
242