1 /*============================================================================= 2 Copyright (c) 2001-2007 Joel de Guzman 3 Copyright (c) 2015 Kohei Takahashi 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 9 #ifndef BOOST_PHOENIX_CORE_DETAIL_FUNCTION_EVAL_HPP 10 #define BOOST_PHOENIX_CORE_DETAIL_FUNCTION_EVAL_HPP 11 12 #include <boost/phoenix/core/limits.hpp> 13 #include <boost/phoenix/support/iterate.hpp> 14 #include <boost/phoenix/core/call.hpp> 15 #include <boost/phoenix/core/expression.hpp> 16 #include <boost/phoenix/core/meta_grammar.hpp> 17 #include <boost/utility/result_of.hpp> 18 19 #ifndef BOOST_PHOENIX_NO_VARIADIC_FUNCTION_EVAL 20 # include <boost/mpl/if.hpp> 21 # include <boost/type_traits/is_reference.hpp> 22 #endif 23 24 #ifdef BOOST_PHOENIX_NO_VARIADIC_EXPRESSION 25 # include <boost/phoenix/core/detail/cpp03/function_eval_expr.hpp> 26 #else 27 BOOST_PHOENIX_DEFINE_EXPRESSION_VARARG( 28 (boost)(phoenix)(detail)(function_eval) 29 , (meta_grammar)(meta_grammar) 30 , _ 31 ) 32 #endif 33 34 namespace boost { namespace phoenix { 35 namespace detail 36 { 37 template <typename T> help_rvalue_deduction(T & x)38 T& help_rvalue_deduction(T& x) 39 { 40 return x; 41 } 42 43 template <typename T> help_rvalue_deduction(T const & x)44 T const& help_rvalue_deduction(T const& x) 45 { 46 return x; 47 } 48 49 struct function_eval 50 { 51 template <typename Sig> 52 struct result; 53 54 #ifdef BOOST_PHOENIX_NO_VARIADIC_FUNCTION_EVAL 55 template <typename This, typename F, typename Context> 56 struct result<This(F, Context)> 57 { 58 typedef typename 59 remove_reference< 60 typename boost::result_of<evaluator(F, Context)>::type 61 >::type 62 fn; 63 64 typedef typename boost::result_of<fn()>::type type; 65 }; 66 67 template <typename F, typename Context> 68 typename result<function_eval(F const&, Context const&)>::type operator ()boost::phoenix::detail::function_eval69 operator()(F const & f, Context const & ctx) const 70 { 71 return boost::phoenix::eval(f, ctx)(); 72 } 73 74 template <typename F, typename Context> 75 typename result<function_eval(F &, Context const&)>::type operator ()boost::phoenix::detail::function_eval76 operator()(F & f, Context const & ctx) const 77 { 78 return boost::phoenix::eval(f, ctx)(); 79 } 80 81 #include <boost/phoenix/core/detail/cpp03/function_eval.hpp> 82 #else 83 template <typename, typename, typename...> struct result_impl; 84 85 template <typename F, typename... A, typename Head, typename... Tail> 86 struct result_impl<F, void(A...), Head, Tail...> 87 : result_impl<F, void(A..., Head), Tail...> 88 { 89 }; 90 91 template <typename F, typename... A, typename Context> 92 struct result_impl<F, void(A...), Context> 93 { 94 typedef typename 95 remove_reference< 96 typename boost::result_of<evaluator(F, Context)>::type 97 >::type 98 fn; 99 100 template <typename T> 101 struct result_of_evaluator 102 { 103 typedef typename boost::add_reference< 104 typename boost::add_const< 105 typename boost::result_of< 106 boost::phoenix::evaluator(T, Context) 107 >::type 108 >::type 109 >::type type; 110 }; 111 112 typedef typename 113 boost::result_of< 114 fn(typename result_of_evaluator<A>::type...) 115 >::type 116 type; 117 callboost::phoenix::detail::function_eval::result_impl118 static type call(F f, A... a, Context ctx) 119 { 120 return boost::phoenix::eval(f, ctx)(help_rvalue_deduction(boost::phoenix::eval(a, ctx))...); 121 } 122 }; 123 124 template <typename This, typename F, typename... A> 125 struct result<This(F, A...)> 126 : result_impl<F, void(), A...> 127 { 128 }; 129 130 template <typename F, typename... A> 131 typename result< 132 function_eval( 133 F const & 134 , typename mpl::if_<is_reference<A>, A, A const &>::type... 135 ) 136 >::type 137 // 'A &... a, Context const &ctx' doesn't work as intended: type deduction always fail. operator ()boost::phoenix::detail::function_eval138 operator()(F && f, A &&... a) const 139 { 140 return 141 result< 142 function_eval( 143 typename mpl::if_<is_reference<F>, F, F const &>::type 144 , typename mpl::if_<is_reference<A>, A, A const &>::type... 145 ) 146 >::call(f, a...); 147 } 148 #endif 149 }; 150 151 } 152 153 template <typename Dummy> 154 struct default_actions::when<detail::rule::function_eval, Dummy> 155 : phoenix::call<detail::function_eval> 156 {}; 157 }} 158 159 #endif 160