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