action_dispatch.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. http://spirit.sourceforge.net/
  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. #if !defined(BOOST_SPIRIT_ACTION_DISPATCH_APRIL_18_2008_0720AM)
  9. #define BOOST_SPIRIT_ACTION_DISPATCH_APRIL_18_2008_0720AM
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include<boost/config.hpp>
  14. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_LAMBDAS) && \
  15. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE)
  16. #include <utility>
  17. #include <type_traits>
  18. #endif
  19. #include <boost/spirit/include/phoenix_core.hpp>
  20. #include <boost/spirit/home/support/attributes.hpp>
  21. namespace boost { namespace spirit { namespace traits
  22. {
  23. template <typename Component>
  24. struct action_dispatch
  25. {
  26. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_LAMBDAS) && \
  27. !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE)
  28. // omit function parameters without specializing for each possible
  29. // type of callable entity
  30. // many thanks to Eelis/##iso-c++ for this contribution
  31. private:
  32. // this will be used to pass around POD types which are safe
  33. // to go through the ellipsis operator (if ever used)
  34. template <typename>
  35. struct fwd_tag {};
  36. // the first parameter is a placeholder to obtain SFINAE when
  37. // doing overload resolution, the second one is the actual
  38. // forwarder, where we can apply our implementation
  39. template <typename, typename T>
  40. struct fwd_storage { typedef T type; };
  41. // gcc should accept fake<T>() but it prints a sorry, needs
  42. // a check once the bug is sorted out, use a FAKE_CALL macro for now
  43. template <typename T>
  44. T fake_call();
  45. #define BOOST_SPIRIT_FAKE_CALL(T) (*(T*)0)
  46. // the forwarders, here we could tweak the implementation of
  47. // how parameters are passed to the functions, if needed
  48. struct fwd_none
  49. {
  50. template<typename F, typename... Rest>
  51. auto operator()(F && f, Rest&&...) -> decltype(f())
  52. {
  53. return f();
  54. }
  55. };
  56. struct fwd_attrib
  57. {
  58. template<typename F, typename A, typename... Rest>
  59. auto operator()(F && f, A && a, Rest&&...) -> decltype(f(a))
  60. {
  61. return f(a);
  62. }
  63. };
  64. struct fwd_attrib_context
  65. {
  66. template<typename F, typename A, typename B, typename... Rest>
  67. auto operator()(F && f, A && a, B && b, Rest&&...)
  68. -> decltype(f(a, b))
  69. {
  70. return f(a, b);
  71. }
  72. };
  73. struct fwd_attrib_context_pass
  74. {
  75. template<typename F, typename A, typename B, typename C
  76. , typename... Rest>
  77. auto operator()(F && f, A && a, B && b, C && c, Rest&&...)
  78. -> decltype(f(a, b, c))
  79. {
  80. return f(a, b, c);
  81. }
  82. };
  83. // SFINAE for our calling syntax, the forwarders are stored based
  84. // on what function call gives a proper result
  85. // this code can probably be more generic once implementations are
  86. // steady
  87. template <typename F>
  88. static auto do_call(F && f, ...)
  89. -> typename fwd_storage<decltype(f()), fwd_none>::type
  90. {
  91. return {};
  92. }
  93. template <typename F, typename A>
  94. static auto do_call(F && f, fwd_tag<A>, ...)
  95. -> typename fwd_storage<decltype(f(BOOST_SPIRIT_FAKE_CALL(A)))
  96. , fwd_attrib>::type
  97. {
  98. return {};
  99. }
  100. template <typename F, typename A, typename B>
  101. static auto do_call(F && f, fwd_tag<A>, fwd_tag<B>, ...)
  102. -> typename fwd_storage<
  103. decltype(f(BOOST_SPIRIT_FAKE_CALL(A), BOOST_SPIRIT_FAKE_CALL(B)))
  104. , fwd_attrib_context>::type
  105. {
  106. return {};
  107. }
  108. template <typename F, typename A, typename B, typename C>
  109. static auto do_call(F && f, fwd_tag<A>, fwd_tag<B>, fwd_tag<C>, ...)
  110. -> typename fwd_storage<
  111. decltype(f(BOOST_SPIRIT_FAKE_CALL(A), BOOST_SPIRIT_FAKE_CALL(B)
  112. , BOOST_SPIRIT_FAKE_CALL(C)))
  113. , fwd_attrib_context_pass>::type
  114. {
  115. return {};
  116. }
  117. // this function calls the forwarder and is responsible for
  118. // stripping the tail of the parameters
  119. template <typename F, typename... A>
  120. static void caller(F && f, A && ... a)
  121. {
  122. do_call(f, fwd_tag<typename std::remove_reference<A>::type>()...)
  123. (std::forward<F>(f), std::forward<A>(a)...);
  124. }
  125. #undef BOOST_SPIRIT_FAKE_CALL
  126. public:
  127. template <typename F, typename Attribute, typename Context>
  128. bool operator()(F const& f, Attribute& attr, Context& context)
  129. {
  130. bool pass = true;
  131. caller(f, attr, context, pass);
  132. return pass;
  133. }
  134. #else
  135. // general handler for everything not explicitly specialized below
  136. template <typename F, typename Attribute, typename Context>
  137. bool operator()(F const& f, Attribute& attr, Context& context)
  138. {
  139. bool pass = true;
  140. f(attr, context, pass);
  141. return pass;
  142. }
  143. #endif
  144. // handler for phoenix actors
  145. // If the component this action has to be invoked for is a tuple, we
  146. // wrap any non-fusion tuple into a fusion tuple (done by pass_attribute)
  147. // and pass through any fusion tuple.
  148. template <typename Eval, typename Attribute, typename Context>
  149. bool operator()(phoenix::actor<Eval> const& f
  150. , Attribute& attr, Context& context)
  151. {
  152. bool pass = true;
  153. typename pass_attribute<Component, Attribute>::type attr_wrap(attr);
  154. f(attr_wrap, context, pass);
  155. return pass;
  156. }
  157. // specializations for plain function pointers taking different number of
  158. // arguments
  159. template <typename RT, typename A0, typename A1, typename A2
  160. , typename Attribute, typename Context>
  161. bool operator()(RT(*f)(A0, A1, A2), Attribute& attr, Context& context)
  162. {
  163. bool pass = true;
  164. f(attr, context, pass);
  165. return pass;
  166. }
  167. template <typename RT, typename A0, typename A1
  168. , typename Attribute, typename Context>
  169. bool operator()(RT(*f)(A0, A1), Attribute& attr, Context& context)
  170. {
  171. f(attr, context);
  172. return true;
  173. }
  174. template <typename RT, typename A0, typename Attribute, typename Context>
  175. bool operator()(RT(*f)(A0), Attribute& attr, Context&)
  176. {
  177. f(attr);
  178. return true;
  179. }
  180. template <typename RT, typename Attribute, typename Context>
  181. bool operator()(RT(*f)(), Attribute&, Context&)
  182. {
  183. f();
  184. return true;
  185. }
  186. };
  187. }}}
  188. #endif