function_eval.hpp 5.2 KB

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