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