/* * Copyright 2014 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FRUIT_META_EVAL_H #define FRUIT_META_EVAL_H #include #include #include #include namespace fruit { namespace impl { namespace meta { template struct DoEval; // General case, meta-constant. template struct DoEval { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = MetaExpr; }; template struct SimpleIsError { static constexpr bool value = false; }; template struct SimpleIsError> { static constexpr bool value = true; }; #if FRUIT_EXTRA_DEBUG // For debugging, we use a separate DoEvalFun so that we get longer (and more informative) // instantiation traces. template struct DoEvalFun { using type = typename DoEval::value...>::value, ExtractFirstError, MetaFun>::type::template apply::type>::type; }; template struct DoEval { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename DoEvalFun::type...>::type; }; // Similar to the previous specialization, but this will be selected when the function signature // became a function pointer (this happens when a signature parameter is itself a signature). template struct DoEval { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename DoEvalFun::type...>::type; }; #else // FRUIT_EXTRA_DEBUG template struct DoEval { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename DoEval::type>::value...>::value, ExtractFirstError, MetaFun>::type::template apply::type...>::type>::type; }; // Similar to the previous specialization, but this will be selected when the function signature // became a function pointer (this happens when a signature parameter is itself a signature). template struct DoEval { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename DoEval::type>::value...>::value, ExtractFirstError, MetaFun>::type::template apply::type...>::type>::type; }; #endif // FRUIT_EXTRA_DEBUG template struct EvalCatch { using type = ExprResult; }; template struct EvalCatch, CaughtErrorTag, Handler> { using type = typename DoEval::type::template apply>::type>::type; }; template struct EvalCatchAll { using type = ExprResult; }; template struct EvalCatchAll, Handler> { using type = typename DoEval::type::template apply>::type>::type; }; template struct DoEval { using type = typename EvalCatch::type, typename DoEval::type, Handler>::type; }; template struct DoEval { using type = typename EvalCatch::type, typename DoEval::type, Handler>::type; }; template struct DoEval { using type = typename EvalCatchAll::type, Handler>::type; }; template struct DoEval { using type = typename EvalCatchAll::type, Handler>::type; }; template struct EvalIf; template struct EvalIf, ThenMetaExpr, ElseMetaExpr> { using type = Error; }; template struct EvalIf, ThenMetaExpr, ElseMetaExpr> { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename DoEval::type; }; template struct EvalIf, ThenMetaExpr, ElseMetaExpr> { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename DoEval::type; }; template struct DoEval { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename EvalIf::type, ThenMetaExpr, ElseMetaExpr>::type; }; // Similar to the previous specialization, but this will be selected when the function signature // became a function pointer (this happens when a signature parameter is itself a signature). template struct DoEval { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename EvalIf::type, ThenMetaExpr, ElseMetaExpr>::type; }; template struct EvalPropagateError { using type = typename DoEval::type; }; template struct EvalPropagateError, ElseMetaExpr> { using type = Error; }; template struct DoEval { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename EvalPropagateError::type, ElseMetaExpr>::type; }; // Similar to the previous specialization, but this will be selected when the function signature // became a function pointer (this happens when a signature parameter is itself a signature). template struct DoEval { #if FRUIT_TRACE_INSTANTIATIONS constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) { return true; } static_assert(static_warning(), ""); #endif using type = typename EvalPropagateError::type, ElseMetaExpr>::type; }; template using Eval = typename DoEval::type; } // namespace meta } // namespace impl } // namespace fruit #endif // FRUIT_META_EVAL_H