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_EVAL_H 18*a65addddSAndroid Build Coastguard Worker #define FRUIT_META_EVAL_H 19*a65addddSAndroid Build Coastguard Worker 20*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/basics.h> 21*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/errors.h> 22*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/logical_operations.h> 23*a65addddSAndroid Build Coastguard Worker 24*a65addddSAndroid Build Coastguard Worker #include <functional> 25*a65addddSAndroid Build Coastguard Worker 26*a65addddSAndroid Build Coastguard Worker namespace fruit { 27*a65addddSAndroid Build Coastguard Worker namespace impl { 28*a65addddSAndroid Build Coastguard Worker namespace meta { 29*a65addddSAndroid Build Coastguard Worker 30*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr> 31*a65addddSAndroid Build Coastguard Worker struct DoEval; 32*a65addddSAndroid Build Coastguard Worker 33*a65addddSAndroid Build Coastguard Worker // General case, meta-constant. 34*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr> 35*a65addddSAndroid Build Coastguard Worker struct DoEval { 36*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS static_warningDoEval37*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 38*a65addddSAndroid Build Coastguard Worker return true; 39*a65addddSAndroid Build Coastguard Worker } 40*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 41*a65addddSAndroid Build Coastguard Worker #endif 42*a65addddSAndroid Build Coastguard Worker using type = MetaExpr; 43*a65addddSAndroid Build Coastguard Worker }; 44*a65addddSAndroid Build Coastguard Worker 45*a65addddSAndroid Build Coastguard Worker template <typename Type> 46*a65addddSAndroid Build Coastguard Worker struct SimpleIsError { 47*a65addddSAndroid Build Coastguard Worker static constexpr bool value = false; 48*a65addddSAndroid Build Coastguard Worker }; 49*a65addddSAndroid Build Coastguard Worker template <typename ErrorTag, typename... ErrorArgs> 50*a65addddSAndroid Build Coastguard Worker struct SimpleIsError<Error<ErrorTag, ErrorArgs...>> { 51*a65addddSAndroid Build Coastguard Worker static constexpr bool value = true; 52*a65addddSAndroid Build Coastguard Worker }; 53*a65addddSAndroid Build Coastguard Worker 54*a65addddSAndroid Build Coastguard Worker #if FRUIT_EXTRA_DEBUG 55*a65addddSAndroid Build Coastguard Worker 56*a65addddSAndroid Build Coastguard Worker // For debugging, we use a separate DoEvalFun so that we get longer (and more informative) 57*a65addddSAndroid Build Coastguard Worker // instantiation traces. 58*a65addddSAndroid Build Coastguard Worker 59*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... Params> 60*a65addddSAndroid Build Coastguard Worker struct DoEvalFun { 61*a65addddSAndroid Build Coastguard Worker using type = 62*a65addddSAndroid Build Coastguard Worker typename DoEval<typename std::conditional<StaticOr<SimpleIsError<Params>::value...>::value, ExtractFirstError, 63*a65addddSAndroid Build Coastguard Worker MetaFun>::type::template apply<Params...>::type>::type; 64*a65addddSAndroid Build Coastguard Worker }; 65*a65addddSAndroid Build Coastguard Worker 66*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... MetaExprs> 67*a65addddSAndroid Build Coastguard Worker struct DoEval<MetaFun(MetaExprs...)> { 68*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 69*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 70*a65addddSAndroid Build Coastguard Worker return true; 71*a65addddSAndroid Build Coastguard Worker } 72*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 73*a65addddSAndroid Build Coastguard Worker #endif 74*a65addddSAndroid Build Coastguard Worker using type = typename DoEvalFun<MetaFun, typename DoEval<MetaExprs>::type...>::type; 75*a65addddSAndroid Build Coastguard Worker }; 76*a65addddSAndroid Build Coastguard Worker 77*a65addddSAndroid Build Coastguard Worker // Similar to the previous specialization, but this will be selected when the function signature 78*a65addddSAndroid Build Coastguard Worker // became a function pointer (this happens when a signature parameter is itself a signature). 79*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... MetaExprs> 80*a65addddSAndroid Build Coastguard Worker struct DoEval<MetaFun (*)(MetaExprs...)> { 81*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 82*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 83*a65addddSAndroid Build Coastguard Worker return true; 84*a65addddSAndroid Build Coastguard Worker } 85*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 86*a65addddSAndroid Build Coastguard Worker #endif 87*a65addddSAndroid Build Coastguard Worker using type = typename DoEvalFun<MetaFun, typename DoEval<MetaExprs>::type...>::type; 88*a65addddSAndroid Build Coastguard Worker }; 89*a65addddSAndroid Build Coastguard Worker 90*a65addddSAndroid Build Coastguard Worker #else // FRUIT_EXTRA_DEBUG 91*a65addddSAndroid Build Coastguard Worker 92*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... MetaExprs> 93*a65addddSAndroid Build Coastguard Worker struct DoEval<MetaFun(MetaExprs...)> { 94*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 95*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 96*a65addddSAndroid Build Coastguard Worker return true; 97*a65addddSAndroid Build Coastguard Worker } 98*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 99*a65addddSAndroid Build Coastguard Worker #endif 100*a65addddSAndroid Build Coastguard Worker using type = typename DoEval<typename std::conditional< 101*a65addddSAndroid Build Coastguard Worker StaticOr<SimpleIsError<typename DoEval<MetaExprs>::type>::value...>::value, ExtractFirstError, 102*a65addddSAndroid Build Coastguard Worker MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type; 103*a65addddSAndroid Build Coastguard Worker }; 104*a65addddSAndroid Build Coastguard Worker 105*a65addddSAndroid Build Coastguard Worker // Similar to the previous specialization, but this will be selected when the function signature 106*a65addddSAndroid Build Coastguard Worker // became a function pointer (this happens when a signature parameter is itself a signature). 107*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... MetaExprs> 108*a65addddSAndroid Build Coastguard Worker struct DoEval<MetaFun (*)(MetaExprs...)> { 109*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 110*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 111*a65addddSAndroid Build Coastguard Worker return true; 112*a65addddSAndroid Build Coastguard Worker } 113*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 114*a65addddSAndroid Build Coastguard Worker #endif 115*a65addddSAndroid Build Coastguard Worker using type = typename DoEval<typename std::conditional< 116*a65addddSAndroid Build Coastguard Worker StaticOr<SimpleIsError<typename DoEval<MetaExprs>::type>::value...>::value, ExtractFirstError, 117*a65addddSAndroid Build Coastguard Worker MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type; 118*a65addddSAndroid Build Coastguard Worker }; 119*a65addddSAndroid Build Coastguard Worker 120*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_EXTRA_DEBUG 121*a65addddSAndroid Build Coastguard Worker 122*a65addddSAndroid Build Coastguard Worker template <typename ExprResult, typename ErrorTag, typename Handler> 123*a65addddSAndroid Build Coastguard Worker struct EvalCatch { 124*a65addddSAndroid Build Coastguard Worker using type = ExprResult; 125*a65addddSAndroid Build Coastguard Worker }; 126*a65addddSAndroid Build Coastguard Worker 127*a65addddSAndroid Build Coastguard Worker template <typename CaughtErrorTag, typename... ErrorArgs, typename Handler> 128*a65addddSAndroid Build Coastguard Worker struct EvalCatch<Error<CaughtErrorTag, ErrorArgs...>, CaughtErrorTag, Handler> { 129*a65addddSAndroid Build Coastguard Worker using type = 130*a65addddSAndroid Build Coastguard Worker typename DoEval<typename DoEval<Handler>::type::template apply<Error<CaughtErrorTag, ErrorArgs...>>::type>::type; 131*a65addddSAndroid Build Coastguard Worker }; 132*a65addddSAndroid Build Coastguard Worker 133*a65addddSAndroid Build Coastguard Worker template <typename ExprResult, typename Handler> 134*a65addddSAndroid Build Coastguard Worker struct EvalCatchAll { 135*a65addddSAndroid Build Coastguard Worker using type = ExprResult; 136*a65addddSAndroid Build Coastguard Worker }; 137*a65addddSAndroid Build Coastguard Worker 138*a65addddSAndroid Build Coastguard Worker template <typename CaughtErrorTag, typename... ErrorArgs, typename Handler> 139*a65addddSAndroid Build Coastguard Worker struct EvalCatchAll<Error<CaughtErrorTag, ErrorArgs...>, Handler> { 140*a65addddSAndroid Build Coastguard Worker using type = 141*a65addddSAndroid Build Coastguard Worker typename DoEval<typename DoEval<Handler>::type::template apply<Error<CaughtErrorTag, ErrorArgs...>>::type>::type; 142*a65addddSAndroid Build Coastguard Worker }; 143*a65addddSAndroid Build Coastguard Worker 144*a65addddSAndroid Build Coastguard Worker template <typename Expr, typename ErrorTag, typename Handler> 145*a65addddSAndroid Build Coastguard Worker struct DoEval<Catch(Expr, ErrorTag, Handler)> { 146*a65addddSAndroid Build Coastguard Worker using type = typename EvalCatch<typename DoEval<Expr>::type, typename DoEval<ErrorTag>::type, Handler>::type; 147*a65addddSAndroid Build Coastguard Worker }; 148*a65addddSAndroid Build Coastguard Worker 149*a65addddSAndroid Build Coastguard Worker template <typename Expr, typename ErrorTag, typename Handler> 150*a65addddSAndroid Build Coastguard Worker struct DoEval<Catch (*)(Expr, ErrorTag, Handler)> { 151*a65addddSAndroid Build Coastguard Worker using type = typename EvalCatch<typename DoEval<Expr>::type, typename DoEval<ErrorTag>::type, Handler>::type; 152*a65addddSAndroid Build Coastguard Worker }; 153*a65addddSAndroid Build Coastguard Worker 154*a65addddSAndroid Build Coastguard Worker template <typename Expr, typename Handler> 155*a65addddSAndroid Build Coastguard Worker struct DoEval<CatchAll(Expr, Handler)> { 156*a65addddSAndroid Build Coastguard Worker using type = typename EvalCatchAll<typename DoEval<Expr>::type, Handler>::type; 157*a65addddSAndroid Build Coastguard Worker }; 158*a65addddSAndroid Build Coastguard Worker 159*a65addddSAndroid Build Coastguard Worker template <typename Expr, typename Handler> 160*a65addddSAndroid Build Coastguard Worker struct DoEval<CatchAll (*)(Expr, Handler)> { 161*a65addddSAndroid Build Coastguard Worker using type = typename EvalCatchAll<typename DoEval<Expr>::type, Handler>::type; 162*a65addddSAndroid Build Coastguard Worker }; 163*a65addddSAndroid Build Coastguard Worker 164*a65addddSAndroid Build Coastguard Worker template <typename MetaBool, typename ThenMetaExpr, typename ElseMetaExpr> 165*a65addddSAndroid Build Coastguard Worker struct EvalIf; 166*a65addddSAndroid Build Coastguard Worker 167*a65addddSAndroid Build Coastguard Worker template <typename ErrorTag, typename... ErrorArgs, typename ThenMetaExpr, typename ElseMetaExpr> 168*a65addddSAndroid Build Coastguard Worker struct EvalIf<Error<ErrorTag, ErrorArgs...>, ThenMetaExpr, ElseMetaExpr> { 169*a65addddSAndroid Build Coastguard Worker using type = Error<ErrorTag, ErrorArgs...>; 170*a65addddSAndroid Build Coastguard Worker }; 171*a65addddSAndroid Build Coastguard Worker 172*a65addddSAndroid Build Coastguard Worker template <typename ThenMetaExpr, typename ElseMetaExpr> 173*a65addddSAndroid Build Coastguard Worker struct EvalIf<Bool<true>, ThenMetaExpr, ElseMetaExpr> { 174*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 175*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 176*a65addddSAndroid Build Coastguard Worker return true; 177*a65addddSAndroid Build Coastguard Worker } 178*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 179*a65addddSAndroid Build Coastguard Worker #endif 180*a65addddSAndroid Build Coastguard Worker using type = typename DoEval<ThenMetaExpr>::type; 181*a65addddSAndroid Build Coastguard Worker }; 182*a65addddSAndroid Build Coastguard Worker 183*a65addddSAndroid Build Coastguard Worker template <typename ThenMetaExpr, typename ElseMetaExpr> 184*a65addddSAndroid Build Coastguard Worker struct EvalIf<Bool<false>, ThenMetaExpr, ElseMetaExpr> { 185*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 186*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 187*a65addddSAndroid Build Coastguard Worker return true; 188*a65addddSAndroid Build Coastguard Worker } 189*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 190*a65addddSAndroid Build Coastguard Worker #endif 191*a65addddSAndroid Build Coastguard Worker using type = typename DoEval<ElseMetaExpr>::type; 192*a65addddSAndroid Build Coastguard Worker }; 193*a65addddSAndroid Build Coastguard Worker 194*a65addddSAndroid Build Coastguard Worker template <typename CondMetaExpr, typename ThenMetaExpr, typename ElseMetaExpr> 195*a65addddSAndroid Build Coastguard Worker struct DoEval<If(CondMetaExpr, ThenMetaExpr, ElseMetaExpr)> { 196*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 197*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 198*a65addddSAndroid Build Coastguard Worker return true; 199*a65addddSAndroid Build Coastguard Worker } 200*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 201*a65addddSAndroid Build Coastguard Worker #endif 202*a65addddSAndroid Build Coastguard Worker using type = typename EvalIf<typename DoEval<CondMetaExpr>::type, ThenMetaExpr, ElseMetaExpr>::type; 203*a65addddSAndroid Build Coastguard Worker }; 204*a65addddSAndroid Build Coastguard Worker 205*a65addddSAndroid Build Coastguard Worker // Similar to the previous specialization, but this will be selected when the function signature 206*a65addddSAndroid Build Coastguard Worker // became a function pointer (this happens when a signature parameter is itself a signature). 207*a65addddSAndroid Build Coastguard Worker template <typename CondMetaExpr, typename ThenMetaExpr, typename ElseMetaExpr> 208*a65addddSAndroid Build Coastguard Worker struct DoEval<If (*)(CondMetaExpr, ThenMetaExpr, ElseMetaExpr)> { 209*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 210*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 211*a65addddSAndroid Build Coastguard Worker return true; 212*a65addddSAndroid Build Coastguard Worker } 213*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 214*a65addddSAndroid Build Coastguard Worker #endif 215*a65addddSAndroid Build Coastguard Worker using type = typename EvalIf<typename DoEval<CondMetaExpr>::type, ThenMetaExpr, ElseMetaExpr>::type; 216*a65addddSAndroid Build Coastguard Worker }; 217*a65addddSAndroid Build Coastguard Worker 218*a65addddSAndroid Build Coastguard Worker template <typename T, typename ElseMetaExpr> 219*a65addddSAndroid Build Coastguard Worker struct EvalPropagateError { 220*a65addddSAndroid Build Coastguard Worker using type = typename DoEval<ElseMetaExpr>::type; 221*a65addddSAndroid Build Coastguard Worker }; 222*a65addddSAndroid Build Coastguard Worker 223*a65addddSAndroid Build Coastguard Worker template <typename ErrorTag, typename... ErrorArgs, typename ElseMetaExpr> 224*a65addddSAndroid Build Coastguard Worker struct EvalPropagateError<Error<ErrorTag, ErrorArgs...>, ElseMetaExpr> { 225*a65addddSAndroid Build Coastguard Worker using type = Error<ErrorTag, ErrorArgs...>; 226*a65addddSAndroid Build Coastguard Worker }; 227*a65addddSAndroid Build Coastguard Worker 228*a65addddSAndroid Build Coastguard Worker template <typename MaybeErrorMetaExpr, typename ElseMetaExpr> 229*a65addddSAndroid Build Coastguard Worker struct DoEval<PropagateError(MaybeErrorMetaExpr, ElseMetaExpr)> { 230*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 231*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 232*a65addddSAndroid Build Coastguard Worker return true; 233*a65addddSAndroid Build Coastguard Worker } 234*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 235*a65addddSAndroid Build Coastguard Worker #endif 236*a65addddSAndroid Build Coastguard Worker using type = typename EvalPropagateError<typename DoEval<MaybeErrorMetaExpr>::type, ElseMetaExpr>::type; 237*a65addddSAndroid Build Coastguard Worker }; 238*a65addddSAndroid Build Coastguard Worker 239*a65addddSAndroid Build Coastguard Worker // Similar to the previous specialization, but this will be selected when the function signature 240*a65addddSAndroid Build Coastguard Worker // became a function pointer (this happens when a signature parameter is itself a signature). 241*a65addddSAndroid Build Coastguard Worker template <typename MaybeErrorMetaExpr, typename ElseMetaExpr> 242*a65addddSAndroid Build Coastguard Worker struct DoEval<PropagateError (*)(MaybeErrorMetaExpr, ElseMetaExpr)> { 243*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS 244*a65addddSAndroid Build Coastguard Worker constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { 245*a65addddSAndroid Build Coastguard Worker return true; 246*a65addddSAndroid Build Coastguard Worker } 247*a65addddSAndroid Build Coastguard Worker static_assert(static_warning(), ""); 248*a65addddSAndroid Build Coastguard Worker #endif 249*a65addddSAndroid Build Coastguard Worker using type = typename EvalPropagateError<typename DoEval<MaybeErrorMetaExpr>::type, ElseMetaExpr>::type; 250*a65addddSAndroid Build Coastguard Worker }; 251*a65addddSAndroid Build Coastguard Worker 252*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr> 253*a65addddSAndroid Build Coastguard Worker using Eval = typename DoEval<MetaExpr>::type; 254*a65addddSAndroid Build Coastguard Worker 255*a65addddSAndroid Build Coastguard Worker } // namespace meta 256*a65addddSAndroid Build Coastguard Worker } // namespace impl 257*a65addddSAndroid Build Coastguard Worker } // namespace fruit 258*a65addddSAndroid Build Coastguard Worker 259*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_META_EVAL_H 260