Imported Upstream version 1.51.0
[platform/upstream/boost.git] / boost / spirit / home / phoenix / core / value.hpp
1 /*=============================================================================
2     Copyright (c) 2001-2007 Joel de Guzman
3
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 #ifndef PHOENIX_CORE_VALUE_HPP
8 #define PHOENIX_CORE_VALUE_HPP
9
10 #include <boost/spirit/home/phoenix/core/actor.hpp>
11 #include <boost/spirit/home/phoenix/core/as_actor.hpp>
12 #include <boost/static_assert.hpp>
13
14 #include <boost/type_traits/is_reference.hpp>
15 #include <boost/type_traits/remove_reference.hpp>
16 #include <boost/type_traits/is_pointer.hpp>
17 #include <boost/type_traits/add_const.hpp>
18 #include <boost/type_traits/add_reference.hpp>
19 #include <boost/type_traits/remove_pointer.hpp>
20 #include <boost/type_traits/is_function.hpp>
21
22 #include <boost/mpl/bool.hpp>
23 #include <boost/mpl/eval_if.hpp>
24 #include <boost/mpl/identity.hpp>
25
26 namespace boost { namespace phoenix
27 {
28     namespace meta
29     {
30         template<typename T>
31         struct const_ref
32             : add_reference<typename add_const<T>::type>
33         {};
34
35         template<typename T>
36         struct argument_type
37             : mpl::eval_if<
38             is_function<typename remove_pointer<T>::type>,
39             mpl::identity<T>,
40             const_ref<T> >
41         {
42             typedef T type;
43         };
44     }
45
46     template <typename T>
47     struct value
48     {
49         BOOST_STATIC_ASSERT(
50             mpl::not_<is_reference<T> >::value != 0);
51
52         typedef mpl::false_ no_nullary;
53
54         template <typename Env>
55         struct result
56         {
57             typedef T type;
58         };
59
60         value()
61             : val() {}
62
63         value(T const& arg)
64             : val(arg) {}
65
66         template <typename Env>
67         T const&
68         eval(Env const&) const
69         {
70             return val;
71         }
72
73         T val;
74     };
75
76     template <typename Actor>
77     struct actor_value
78     {
79         typedef typename Actor::no_nullary no_nullary;
80
81         template <typename Env>
82         struct result
83         {
84             typedef typename
85                 remove_reference<
86                     typename eval_result<Actor, Env>::type
87                 >::type
88             type;
89         };
90
91         actor_value(Actor const& actor)
92             : actor(actor) {}
93
94         template <typename Env>
95         typename result<Env>::type
96         eval(Env const& env) const
97         {
98             return actor.eval(env);
99         }
100
101         Actor actor;
102     };
103
104     template <typename T>
105     inline typename as_actor<T>::type
106     val(T const& v)
107     {
108         return as_actor<T>::convert(v);
109     }
110
111     template <typename Derived>
112     inline actor<actor_value<Derived> >
113     val(actor<Derived> const& actor)
114     {
115         return actor_value<Derived>(actor);
116     }
117
118     template <typename T>
119     struct as_actor_base
120     {
121         typedef value<T> type;
122
123         static value<T>
124         convert(typename meta::argument_type<T>::type x)
125         {
126             return value<T>(x);
127         }
128     };
129
130     // Sometimes it is necessary to auto-convert references to
131     // a value<T>. This happens when we are re-currying. This
132     // cannot happen through the standard public actor interfaces.
133     template <typename T>
134     struct as_actor_base<T&>
135     {
136         typedef value<T> type;
137
138         static value<T>
139         convert(T& x)
140         {
141             return value<T>(x);
142         }
143     };
144
145     template <typename T, int N>
146     struct as_actor_base<T[N]>
147     {
148         typedef value<T const*> type;
149
150         static value<T const*>
151         convert(T const x[N])
152         {
153             return value<T const*>(x);
154         }
155     };
156 }}
157
158 #endif