| /////////////////////////////////////////////////////////////////////////////// |
| // 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 |