1 /*============================================================================== 2 Copyright (c) 2001-2010 Joel de Guzman 3 Copyright (c) 2010 Thomas Heller 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #ifndef BOOST_PHOENIX_CORE_REFERENCE_HPP 9 #define BOOST_PHOENIX_CORE_REFERENCE_HPP 10 11 #include <boost/phoenix/core/limits.hpp> 12 #include <boost/ref.hpp> 13 #include <boost/phoenix/core/actor.hpp> 14 #include <boost/phoenix/core/terminal.hpp> 15 #include <boost/utility/result_of.hpp> 16 17 namespace boost { namespace phoenix 18 { 19 ///////////////////////////////////////////////////////////////////////////// 20 // 21 // reference 22 // 23 // function for evaluating references, e.g. ref(123) 24 // 25 ///////////////////////////////////////////////////////////////////////////// 26 namespace expression 27 { 28 template <typename T> 29 struct reference 30 : expression::terminal<reference_wrapper<T> > 31 { 32 typedef 33 typename expression::terminal<reference_wrapper<T> >::type 34 type; 35 makeboost::phoenix::expression::reference36 static const type make(T & t) 37 { 38 typename reference<T>::type const e = {{boost::ref(t)}}; 39 return e; 40 } 41 }; 42 43 template <typename T> 44 struct reference<T const> 45 : expression::terminal<reference_wrapper<T const> > 46 { 47 typedef 48 typename expression::terminal<reference_wrapper<T const> >::type 49 type; 50 makeboost::phoenix::expression::reference51 static const type make(T const & t) 52 { 53 typename reference<T const>::type const e = {{boost::cref(t)}}; 54 return e; 55 } 56 }; 57 } 58 59 namespace rule 60 { 61 struct reference 62 : expression::reference<proto::_> 63 {}; 64 } 65 66 template <typename T> 67 inline 68 typename expression::reference<T>::type const ref(T & t)69 ref(T & t) 70 { 71 return expression::reference<T>::make(t); 72 } 73 74 template <typename T> 75 inline 76 typename expression::reference<T const>::type const cref(T const & t)77 cref(T const & t) 78 { 79 return expression::reference<T const>::make(t); 80 } 81 82 // Call out boost::reference_wrapper for special handling 83 template<typename T> 84 struct is_custom_terminal<boost::reference_wrapper<T> > 85 : mpl::true_ 86 {}; 87 88 // Special handling for boost::reference_wrapper 89 template<typename T> 90 struct custom_terminal<boost::reference_wrapper<T> > 91 { 92 typedef T &result_type; 93 94 template <typename Context> operator ()boost::phoenix::custom_terminal95 T &operator()(boost::reference_wrapper<T> r, Context &) const 96 { 97 return r; 98 } 99 }; 100 101 template<typename Expr> 102 struct custom_terminal<boost::reference_wrapper<actor<Expr> > > 103 { 104 template <typename Sig> 105 struct result; 106 107 template <typename This, typename Context> 108 struct result<This(boost::reference_wrapper<actor<Expr> > const &, Context)> 109 : boost::result_of<evaluator(actor<Expr> &, Context)> 110 {}; 111 112 template <typename This, typename Context> 113 struct result<This(boost::reference_wrapper<actor<Expr> > &, Context)> 114 : boost::result_of<evaluator(actor<Expr> &, Context)> 115 {}; 116 117 template <typename Context> 118 typename boost::result_of<evaluator(actor<Expr> &, Context const &)>::type operator ()boost::phoenix::custom_terminal119 operator()(boost::reference_wrapper<actor<Expr> > & r, Context const & ctx) const 120 { 121 return boost::phoenix::eval(r, ctx); 122 } 123 }; 124 125 template<typename Expr> 126 struct custom_terminal<boost::reference_wrapper<actor<Expr> const> > 127 { 128 template <typename Sig> 129 struct result; 130 131 template <typename This, typename Context> 132 struct result<This(boost::reference_wrapper<actor<Expr> const> const &, Context)> 133 : boost::result_of<evaluator(actor<Expr> const&, Context)> 134 {}; 135 136 template <typename This, typename Context> 137 struct result<This(boost::reference_wrapper<actor<Expr> const> &, Context)> 138 : boost::result_of<evaluator(actor<Expr> const&, Context)> 139 {}; 140 141 template <typename Context> 142 typename boost::result_of<evaluator(actor<Expr> const&, Context const &)>::type operator ()boost::phoenix::custom_terminal143 operator()(boost::reference_wrapper<actor<Expr> const> const & r, Context & ctx) const 144 { 145 return boost::phoenix::eval(unwrap_ref(r), ctx); 146 } 147 }; 148 }} 149 150 #endif 151