action_dispatch.hpp 7.3 KB

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