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