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