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
 | 
