summaryrefslogtreecommitdiffstats
blob: a275a7d22137f87e2c6d1d9d57be63cb14cb3ac6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*=============================================================================
    Copyright (c) 2001-2007 Joel de Guzman

    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 PHOENIX_CORE_VALUE_HPP
#define PHOENIX_CORE_VALUE_HPP

#include <boost/spirit/home/phoenix/core/actor.hpp>
#include <boost/spirit/home/phoenix/core/as_actor.hpp>
#include <boost/static_assert.hpp>

#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/is_function.hpp>

#include <boost/mpl/bool.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>

namespace boost { namespace phoenix
{
    namespace meta
    {
        template<typename T>
        struct const_ref
            : add_reference<typename add_const<T>::type>
        {};

        template<typename T>
        struct argument_type
            : mpl::eval_if<
            is_function<typename remove_pointer<T>::type>,
            mpl::identity<T>,
            const_ref<T> >
        {
            typedef T type;
        };
    }

    template <typename T>
    struct value
    {
        BOOST_STATIC_ASSERT(
            mpl::not_<is_reference<T> >::value != 0);

        typedef mpl::false_ no_nullary;

        template <typename Env>
        struct result
        {
            typedef T type;
        };

        value()
            : val() {}

        value(T const& arg)
            : val(arg) {}

        template <typename Env>
        T const&
        eval(Env const&) const
        {
            return val;
        }

        T val;
    };

    template <typename Actor>
    struct actor_value
    {
        typedef typename Actor::no_nullary no_nullary;

        template <typename Env>
        struct result
        {
            typedef typename
                remove_reference<
                    typename eval_result<Actor, Env>::type
                >::type
            type;
        };

        actor_value(Actor const& actor)
            : actor(actor) {}

        template <typename Env>
        typename result<Env>::type
        eval(Env const& env) const
        {
            return actor.eval(env);
        }

        Actor actor;
    };

    template <typename T>
    inline typename as_actor<T>::type
    val(T const& v)
    {
        return as_actor<T>::convert(v);
    }

    template <typename Derived>
    inline actor<actor_value<Derived> >
    val(actor<Derived> const& actor)
    {
        return actor_value<Derived>(actor);
    }

    template <typename T>
    struct as_actor_base
    {
        typedef value<T> type;

        static value<T>
        convert(typename meta::argument_type<T>::type x)
        {
            return value<T>(x);
        }
    };

    // Sometimes it is necessary to auto-convert references to
    // a value<T>. This happens when we are re-currying. This
    // cannot happen through the standard public actor interfaces.
    template <typename T>
    struct as_actor_base<T&>
    {
        typedef value<T> type;

        static value<T>
        convert(T& x)
        {
            return value<T>(x);
        }
    };

    template <typename T, int N>
    struct as_actor_base<T[N]>
    {
        typedef value<T const*> type;

        static value<T const*>
        convert(T const x[N])
        {
            return value<T const*>(x);
        }
    };
}}

#endif