]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // env.hpp | |
3 | // Helpers for producing and consuming tranform env variables. | |
4 | // | |
5 | // Copyright 2012 Eric Niebler. Distributed under the Boost | |
6 | // Software License, Version 1.0. (See accompanying file | |
7 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ||
9 | #ifndef BOOST_PROTO_TRANSFORM_ENV_HPP_EAN_18_07_2012 | |
10 | #define BOOST_PROTO_TRANSFORM_ENV_HPP_EAN_18_07_2012 | |
11 | ||
12 | #include <boost/config.hpp> | |
13 | #include <boost/detail/workaround.hpp> | |
14 | #include <boost/ref.hpp> | |
15 | #include <boost/utility/enable_if.hpp> | |
16 | #include <boost/type_traits/is_const.hpp> | |
17 | #include <boost/type_traits/is_same.hpp> | |
18 | #include <boost/type_traits/add_const.hpp> | |
19 | #include <boost/type_traits/add_reference.hpp> | |
20 | #include <boost/type_traits/remove_const.hpp> | |
21 | #include <boost/mpl/assert.hpp> | |
22 | #include <boost/mpl/bool.hpp> | |
23 | #include <boost/mpl/if.hpp> | |
24 | #include <boost/mpl/not.hpp> | |
25 | #include <boost/proto/proto_fwd.hpp> | |
26 | #include <boost/proto/transform/impl.hpp> | |
27 | #include <boost/proto/detail/poly_function.hpp> | |
28 | #include <boost/proto/detail/is_noncopyable.hpp> | |
29 | ||
30 | #ifdef _MSC_VER | |
31 | # pragma warning(push) | |
32 | # pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored | |
33 | #endif | |
34 | ||
35 | namespace boost | |
36 | { | |
37 | namespace proto | |
38 | { | |
39 | namespace detail | |
40 | { | |
41 | template<typename T> | |
42 | struct value_type | |
43 | { | |
44 | typedef typename remove_const<T>::type value; | |
45 | typedef typename add_reference<T>::type reference; | |
46 | typedef typename mpl::if_c<is_noncopyable<T>::value, reference, value>::type type; | |
47 | }; | |
48 | ||
49 | template<typename T> | |
50 | struct value_type<T &> | |
51 | { | |
52 | typedef T &value; | |
53 | typedef T &reference; | |
54 | typedef T &type; | |
55 | }; | |
56 | } | |
57 | ||
58 | #define BOOST_PROTO_DEFINE_ENV_VAR(TAG, NAME) \ | |
59 | struct TAG \ | |
60 | { \ | |
61 | template<typename Value> \ | |
62 | boost::proto::env<TAG, Value &> const \ | |
63 | operator =(boost::reference_wrapper<Value> &value) const \ | |
64 | { \ | |
65 | return boost::proto::env<TAG, Value &>(value.get()); \ | |
66 | } \ | |
67 | template<typename Value> \ | |
68 | boost::proto::env<TAG, Value &> const \ | |
69 | operator =(boost::reference_wrapper<Value> const &value) const \ | |
70 | { \ | |
71 | return boost::proto::env<TAG, Value &>(value.get()); \ | |
72 | } \ | |
73 | template<typename Value> \ | |
74 | typename boost::disable_if_c< \ | |
75 | boost::is_const<Value>::value \ | |
76 | , boost::proto::env<TAG, typename boost::proto::detail::value_type<Value>::type> \ | |
77 | >::type const operator =(Value &value) const \ | |
78 | { \ | |
79 | return boost::proto::env<TAG, typename boost::proto::detail::value_type<Value>::type>(value); \ | |
80 | } \ | |
81 | template<typename Value> \ | |
82 | boost::proto::env<TAG, typename boost::proto::detail::value_type<Value const>::type> const \ | |
83 | operator =(Value const &value) const \ | |
84 | { \ | |
85 | return boost::proto::env<TAG, typename boost::proto::detail::value_type<Value const>::type>(value); \ | |
86 | } \ | |
87 | }; \ | |
88 | \ | |
89 | TAG const NAME = {} \ | |
90 | /**/ | |
91 | ||
92 | namespace envns_ | |
93 | { | |
94 | //////////////////////////////////////////////////////////////////////////////////////////// | |
95 | // env | |
96 | // A transform env is a slot-based storage mechanism, accessible by tag. | |
97 | template<typename Key, typename Value, typename Base /*= empty_env*/> | |
98 | struct env | |
99 | : private Base | |
100 | { | |
101 | private: | |
102 | Value value_; | |
103 | ||
104 | public: | |
105 | typedef Value value_type; | |
106 | typedef typename add_reference<Value>::type reference; | |
107 | typedef typename add_reference<typename add_const<Value>::type>::type const_reference; | |
108 | typedef void proto_environment_; ///< INTERNAL ONLY | |
109 | ||
110 | explicit env(const_reference value, Base const &base = Base()) | |
111 | : Base(base) | |
112 | , value_(value) | |
113 | {} | |
114 | ||
115 | #if BOOST_WORKAROUND(__GNUC__, == 3) || (BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ <= 2) | |
116 | /// INTERNAL ONLY | |
117 | struct found | |
118 | { | |
119 | typedef Value type; | |
120 | typedef typename add_reference<typename add_const<Value>::type>::type const_reference; | |
121 | }; | |
122 | ||
123 | template<typename OtherKey, typename OtherValue = key_not_found> | |
124 | struct lookup | |
125 | : mpl::if_c< | |
126 | is_same<OtherKey, Key>::value | |
127 | , found | |
128 | , typename Base::template lookup<OtherKey, OtherValue> | |
129 | >::type | |
130 | {}; | |
131 | #else | |
132 | /// INTERNAL ONLY | |
133 | template<typename OtherKey, typename OtherValue = key_not_found> | |
134 | struct lookup | |
135 | : Base::template lookup<OtherKey, OtherValue> | |
136 | {}; | |
137 | ||
138 | /// INTERNAL ONLY | |
139 | template<typename OtherValue> | |
140 | struct lookup<Key, OtherValue> | |
141 | { | |
142 | typedef Value type; | |
143 | typedef typename add_reference<typename add_const<Value>::type>::type const_reference; | |
144 | }; | |
145 | #endif | |
146 | ||
147 | // For key-based lookups not intended to fail | |
148 | using Base::operator[]; | |
149 | const_reference operator[](Key) const | |
150 | { | |
151 | return this->value_; | |
152 | } | |
153 | ||
154 | // For key-based lookups that can fail, use the default if key not found. | |
155 | using Base::at; | |
156 | template<typename T> | |
157 | const_reference at(Key, T const &) const | |
158 | { | |
159 | return this->value_; | |
160 | } | |
161 | }; | |
162 | ||
163 | // define proto::data_type type and proto::data global | |
164 | BOOST_PROTO_DEFINE_ENV_VAR(data_type, data); | |
165 | } | |
166 | ||
167 | using envns_::data; | |
168 | ||
169 | namespace functional | |
170 | { | |
171 | //////////////////////////////////////////////////////////////////////////////////////// | |
172 | // as_env | |
173 | struct as_env | |
174 | { | |
175 | BOOST_PROTO_CALLABLE() | |
176 | BOOST_PROTO_POLY_FUNCTION() | |
177 | ||
178 | /// INTERNAL ONLY | |
179 | template<typename T, bool B = is_env<T>::value> | |
180 | struct impl | |
181 | { | |
182 | typedef env<data_type, typename detail::value_type<T>::type> result_type; | |
183 | ||
184 | result_type const operator()(detail::arg<T> t) const | |
185 | { | |
186 | return result_type(t()); | |
187 | } | |
188 | }; | |
189 | ||
190 | /// INTERNAL ONLY | |
191 | template<typename T> | |
192 | struct impl<T, true> | |
193 | { | |
194 | typedef T result_type; | |
195 | ||
196 | typename add_const<T>::type operator()(detail::arg<T> t) const | |
197 | { | |
198 | return t(); | |
199 | } | |
200 | }; | |
201 | ||
202 | template<typename Sig> | |
203 | struct result; | |
204 | ||
205 | template<typename This, typename T> | |
206 | struct result<This(T)> | |
207 | { | |
208 | typedef typename impl<typename detail::normalize_arg<T>::type>::result_type type; | |
209 | }; | |
210 | ||
211 | template<typename T> | |
212 | typename impl<typename detail::normalize_arg<T &>::type>::result_type const | |
213 | operator()(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) const | |
214 | { | |
215 | return impl<typename detail::normalize_arg<T &>::type>()( | |
216 | static_cast<typename detail::normalize_arg<T &>::reference>(t) | |
217 | ); | |
218 | } | |
219 | ||
220 | template<typename T> | |
221 | typename impl<typename detail::normalize_arg<T const &>::type>::result_type const | |
222 | operator()(T const &t) const | |
223 | { | |
224 | return impl<typename detail::normalize_arg<T const &>::type>()( | |
225 | static_cast<typename detail::normalize_arg<T const &>::reference>(t) | |
226 | ); | |
227 | } | |
228 | }; | |
229 | ||
230 | //////////////////////////////////////////////////////////////////////////////////////// | |
231 | // has_env_var | |
232 | template<typename Key> | |
233 | struct has_env_var | |
234 | : detail::poly_function<has_env_var<Key> > | |
235 | { | |
236 | BOOST_PROTO_CALLABLE() | |
237 | ||
238 | template<typename Env, bool IsEnv = is_env<Env>::value> | |
239 | struct impl | |
240 | { | |
241 | typedef | |
242 | mpl::not_< | |
243 | is_same< | |
244 | typename remove_reference<Env>::type::template lookup<Key>::type | |
245 | , key_not_found | |
246 | > | |
247 | > | |
248 | result_type; | |
249 | ||
250 | result_type operator()(detail::arg<Env>) const | |
251 | { | |
252 | return result_type(); | |
253 | } | |
254 | }; | |
255 | ||
256 | template<typename Env> | |
257 | struct impl<Env, false> | |
258 | { | |
259 | typedef mpl::false_ result_type; | |
260 | ||
261 | result_type operator()(detail::arg<Env>) const | |
262 | { | |
263 | return result_type(); | |
264 | } | |
265 | }; | |
266 | }; | |
267 | ||
268 | template<> | |
269 | struct has_env_var<data_type> | |
270 | : detail::poly_function<has_env_var<data_type> > | |
271 | { | |
272 | BOOST_PROTO_CALLABLE() | |
273 | ||
274 | template<typename Env, bool IsEnv = is_env<Env>::value> | |
275 | struct impl | |
276 | { | |
277 | typedef | |
278 | mpl::not_< | |
279 | is_same< | |
280 | typename remove_reference<Env>::type::template lookup<data_type>::type | |
281 | , key_not_found | |
282 | > | |
283 | > | |
284 | result_type; | |
285 | ||
286 | result_type operator()(detail::arg<Env>) const | |
287 | { | |
288 | return result_type(); | |
289 | } | |
290 | }; | |
291 | ||
292 | template<typename Env> | |
293 | struct impl<Env, false> | |
294 | { | |
295 | typedef mpl::true_ result_type; | |
296 | ||
297 | result_type operator()(detail::arg<Env>) const | |
298 | { | |
299 | return result_type(); | |
300 | } | |
301 | }; | |
302 | }; | |
303 | ||
304 | //////////////////////////////////////////////////////////////////////////////////////// | |
305 | // env_var | |
306 | template<typename Key> | |
307 | struct env_var | |
308 | : detail::poly_function<env_var<Key> > | |
309 | { | |
310 | BOOST_PROTO_CALLABLE() | |
311 | ||
312 | template<typename Env> | |
313 | struct impl | |
314 | { | |
315 | typedef | |
316 | typename remove_reference<Env>::type::template lookup<Key>::type | |
317 | result_type; | |
318 | ||
319 | result_type operator()(detail::arg<Env> e) const | |
320 | { | |
321 | return e()[Key()]; | |
322 | } | |
323 | }; | |
324 | }; | |
325 | ||
326 | template<> | |
327 | struct env_var<data_type> | |
328 | : detail::poly_function<env_var<data_type> > | |
329 | { | |
330 | BOOST_PROTO_CALLABLE() | |
331 | ||
332 | template<typename Env, bool B = is_env<Env>::value> | |
333 | struct impl | |
334 | { | |
335 | typedef Env result_type; | |
336 | ||
337 | result_type operator()(detail::arg<Env> e) const | |
338 | { | |
339 | return e(); | |
340 | } | |
341 | }; | |
342 | ||
343 | template<typename Env> | |
344 | struct impl<Env, true> | |
345 | { | |
346 | typedef | |
347 | typename remove_reference<Env>::type::template lookup<data_type>::type | |
348 | result_type; | |
349 | ||
350 | result_type operator()(detail::arg<Env> e) const | |
351 | { | |
352 | return e()[proto::data]; | |
353 | } | |
354 | }; | |
355 | }; | |
356 | } | |
357 | ||
358 | namespace result_of | |
359 | { | |
360 | template<typename T> | |
361 | struct as_env | |
362 | : BOOST_PROTO_RESULT_OF<functional::as_env(T)> | |
363 | {}; | |
364 | ||
365 | template<typename Env, typename Key> | |
366 | struct has_env_var | |
367 | : BOOST_PROTO_RESULT_OF<functional::has_env_var<Key>(Env)>::type | |
368 | {}; | |
369 | ||
370 | template<typename Env, typename Key> | |
371 | struct env_var | |
372 | : BOOST_PROTO_RESULT_OF<functional::env_var<Key>(Env)> | |
373 | {}; | |
374 | } | |
375 | ||
376 | //////////////////////////////////////////////////////////////////////////////////////////// | |
377 | // as_env | |
378 | template<typename T> | |
379 | typename proto::result_of::as_env<T &>::type const as_env(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) | |
380 | { | |
381 | return proto::functional::as_env()(t); | |
382 | } | |
383 | ||
384 | template<typename T> | |
385 | typename proto::result_of::as_env<T const &>::type const as_env(T const &t) | |
386 | { | |
387 | return proto::functional::as_env()(t); | |
388 | } | |
389 | ||
390 | //////////////////////////////////////////////////////////////////////////////////////////// | |
391 | // has_env_var | |
392 | template<typename Key, typename Env> | |
393 | typename proto::result_of::has_env_var<Env &, Key>::type has_env_var(Env &e BOOST_PROTO_DISABLE_IF_IS_CONST(Env)) | |
394 | { | |
395 | return functional::has_env_var<Key>()(e); | |
396 | } | |
397 | ||
398 | template<typename Key, typename Env> | |
399 | typename proto::result_of::has_env_var<Env const &, Key>::type has_env_var(Env const &e) | |
400 | { | |
401 | return functional::has_env_var<Key>()(e); | |
402 | } | |
403 | ||
404 | //////////////////////////////////////////////////////////////////////////////////////////// | |
405 | // env_var | |
406 | template<typename Key, typename Env> | |
407 | typename proto::result_of::env_var<Env &, Key>::type env_var(Env &e BOOST_PROTO_DISABLE_IF_IS_CONST(Env)) | |
408 | { | |
409 | return functional::env_var<Key>()(e); | |
410 | } | |
411 | ||
412 | template<typename Key, typename Env> | |
413 | typename proto::result_of::env_var<Env const &, Key>::type env_var(Env const &e) | |
414 | { | |
415 | return functional::env_var<Key>()(e); | |
416 | } | |
417 | ||
418 | namespace envns_ | |
419 | { | |
420 | //////////////////////////////////////////////////////////////////////////////////////// | |
421 | // env operator, | |
422 | template<typename T, typename T1, typename V1> | |
423 | inline typename disable_if_c< | |
424 | is_const<T>::value | |
425 | , env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T &>::type)> | |
426 | >::type const operator,(T &t, env<T1, V1> const &head) | |
427 | { | |
428 | return env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T &>::type)>( | |
429 | head[T1()] | |
430 | , proto::as_env(t) | |
431 | ); | |
432 | } | |
433 | ||
434 | template<typename T, typename T1, typename V1> | |
435 | inline env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T const &>::type)> const | |
436 | operator,(T const &t, env<T1, V1> const &head) | |
437 | { | |
438 | return env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T const &>::type)>( | |
439 | head[T1()] | |
440 | , proto::as_env(t) | |
441 | ); | |
442 | } | |
443 | } | |
444 | ||
445 | //////////////////////////////////////////////////////////////////////////////////////////// | |
446 | // _env_var | |
447 | template<typename Key> | |
448 | struct _env_var | |
449 | : proto::transform<_env_var<Key> > | |
450 | { | |
451 | template<typename Expr, typename State, typename Data> | |
452 | struct impl | |
453 | : transform_impl<Expr, State, Data> | |
454 | { | |
455 | typedef typename impl::data::template lookup<Key>::type result_type; | |
456 | BOOST_MPL_ASSERT_NOT((is_same<result_type, key_not_found>)); // lookup failed | |
457 | ||
458 | BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::data::template lookup<Key>::const_reference) | |
459 | operator ()( | |
460 | typename impl::expr_param | |
461 | , typename impl::state_param | |
462 | , typename impl::data_param d | |
463 | ) const | |
464 | { | |
465 | return d[Key()]; | |
466 | } | |
467 | }; | |
468 | }; | |
469 | ||
470 | struct _env | |
471 | : transform<_env> | |
472 | { | |
473 | template<typename Expr, typename State, typename Data> | |
474 | struct impl | |
475 | : transform_impl<Expr, State, Data> | |
476 | { | |
477 | typedef Data result_type; | |
478 | ||
479 | BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::data_param) | |
480 | operator ()( | |
481 | typename impl::expr_param | |
482 | , typename impl::state_param | |
483 | , typename impl::data_param d | |
484 | ) const | |
485 | { | |
486 | return d; | |
487 | } | |
488 | }; | |
489 | }; | |
490 | ||
491 | /// INTERNAL ONLY | |
492 | template<typename Key> | |
493 | struct is_callable<_env_var<Key> > | |
494 | : mpl::true_ | |
495 | {}; | |
496 | ||
497 | /// INTERNAL ONLY | |
498 | template<typename Key> | |
499 | struct is_callable<functional::has_env_var<Key> > | |
500 | : mpl::true_ | |
501 | {}; | |
502 | ||
503 | /// INTERNAL ONLY | |
504 | template<typename Key> | |
505 | struct is_callable<functional::env_var<Key> > | |
506 | : mpl::true_ | |
507 | {}; | |
508 | } | |
509 | } | |
510 | ||
511 | #ifdef _MSC_VER | |
512 | # pragma warning(pop) | |
513 | #endif | |
514 | ||
515 | #endif |