meta_create.hpp 9.9 KB

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