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