/////////////////////////////////////////////////////////////////////////////// // 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 struct value_type { typedef typename remove_const::type value; typedef typename add_reference::type reference; typedef typename mpl::if_c::value, reference, value>::type type; }; template struct value_type { typedef T &value; typedef T &reference; typedef T &type; }; } #define BOOST_PROTO_DEFINE_ENV_VAR(TAG, NAME) \ struct TAG \ { \ template \ boost::proto::env const \ operator =(boost::reference_wrapper &value) const \ { \ return boost::proto::env(value.get()); \ } \ template \ boost::proto::env const \ operator =(boost::reference_wrapper const &value) const \ { \ return boost::proto::env(value.get()); \ } \ template \ typename boost::disable_if_c< \ boost::is_const::value \ , boost::proto::env::type> \ >::type const operator =(Value &value) const \ { \ return boost::proto::env::type>(value); \ } \ template \ boost::proto::env::type> const \ operator =(Value const &value) const \ { \ return boost::proto::env::type>(value); \ } \ }; \ \ TAG const NAME = {} \ /**/ namespace envns_ { //////////////////////////////////////////////////////////////////////////////////////////// // env // A transform env is a slot-based storage mechanism, accessible by tag. template struct env : private Base { private: Value value_; public: typedef Value value_type; typedef typename add_reference::type reference; typedef typename add_reference::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::type>::type const_reference; }; template struct lookup : mpl::if_c< is_same::value , found , typename Base::template lookup >::type {}; #else /// INTERNAL ONLY template struct lookup : Base::template lookup {}; /// INTERNAL ONLY template struct lookup { typedef Value type; typedef typename add_reference::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 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::value> struct impl { typedef env::type> result_type; result_type const operator()(detail::arg t) const { return result_type(t()); } }; /// INTERNAL ONLY template struct impl { typedef T result_type; typename add_const::type operator()(detail::arg t) const { return t(); } }; template struct result; template struct result { typedef typename impl::type>::result_type type; }; template typename impl::type>::result_type const operator()(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) const { return impl::type>()( static_cast::reference>(t) ); } template typename impl::type>::result_type const operator()(T const &t) const { return impl::type>()( static_cast::reference>(t) ); } }; //////////////////////////////////////////////////////////////////////////////////////// // has_env_var template struct has_env_var : detail::poly_function > { BOOST_PROTO_CALLABLE() template::value> struct impl { typedef mpl::not_< is_same< typename remove_reference::type::template lookup::type , key_not_found > > result_type; result_type operator()(detail::arg) const { return result_type(); } }; template struct impl { typedef mpl::false_ result_type; result_type operator()(detail::arg) const { return result_type(); } }; }; template<> struct has_env_var : detail::poly_function > { BOOST_PROTO_CALLABLE() template::value> struct impl { typedef mpl::not_< is_same< typename remove_reference::type::template lookup::type , key_not_found > > result_type; result_type operator()(detail::arg) const { return result_type(); } }; template struct impl { typedef mpl::true_ result_type; result_type operator()(detail::arg) const { return result_type(); } }; }; //////////////////////////////////////////////////////////////////////////////////////// // env_var template struct env_var : detail::poly_function > { BOOST_PROTO_CALLABLE() template struct impl { typedef typename remove_reference::type::template lookup::type result_type; result_type operator()(detail::arg e) const { return e()[Key()]; } }; }; template<> struct env_var : detail::poly_function > { BOOST_PROTO_CALLABLE() template::value> struct impl { typedef Env result_type; result_type operator()(detail::arg e) const { return e(); } }; template struct impl { typedef typename remove_reference::type::template lookup::type result_type; result_type operator()(detail::arg e) const { return e()[proto::data]; } }; }; } namespace result_of { template struct as_env : BOOST_PROTO_RESULT_OF {}; template struct has_env_var : BOOST_PROTO_RESULT_OF(Env)>::type {}; template struct env_var : BOOST_PROTO_RESULT_OF(Env)> {}; } //////////////////////////////////////////////////////////////////////////////////////////// // as_env template typename proto::result_of::as_env::type const as_env(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) { return proto::functional::as_env()(t); } template typename proto::result_of::as_env::type const as_env(T const &t) { return proto::functional::as_env()(t); } //////////////////////////////////////////////////////////////////////////////////////////// // has_env_var template typename proto::result_of::has_env_var::type has_env_var(Env &e BOOST_PROTO_DISABLE_IF_IS_CONST(Env)) { return functional::has_env_var()(e); } template typename proto::result_of::has_env_var::type has_env_var(Env const &e) { return functional::has_env_var()(e); } //////////////////////////////////////////////////////////////////////////////////////////// // env_var template typename proto::result_of::env_var::type env_var(Env &e BOOST_PROTO_DISABLE_IF_IS_CONST(Env)) { return functional::env_var()(e); } template typename proto::result_of::env_var::type env_var(Env const &e) { return functional::env_var()(e); } namespace envns_ { //////////////////////////////////////////////////////////////////////////////////////// // env operator, template inline typename disable_if_c< is_const::value , env::type)> >::type const operator,(T &t, env const &head) { return env::type)>( head[T1()] , proto::as_env(t) ); } template inline env::type)> const operator,(T const &t, env const &head) { return env::type)>( head[T1()] , proto::as_env(t) ); } } //////////////////////////////////////////////////////////////////////////////////////////// // _env_var template struct _env_var : proto::transform<_env_var > { template struct impl : transform_impl { typedef typename impl::data::template lookup::type result_type; BOOST_MPL_ASSERT_NOT((is_same)); // lookup failed BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::data::template lookup::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 struct impl : transform_impl { 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 struct is_callable<_env_var > : mpl::true_ {}; /// INTERNAL ONLY template struct is_callable > : mpl::true_ {}; /// INTERNAL ONLY template struct is_callable > : mpl::true_ {}; } } #ifdef _MSC_VER # pragma warning(pop) #endif #endif