meta_create.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_SUPPORT_META_CREATE_NOV_21_2009_0327PM)
  6. #define BOOST_SPIRIT_SUPPORT_META_CREATE_NOV_21_2009_0327PM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/spirit/home/support/unused.hpp>
  11. #include <boost/version.hpp>
  12. #include <boost/spirit/include/phoenix_limits.hpp> // needs to be included before proto
  13. #include <boost/proto/proto.hpp>
  14. #include <boost/utility/result_of.hpp>
  15. #include <boost/type_traits/add_const.hpp>
  16. #include <boost/type_traits/add_reference.hpp>
  17. #include <boost/type_traits/remove_const.hpp>
  18. #include <boost/type_traits/remove_reference.hpp>
  19. #include <boost/fusion/include/fold.hpp>
  20. #include <boost/mpl/and.hpp>
  21. #include <boost/mpl/not.hpp>
  22. // needed for workaround below
  23. #if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
  24. #include <boost/type_traits/is_same.hpp>
  25. #endif
  26. namespace boost { namespace spirit { namespace traits
  27. {
  28. ///////////////////////////////////////////////////////////////////////////
  29. // This is the main dispatch point for meta_create to the correct domain
  30. template <typename Domain, typename T, typename Enable = void>
  31. struct meta_create;
  32. ///////////////////////////////////////////////////////////////////////////
  33. // This allows to query whether a valid mapping exists for the given data
  34. // type to a component in the given domain
  35. template <typename Domain, typename T, typename Enable = void>
  36. struct meta_create_exists : mpl::false_ {};
  37. }}}
  38. namespace boost { namespace spirit
  39. {
  40. ///////////////////////////////////////////////////////////////////////////
  41. namespace detail
  42. {
  43. template <typename T>
  44. struct add_const_ref
  45. : add_reference<typename add_const<T>::type> {};
  46. template <typename T>
  47. struct remove_const_ref
  48. : remove_const<typename remove_reference<T>::type> {};
  49. // starting with Boost V1.42 fusion::fold has been changed to be compatible
  50. // with mpl::fold (the sequence of template parameters for the meta-function
  51. // object has been changed)
  52. #if BOOST_VERSION < 104200
  53. ///////////////////////////////////////////////////////////////////////
  54. template <typename OpTag, typename Domain>
  55. struct nary_proto_expr_function
  56. {
  57. template <typename T>
  58. struct result;
  59. // this is a workaround for older versions of g++ (< V4.3) which apparently have
  60. // problems with the following template specialization
  61. #if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
  62. template <typename F, typename T1, typename T2>
  63. struct result<F(T1, T2)>
  64. {
  65. BOOST_STATIC_ASSERT((is_same<F, nary_proto_expr_function>::value));
  66. #else
  67. template <typename T1, typename T2>
  68. struct result<nary_proto_expr_function(T1, T2)>
  69. {
  70. #endif
  71. typedef typename remove_const_ref<T2>::type left_type;
  72. typedef typename
  73. spirit::traits::meta_create<Domain, T1>::type
  74. right_type;
  75. typedef typename mpl::eval_if<
  76. traits::not_is_unused<left_type>
  77. , proto::result_of::make_expr<OpTag, left_type, right_type>
  78. , mpl::identity<right_type>
  79. >::type type;
  80. };
  81. template <typename T>
  82. typename result<nary_proto_expr_function(T, unused_type const&)>::type
  83. operator()(T, unused_type const&) const
  84. {
  85. typedef spirit::traits::meta_create<Domain, T> right_type;
  86. return right_type::call();
  87. }
  88. template <typename T1, typename T2>
  89. typename result<nary_proto_expr_function(T1, T2)>::type
  90. operator()(T1, T2 const& t2) const
  91. {
  92. // we variants to the alternative operator
  93. typedef spirit::traits::meta_create<Domain, T1> right_type;
  94. return proto::make_expr<OpTag>(t2, right_type::call());
  95. }
  96. };
  97. #else
  98. ///////////////////////////////////////////////////////////////////////
  99. template <typename OpTag, typename Domain>
  100. struct nary_proto_expr_function
  101. {
  102. template <typename T>
  103. struct result;
  104. // this is a workaround for older versions of g++ (< V4.3) which apparently have
  105. // problems with the following template specialization
  106. #if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
  107. template <typename F, typename T1, typename T2>
  108. struct result<F(T1, T2)>
  109. {
  110. BOOST_STATIC_ASSERT((is_same<F, nary_proto_expr_function>::value));
  111. #else
  112. template <typename T1, typename T2>
  113. struct result<nary_proto_expr_function(T1, T2)>
  114. {
  115. #endif
  116. typedef typename remove_const_ref<T1>::type left_type;
  117. typedef typename
  118. spirit::traits::meta_create<Domain, T2>::type
  119. right_type;
  120. typedef typename mpl::eval_if<
  121. traits::not_is_unused<left_type>
  122. , proto::result_of::make_expr<OpTag, left_type, right_type>
  123. , mpl::identity<right_type>
  124. >::type type;
  125. };
  126. template <typename T>
  127. typename result<nary_proto_expr_function(unused_type const&, T)>::type
  128. operator()(unused_type const&, T) const
  129. {
  130. typedef spirit::traits::meta_create<Domain, T> right_type;
  131. return right_type::call();
  132. }
  133. template <typename T1, typename T2>
  134. typename result<nary_proto_expr_function(T1, T2)>::type
  135. operator()(T1 const& t1, T2) const
  136. {
  137. // we variants to the alternative operator
  138. typedef spirit::traits::meta_create<Domain, T2> right_type;
  139. return proto::make_expr<OpTag>(t1, right_type::call());
  140. }
  141. };
  142. #endif
  143. }
  144. ///////////////////////////////////////////////////////////////////////
  145. template <typename T, typename OpTag, typename Domain>
  146. struct make_unary_proto_expr
  147. {
  148. typedef spirit::traits::meta_create<Domain, T> subject_type;
  149. typedef typename proto::result_of::make_expr<
  150. OpTag, typename subject_type::type
  151. >::type type;
  152. static type call()
  153. {
  154. return proto::make_expr<OpTag>(subject_type::call());
  155. }
  156. };
  157. ///////////////////////////////////////////////////////////////////////////
  158. template <typename Sequence, typename OpTag, typename Domain>
  159. struct make_nary_proto_expr
  160. {
  161. typedef detail::nary_proto_expr_function<OpTag, Domain>
  162. make_proto_expr;
  163. typedef typename fusion::result_of::fold<
  164. Sequence, unused_type, make_proto_expr
  165. >::type type;
  166. static type call()
  167. {
  168. return fusion::fold(Sequence(), unused, make_proto_expr());
  169. }
  170. };
  171. ///////////////////////////////////////////////////////////////////////////
  172. namespace detail
  173. {
  174. // Starting with newer versions of Proto, all Proto expressions are at
  175. // the same time Fusion sequences. This is the correct behavior, but
  176. // we need to distinguish between Fusion sequences and Proto
  177. // expressions. This meta-function does exactly that.
  178. template <typename T>
  179. struct is_fusion_sequence_but_not_proto_expr
  180. : mpl::and_<
  181. fusion::traits::is_sequence<T>
  182. , mpl::not_<proto::is_expr<T> > >
  183. {};
  184. }
  185. }}
  186. #endif