516 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			516 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | /////////////////////////////////////////////////////////////////////////////// | ||
|  | // env.hpp | ||
|  | // Helpers for producing and consuming tranform env variables. | ||
|  | // | ||
|  | //  Copyright 2012 Eric Niebler. Distributed under the Boost | ||
|  | //  Software License, Version 1.0. (See accompanying file | ||
|  | //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|  | 
 | ||
|  | #ifndef BOOST_PROTO_TRANSFORM_ENV_HPP_EAN_18_07_2012 | ||
|  | #define BOOST_PROTO_TRANSFORM_ENV_HPP_EAN_18_07_2012 | ||
|  | 
 | ||
|  | #include <boost/config.hpp> | ||
|  | #include <boost/detail/workaround.hpp> | ||
|  | #include <boost/ref.hpp> | ||
|  | #include <boost/utility/enable_if.hpp> | ||
|  | #include <boost/type_traits/is_const.hpp> | ||
|  | #include <boost/type_traits/is_same.hpp> | ||
|  | #include <boost/type_traits/add_const.hpp> | ||
|  | #include <boost/type_traits/add_reference.hpp> | ||
|  | #include <boost/type_traits/remove_const.hpp> | ||
|  | #include <boost/mpl/assert.hpp> | ||
|  | #include <boost/mpl/bool.hpp> | ||
|  | #include <boost/mpl/if.hpp> | ||
|  | #include <boost/mpl/not.hpp> | ||
|  | #include <boost/proto/proto_fwd.hpp> | ||
|  | #include <boost/proto/transform/impl.hpp> | ||
|  | #include <boost/proto/detail/poly_function.hpp> | ||
|  | #include <boost/proto/detail/is_noncopyable.hpp> | ||
|  | 
 | ||
|  | #ifdef _MSC_VER | ||
|  | # pragma warning(push) | ||
|  | # pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored | ||
|  | #endif | ||
|  | 
 | ||
|  | namespace boost | ||
|  | { | ||
|  |     namespace proto | ||
|  |     { | ||
|  |         namespace detail | ||
|  |         { | ||
|  |             template<typename T> | ||
|  |             struct value_type | ||
|  |             { | ||
|  |                 typedef typename remove_const<T>::type value; | ||
|  |                 typedef typename add_reference<T>::type reference; | ||
|  |                 typedef typename mpl::if_c<is_noncopyable<T>::value, reference, value>::type type; | ||
|  |             }; | ||
|  | 
 | ||
|  |             template<typename T> | ||
|  |             struct value_type<T &> | ||
|  |             { | ||
|  |                 typedef T &value; | ||
|  |                 typedef T &reference; | ||
|  |                 typedef T &type; | ||
|  |             }; | ||
|  |         } | ||
|  | 
 | ||
|  |     #define BOOST_PROTO_DEFINE_ENV_VAR(TAG, NAME)                                                   \ | ||
|  |         struct TAG                                                                                  \ | ||
|  |         {                                                                                           \ | ||
|  |             template<typename Value>                                                                \ | ||
|  |             boost::proto::env<TAG, Value &> const                                                   \ | ||
|  |                 operator =(boost::reference_wrapper<Value> &value) const                            \ | ||
|  |             {                                                                                       \ | ||
|  |                 return boost::proto::env<TAG, Value &>(value.get());                                \ | ||
|  |             }                                                                                       \ | ||
|  |             template<typename Value>                                                                \ | ||
|  |             boost::proto::env<TAG, Value &> const                                                   \ | ||
|  |                 operator =(boost::reference_wrapper<Value> const &value) const                      \ | ||
|  |             {                                                                                       \ | ||
|  |                 return boost::proto::env<TAG, Value &>(value.get());                                \ | ||
|  |             }                                                                                       \ | ||
|  |             template<typename Value>                                                                \ | ||
|  |             typename boost::disable_if_c<                                                           \ | ||
|  |                 boost::is_const<Value>::value                                                       \ | ||
|  |               , boost::proto::env<TAG, typename boost::proto::detail::value_type<Value>::type>      \ | ||
|  |             >::type const operator =(Value &value) const                                            \ | ||
|  |             {                                                                                       \ | ||
|  |                 return boost::proto::env<TAG, typename boost::proto::detail::value_type<Value>::type>(value); \ | ||
|  |             }                                                                                       \ | ||
|  |             template<typename Value>                                                                \ | ||
|  |             boost::proto::env<TAG, typename boost::proto::detail::value_type<Value const>::type> const \ | ||
|  |                 operator =(Value const &value) const                                                \ | ||
|  |             {                                                                                       \ | ||
|  |                 return boost::proto::env<TAG, typename boost::proto::detail::value_type<Value const>::type>(value); \ | ||
|  |             }                                                                                       \ | ||
|  |         };                                                                                          \ | ||
|  |                                                                                                     \ | ||
|  |         TAG const NAME = {}                                                                         \ | ||
|  |         /**/ | ||
|  | 
 | ||
|  |         namespace envns_ | ||
|  |         { | ||
|  |             //////////////////////////////////////////////////////////////////////////////////////////// | ||
|  |             // env | ||
|  |             // A transform env is a slot-based storage mechanism, accessible by tag. | ||
|  |             template<typename Key, typename Value, typename Base /*= empty_env*/> | ||
|  |             struct env | ||
|  |               : private Base | ||
|  |             { | ||
|  |             private: | ||
|  |                 Value value_; | ||
|  | 
 | ||
|  |             public: | ||
|  |                 typedef Value value_type; | ||
|  |                 typedef typename add_reference<Value>::type reference; | ||
|  |                 typedef typename add_reference<typename add_const<Value>::type>::type const_reference; | ||
|  |                 typedef void proto_environment_; ///< INTERNAL ONLY | ||
|  | 
 | ||
|  |                 explicit env(const_reference value, Base const &base = Base()) | ||
|  |                   : Base(base) | ||
|  |                   , value_(value) | ||
|  |                 {} | ||
|  | 
 | ||
|  |                 #if BOOST_WORKAROUND(__GNUC__, == 3) || (BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ <= 2) | ||
|  |                 /// INTERNAL ONLY | ||
|  |                 struct found | ||
|  |                 { | ||
|  |                     typedef Value type; | ||
|  |                     typedef typename add_reference<typename add_const<Value>::type>::type const_reference; | ||
|  |                 }; | ||
|  | 
 | ||
|  |                 template<typename OtherKey, typename OtherValue = key_not_found> | ||
|  |                 struct lookup | ||
|  |                   : mpl::if_c< | ||
|  |                         is_same<OtherKey, Key>::value | ||
|  |                       , found | ||
|  |                       , typename Base::template lookup<OtherKey, OtherValue> | ||
|  |                     >::type | ||
|  |                 {}; | ||
|  |                 #else | ||
|  |                 /// INTERNAL ONLY | ||
|  |                 template<typename OtherKey, typename OtherValue = key_not_found> | ||
|  |                 struct lookup | ||
|  |                   : Base::template lookup<OtherKey, OtherValue> | ||
|  |                 {}; | ||
|  | 
 | ||
|  |                 /// INTERNAL ONLY | ||
|  |                 template<typename OtherValue> | ||
|  |                 struct lookup<Key, OtherValue> | ||
|  |                 { | ||
|  |                     typedef Value type; | ||
|  |                     typedef typename add_reference<typename add_const<Value>::type>::type const_reference; | ||
|  |                 }; | ||
|  |                 #endif | ||
|  | 
 | ||
|  |                 // For key-based lookups not intended to fail | ||
|  |                 using Base::operator[]; | ||
|  |                 const_reference operator[](Key) const | ||
|  |                 { | ||
|  |                     return this->value_; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 // For key-based lookups that can fail, use the default if key not found. | ||
|  |                 using Base::at; | ||
|  |                 template<typename T> | ||
|  |                 const_reference at(Key, T const &) const | ||
|  |                 { | ||
|  |                     return this->value_; | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  |             // define proto::data_type type and proto::data global | ||
|  |             BOOST_PROTO_DEFINE_ENV_VAR(data_type, data); | ||
|  |         } | ||
|  | 
 | ||
|  |         using envns_::data; | ||
|  | 
 | ||
|  |         namespace functional | ||
|  |         { | ||
|  |             //////////////////////////////////////////////////////////////////////////////////////// | ||
|  |             // as_env | ||
|  |             struct as_env | ||
|  |             { | ||
|  |                 BOOST_PROTO_CALLABLE() | ||
|  |                 BOOST_PROTO_POLY_FUNCTION() | ||
|  | 
 | ||
|  |                 /// INTERNAL ONLY | ||
|  |                 template<typename T, bool B = is_env<T>::value> | ||
|  |                 struct impl | ||
|  |                 { | ||
|  |                     typedef env<data_type, typename detail::value_type<T>::type> result_type; | ||
|  | 
 | ||
|  |                     result_type const operator()(detail::arg<T> t) const | ||
|  |                     { | ||
|  |                         return result_type(t()); | ||
|  |                     } | ||
|  |                 }; | ||
|  | 
 | ||
|  |                 /// INTERNAL ONLY | ||
|  |                 template<typename T> | ||
|  |                 struct impl<T, true> | ||
|  |                 { | ||
|  |                     typedef T result_type; | ||
|  | 
 | ||
|  |                     typename add_const<T>::type operator()(detail::arg<T> t) const | ||
|  |                     { | ||
|  |                         return t(); | ||
|  |                     } | ||
|  |                 }; | ||
|  | 
 | ||
|  |                 template<typename Sig> | ||
|  |                 struct result; | ||
|  | 
 | ||
|  |                 template<typename This, typename T> | ||
|  |                 struct result<This(T)> | ||
|  |                 { | ||
|  |                     typedef typename impl<typename detail::normalize_arg<T>::type>::result_type type; | ||
|  |                 }; | ||
|  | 
 | ||
|  |                 template<typename T> | ||
|  |                 typename impl<typename detail::normalize_arg<T &>::type>::result_type const | ||
|  |                     operator()(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) const | ||
|  |                 { | ||
|  |                     return impl<typename detail::normalize_arg<T &>::type>()( | ||
|  |                         static_cast<typename detail::normalize_arg<T &>::reference>(t) | ||
|  |                     ); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 template<typename T> | ||
|  |                 typename impl<typename detail::normalize_arg<T const &>::type>::result_type const | ||
|  |                     operator()(T const &t) const | ||
|  |                 { | ||
|  |                     return impl<typename detail::normalize_arg<T const &>::type>()( | ||
|  |                         static_cast<typename detail::normalize_arg<T const &>::reference>(t) | ||
|  |                     ); | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  |             //////////////////////////////////////////////////////////////////////////////////////// | ||
|  |             // has_env_var | ||
|  |             template<typename Key> | ||
|  |             struct has_env_var | ||
|  |               : detail::poly_function<has_env_var<Key> > | ||
|  |             { | ||
|  |                 BOOST_PROTO_CALLABLE() | ||
|  | 
 | ||
|  |                 template<typename Env, bool IsEnv = is_env<Env>::value> | ||
|  |                 struct impl | ||
|  |                 { | ||
|  |                     typedef | ||
|  |                         mpl::not_< | ||
|  |                             is_same< | ||
|  |                                 typename remove_reference<Env>::type::template lookup<Key>::type | ||
|  |                               , key_not_found | ||
|  |                             > | ||
|  |                         > | ||
|  |                     result_type; | ||
|  | 
 | ||
|  |                     result_type operator()(detail::arg<Env>) const | ||
|  |                     { | ||
|  |                         return result_type(); | ||
|  |                     } | ||
|  |                 }; | ||
|  | 
 | ||
|  |                 template<typename Env> | ||
|  |                 struct impl<Env, false> | ||
|  |                 { | ||
|  |                     typedef mpl::false_ result_type; | ||
|  | 
 | ||
|  |                     result_type operator()(detail::arg<Env>) const | ||
|  |                     { | ||
|  |                         return result_type(); | ||
|  |                     } | ||
|  |                 }; | ||
|  |             }; | ||
|  | 
 | ||
|  |             template<> | ||
|  |             struct has_env_var<data_type> | ||
|  |               : detail::poly_function<has_env_var<data_type> > | ||
|  |             { | ||
|  |                 BOOST_PROTO_CALLABLE() | ||
|  | 
 | ||
|  |                 template<typename Env, bool IsEnv = is_env<Env>::value> | ||
|  |                 struct impl | ||
|  |                 { | ||
|  |                     typedef | ||
|  |                         mpl::not_< | ||
|  |                             is_same< | ||
|  |                                 typename remove_reference<Env>::type::template lookup<data_type>::type | ||
|  |                               , key_not_found | ||
|  |                             > | ||
|  |                         > | ||
|  |                     result_type; | ||
|  | 
 | ||
|  |                     result_type operator()(detail::arg<Env>) const | ||
|  |                     { | ||
|  |                         return result_type(); | ||
|  |                     } | ||
|  |                 }; | ||
|  | 
 | ||
|  |                 template<typename Env> | ||
|  |                 struct impl<Env, false> | ||
|  |                 { | ||
|  |                     typedef mpl::true_ result_type; | ||
|  | 
 | ||
|  |                     result_type operator()(detail::arg<Env>) const | ||
|  |                     { | ||
|  |                         return result_type(); | ||
|  |                     } | ||
|  |                 }; | ||
|  |             }; | ||
|  | 
 | ||
|  |             //////////////////////////////////////////////////////////////////////////////////////// | ||
|  |             // env_var | ||
|  |             template<typename Key> | ||
|  |             struct env_var | ||
|  |               : detail::poly_function<env_var<Key> > | ||
|  |             { | ||
|  |                 BOOST_PROTO_CALLABLE() | ||
|  | 
 | ||
|  |                 template<typename Env> | ||
|  |                 struct impl | ||
|  |                 { | ||
|  |                     typedef | ||
|  |                         typename remove_reference<Env>::type::template lookup<Key>::type | ||
|  |                     result_type; | ||
|  | 
 | ||
|  |                     result_type operator()(detail::arg<Env> e) const | ||
|  |                     { | ||
|  |                         return e()[Key()]; | ||
|  |                     } | ||
|  |                 }; | ||
|  |             }; | ||
|  | 
 | ||
|  |             template<> | ||
|  |             struct env_var<data_type> | ||
|  |               : detail::poly_function<env_var<data_type> > | ||
|  |             { | ||
|  |                 BOOST_PROTO_CALLABLE() | ||
|  | 
 | ||
|  |                 template<typename Env, bool B = is_env<Env>::value> | ||
|  |                 struct impl | ||
|  |                 { | ||
|  |                     typedef Env result_type; | ||
|  | 
 | ||
|  |                     result_type operator()(detail::arg<Env> e) const | ||
|  |                     { | ||
|  |                         return e(); | ||
|  |                     } | ||
|  |                 }; | ||
|  | 
 | ||
|  |                 template<typename Env> | ||
|  |                 struct impl<Env, true> | ||
|  |                 { | ||
|  |                     typedef | ||
|  |                         typename remove_reference<Env>::type::template lookup<data_type>::type | ||
|  |                     result_type; | ||
|  | 
 | ||
|  |                     result_type operator()(detail::arg<Env> e) const | ||
|  |                     { | ||
|  |                         return e()[proto::data]; | ||
|  |                     } | ||
|  |                 }; | ||
|  |             }; | ||
|  |         } | ||
|  | 
 | ||
|  |         namespace result_of | ||
|  |         { | ||
|  |             template<typename T> | ||
|  |             struct as_env | ||
|  |               : BOOST_PROTO_RESULT_OF<functional::as_env(T)> | ||
|  |             {}; | ||
|  | 
 | ||
|  |             template<typename Env, typename Key> | ||
|  |             struct has_env_var | ||
|  |               : BOOST_PROTO_RESULT_OF<functional::has_env_var<Key>(Env)>::type | ||
|  |             {}; | ||
|  | 
 | ||
|  |             template<typename Env, typename Key> | ||
|  |             struct env_var | ||
|  |               : BOOST_PROTO_RESULT_OF<functional::env_var<Key>(Env)> | ||
|  |             {}; | ||
|  |         } | ||
|  | 
 | ||
|  |         //////////////////////////////////////////////////////////////////////////////////////////// | ||
|  |         // as_env | ||
|  |         template<typename T> | ||
|  |         typename proto::result_of::as_env<T &>::type const as_env(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) | ||
|  |         { | ||
|  |             return proto::functional::as_env()(t); | ||
|  |         } | ||
|  | 
 | ||
|  |         template<typename T> | ||
|  |         typename proto::result_of::as_env<T const &>::type const as_env(T const &t) | ||
|  |         { | ||
|  |             return proto::functional::as_env()(t); | ||
|  |         } | ||
|  | 
 | ||
|  |         //////////////////////////////////////////////////////////////////////////////////////////// | ||
|  |         // has_env_var | ||
|  |         template<typename Key, typename Env> | ||
|  |         typename proto::result_of::has_env_var<Env &, Key>::type has_env_var(Env &e BOOST_PROTO_DISABLE_IF_IS_CONST(Env)) | ||
|  |         { | ||
|  |             return functional::has_env_var<Key>()(e); | ||
|  |         } | ||
|  | 
 | ||
|  |         template<typename Key, typename Env> | ||
|  |         typename proto::result_of::has_env_var<Env const &, Key>::type has_env_var(Env const &e) | ||
|  |         { | ||
|  |             return functional::has_env_var<Key>()(e); | ||
|  |         } | ||
|  | 
 | ||
|  |         //////////////////////////////////////////////////////////////////////////////////////////// | ||
|  |         // env_var | ||
|  |         template<typename Key, typename Env> | ||
|  |         typename proto::result_of::env_var<Env &, Key>::type env_var(Env &e BOOST_PROTO_DISABLE_IF_IS_CONST(Env)) | ||
|  |         { | ||
|  |             return functional::env_var<Key>()(e); | ||
|  |         } | ||
|  | 
 | ||
|  |         template<typename Key, typename Env> | ||
|  |         typename proto::result_of::env_var<Env const &, Key>::type env_var(Env const &e) | ||
|  |         { | ||
|  |             return functional::env_var<Key>()(e); | ||
|  |         } | ||
|  | 
 | ||
|  |         namespace envns_ | ||
|  |         { | ||
|  |             //////////////////////////////////////////////////////////////////////////////////////// | ||
|  |             // env operator, | ||
|  |             template<typename T, typename T1, typename V1> | ||
|  |             inline typename disable_if_c< | ||
|  |                 is_const<T>::value | ||
|  |               , env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T &>::type)> | ||
|  |             >::type const operator,(T &t, env<T1, V1> const &head) | ||
|  |             { | ||
|  |                 return env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T &>::type)>( | ||
|  |                     head[T1()] | ||
|  |                   , proto::as_env(t) | ||
|  |                 ); | ||
|  |             } | ||
|  | 
 | ||
|  |             template<typename T, typename T1, typename V1> | ||
|  |             inline env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T const &>::type)> const | ||
|  |                 operator,(T const &t, env<T1, V1> const &head) | ||
|  |             { | ||
|  |                 return env<T1, V1, BOOST_PROTO_UNCVREF(typename result_of::as_env<T const &>::type)>( | ||
|  |                     head[T1()] | ||
|  |                   , proto::as_env(t) | ||
|  |                 ); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         //////////////////////////////////////////////////////////////////////////////////////////// | ||
|  |         // _env_var | ||
|  |         template<typename Key> | ||
|  |         struct _env_var | ||
|  |           : proto::transform<_env_var<Key> > | ||
|  |         { | ||
|  |             template<typename Expr, typename State, typename Data> | ||
|  |             struct impl | ||
|  |               : transform_impl<Expr, State, Data> | ||
|  |             { | ||
|  |                 typedef typename impl::data::template lookup<Key>::type result_type; | ||
|  |                 BOOST_MPL_ASSERT_NOT((is_same<result_type, key_not_found>)); // lookup failed | ||
|  | 
 | ||
|  |                 BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::data::template lookup<Key>::const_reference) | ||
|  |                 operator ()( | ||
|  |                     typename impl::expr_param | ||
|  |                   , typename impl::state_param | ||
|  |                   , typename impl::data_param d | ||
|  |                 ) const | ||
|  |                 { | ||
|  |                     return d[Key()]; | ||
|  |                 } | ||
|  |             }; | ||
|  |         }; | ||
|  | 
 | ||
|  |         struct _env | ||
|  |           : transform<_env> | ||
|  |         { | ||
|  |             template<typename Expr, typename State, typename Data> | ||
|  |             struct impl | ||
|  |               : transform_impl<Expr, State, Data> | ||
|  |             { | ||
|  |                 typedef Data result_type; | ||
|  | 
 | ||
|  |                 BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::data_param) | ||
|  |                 operator ()( | ||
|  |                     typename impl::expr_param | ||
|  |                   , typename impl::state_param | ||
|  |                   , typename impl::data_param d | ||
|  |                 ) const | ||
|  |                 { | ||
|  |                     return d; | ||
|  |                 } | ||
|  |             }; | ||
|  |         }; | ||
|  | 
 | ||
|  |         /// INTERNAL ONLY | ||
|  |         template<typename Key> | ||
|  |         struct is_callable<_env_var<Key> > | ||
|  |           : mpl::true_ | ||
|  |         {}; | ||
|  | 
 | ||
|  |         /// INTERNAL ONLY | ||
|  |         template<typename Key> | ||
|  |         struct is_callable<functional::has_env_var<Key> > | ||
|  |           : mpl::true_ | ||
|  |         {}; | ||
|  | 
 | ||
|  |         /// INTERNAL ONLY | ||
|  |         template<typename Key> | ||
|  |         struct is_callable<functional::env_var<Key> > | ||
|  |           : mpl::true_ | ||
|  |         {}; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef _MSC_VER | ||
|  | # pragma warning(pop) | ||
|  | #endif | ||
|  | 
 | ||
|  | #endif |