9
3

meta_create.hpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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_KARMA_META_CREATE_NOV_21_2009_0425PM)
  6. #define BOOST_SPIRIT_KARMA_META_CREATE_NOV_21_2009_0425PM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/spirit/home/karma/domain.hpp>
  11. #include <boost/spirit/home/support/common_terminals.hpp>
  12. #include <boost/spirit/home/support/auto/meta_create.hpp>
  13. #include <boost/utility/enable_if.hpp>
  14. #include <boost/variant.hpp>
  15. #include <boost/optional.hpp>
  16. #include <boost/config.hpp>
  17. #include <boost/mpl/not.hpp>
  18. #include <boost/mpl/fold.hpp>
  19. #include <boost/mpl/vector.hpp>
  20. #include <boost/mpl/push_back.hpp>
  21. #include <boost/fusion/include/as_vector.hpp>
  22. #include <boost/type_traits/is_same.hpp>
  23. ///////////////////////////////////////////////////////////////////////////////
  24. namespace boost { namespace spirit { namespace karma
  25. {
  26. ///////////////////////////////////////////////////////////////////////////
  27. // compatible STL containers
  28. template <typename Container>
  29. struct meta_create_container
  30. {
  31. typedef make_unary_proto_expr<
  32. typename Container::value_type
  33. , proto::tag::dereference, karma::domain
  34. > make_proto_expr;
  35. typedef typename make_proto_expr::type type;
  36. static type call()
  37. {
  38. return make_proto_expr::call();
  39. }
  40. };
  41. ///////////////////////////////////////////////////////////////////////////
  42. // String types
  43. template <typename String>
  44. struct meta_create_string
  45. {
  46. typedef spirit::standard::string_type type;
  47. static type const call() { return type(); }
  48. };
  49. template <>
  50. struct meta_create_string<wchar_t*>
  51. {
  52. typedef spirit::standard_wide::string_type type;
  53. static type const call() { return type(); }
  54. };
  55. template <>
  56. struct meta_create_string<wchar_t const*>
  57. {
  58. typedef spirit::standard_wide::string_type type;
  59. static type const call() { return type(); }
  60. };
  61. template <int N>
  62. struct meta_create_string<wchar_t[N]>
  63. {
  64. typedef spirit::standard_wide::string_type type;
  65. static type const call() { return type(); }
  66. };
  67. template <int N>
  68. struct meta_create_string<wchar_t const[N]>
  69. {
  70. typedef spirit::standard_wide::string_type type;
  71. static type const call() { return type(); }
  72. };
  73. template <int N>
  74. struct meta_create_string<wchar_t(&)[N]>
  75. {
  76. typedef spirit::standard_wide::string_type type;
  77. static type const call() { return type(); }
  78. };
  79. template <int N>
  80. struct meta_create_string<wchar_t const(&)[N]>
  81. {
  82. typedef spirit::standard_wide::string_type type;
  83. static type const call() { return type(); }
  84. };
  85. template <typename Traits, typename Allocator>
  86. struct meta_create_string<std::basic_string<wchar_t, Traits, Allocator> >
  87. {
  88. typedef spirit::standard_wide::string_type type;
  89. static type const call() { return type(); }
  90. };
  91. ///////////////////////////////////////////////////////////////////////////
  92. // Fusion sequences
  93. template <typename Sequence>
  94. struct meta_create_sequence
  95. {
  96. // create a mpl sequence from the given fusion sequence
  97. typedef typename mpl::fold<
  98. typename fusion::result_of::as_vector<Sequence>::type
  99. , mpl::vector<>, mpl::push_back<mpl::_, mpl::_>
  100. >::type sequence_type;
  101. typedef make_nary_proto_expr<
  102. sequence_type, proto::tag::shift_left, karma::domain
  103. > make_proto_expr;
  104. typedef typename make_proto_expr::type type;
  105. static type call()
  106. {
  107. return make_proto_expr::call();
  108. }
  109. };
  110. ///////////////////////////////////////////////////////////////////////////
  111. // the default is to use the standard streaming operator unless it's a
  112. // STL container or a fusion sequence
  113. // The default implementation will be chosen if no predefined mapping of
  114. // the data type T to a Karma component is defined.
  115. struct no_auto_mapping_exists {};
  116. template <typename T, typename Enable = void>
  117. struct meta_create_impl : mpl::identity<no_auto_mapping_exists> {};
  118. template <typename T>
  119. struct meta_create_impl<T
  120. , typename enable_if<
  121. mpl::and_<
  122. traits::is_container<T>
  123. , mpl::not_<traits::is_string<T> >
  124. , mpl::not_<fusion::traits::is_sequence<T> >
  125. > >::type>
  126. : meta_create_container<T> {};
  127. template <typename T>
  128. struct meta_create_impl<T
  129. , typename enable_if<traits::is_string<T> >::type>
  130. : meta_create_string<T> {};
  131. template <typename T>
  132. struct meta_create_impl<T, typename enable_if<
  133. spirit::detail::is_fusion_sequence_but_not_proto_expr<T>
  134. >::type>
  135. : meta_create_sequence<T> {};
  136. template <typename T, typename Enable = void>
  137. struct meta_create : meta_create_impl<T> {};
  138. ///////////////////////////////////////////////////////////////////////////
  139. // optional
  140. template <typename T>
  141. struct meta_create<boost::optional<T> >
  142. {
  143. typedef make_unary_proto_expr<
  144. T, proto::tag::negate, karma::domain
  145. > make_proto_expr;
  146. typedef typename make_proto_expr::type type;
  147. static type call()
  148. {
  149. return make_proto_expr::call();
  150. }
  151. };
  152. ///////////////////////////////////////////////////////////////////////////
  153. // alternatives
  154. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  155. struct meta_create<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  156. {
  157. typedef make_nary_proto_expr<
  158. typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
  159. , proto::tag::bitwise_or, karma::domain
  160. > make_proto_expr;
  161. typedef typename make_proto_expr::type type;
  162. static type call()
  163. {
  164. return make_proto_expr::call();
  165. }
  166. };
  167. ///////////////////////////////////////////////////////////////////////////
  168. // predefined specializations for primitive components
  169. // character generator
  170. template <>
  171. struct meta_create<char>
  172. {
  173. typedef spirit::standard::char_type type;
  174. static type const call() { return type(); }
  175. };
  176. template <>
  177. struct meta_create<signed char>
  178. {
  179. typedef spirit::standard::char_type type;
  180. static type const call() { return type(); }
  181. };
  182. template <>
  183. struct meta_create<wchar_t>
  184. {
  185. typedef spirit::standard_wide::char_type type;
  186. static type const call() { return type(); }
  187. };
  188. template <>
  189. struct meta_create<unsigned char>
  190. {
  191. typedef spirit::standard::char_type type;
  192. static type const call() { return type(); }
  193. };
  194. // boolean generator
  195. template <>
  196. struct meta_create<bool>
  197. {
  198. typedef spirit::bool_type type;
  199. static type call() { return type(); }
  200. };
  201. // integral generators
  202. template <>
  203. struct meta_create<int>
  204. {
  205. typedef spirit::int_type type;
  206. static type call() { return type(); }
  207. };
  208. template <>
  209. struct meta_create<short>
  210. {
  211. typedef spirit::short_type type;
  212. static type call() { return type(); }
  213. };
  214. template <>
  215. struct meta_create<long>
  216. {
  217. typedef spirit::long_type type;
  218. static type call() { return type(); }
  219. };
  220. template <>
  221. struct meta_create<unsigned int>
  222. {
  223. typedef spirit::uint_type type;
  224. static type call() { return type(); }
  225. };
  226. #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  227. template <>
  228. struct meta_create<unsigned short>
  229. {
  230. typedef spirit::ushort_type type;
  231. static type call() { return type(); }
  232. };
  233. #endif
  234. template <>
  235. struct meta_create<unsigned long>
  236. {
  237. typedef spirit::ulong_type type;
  238. static type call() { return type(); }
  239. };
  240. #ifdef BOOST_HAS_LONG_LONG
  241. template <>
  242. struct meta_create<boost::long_long_type>
  243. {
  244. typedef spirit::long_long_type type;
  245. static type call() { return type(); }
  246. };
  247. template <>
  248. struct meta_create<boost::ulong_long_type>
  249. {
  250. typedef spirit::ulong_long_type type;
  251. static type call() { return type(); }
  252. };
  253. #endif
  254. // floating point generators
  255. template <>
  256. struct meta_create<float>
  257. {
  258. typedef spirit::float_type type;
  259. static type call() { return type(); }
  260. };
  261. template <>
  262. struct meta_create<double>
  263. {
  264. typedef spirit::double_type type;
  265. static type call() { return type(); }
  266. };
  267. template <>
  268. struct meta_create<long double>
  269. {
  270. typedef spirit::long_double_type type;
  271. static type call() { return type(); }
  272. };
  273. }}}
  274. ///////////////////////////////////////////////////////////////////////////////
  275. namespace boost { namespace spirit { namespace traits
  276. {
  277. ///////////////////////////////////////////////////////////////////////////
  278. // main customization point for create_generator
  279. template <typename T, typename Enable = void>
  280. struct create_generator : karma::meta_create<T> {};
  281. ///////////////////////////////////////////////////////////////////////////
  282. // dispatch this to the karma related specializations
  283. template <typename T>
  284. struct meta_create<karma::domain, T>
  285. : create_generator<typename spirit::detail::remove_const_ref<T>::type> {};
  286. ///////////////////////////////////////////////////////////////////////////
  287. // Check whether a valid mapping exits for the given data type to a Karma
  288. // component
  289. template <typename T>
  290. struct meta_create_exists<karma::domain, T>
  291. : mpl::not_<is_same<
  292. karma::no_auto_mapping_exists
  293. , typename meta_create<karma::domain, T>::type
  294. > > {};
  295. }}}
  296. #endif