• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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