summaryrefslogtreecommitdiffstats
blob: 27f3e8d1a8a868473b7e784b702c8cab75af7eea (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
/*=============================================================================
    Copyright (c) 2005-2007 Dan Marsden
    Copyright (c) 2005-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_OPERATOR_MEMBER_HPP
#define PHOENIX_OPERATOR_MEMBER_HPP

#include <boost/spirit/home/phoenix/core/actor.hpp>
#include <boost/spirit/home/phoenix/core/composite.hpp>
#include <boost/spirit/home/phoenix/core/compose.hpp>

#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_member_pointer.hpp>
#include <boost/type_traits/is_member_function_pointer.hpp>

#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>

#include <boost/utility/enable_if.hpp>

#include <boost/get_pointer.hpp>

#include <boost/spirit/home/phoenix/operator/detail/mem_fun_ptr_gen.hpp>

#include <memory>

namespace boost { 
    template<typename T> class shared_ptr;
    template<typename T> class scoped_ptr;

namespace phoenix {
    namespace detail
    {
        template<typename T>
        struct member_type;
        
        template<typename Class, typename MemberType>
        struct member_type<MemberType (Class::*)>
        {
            typedef MemberType type;
        };
    }

    namespace meta
    {
        template<typename T> 
        struct pointed_type;

        template<typename T>
        struct pointed_type<T*>
        {
            typedef T type;
        };

        template<typename T>
        struct pointed_type<shared_ptr<T> >
        {
            typedef T type;
        };
        
        template<typename T>
        struct pointed_type<scoped_ptr<T> >
        {
            typedef T type;
        };

        template<typename T>
        struct pointed_type<std::auto_ptr<T> >
        {
            typedef T type;
        };
    }

    struct member_object_eval
    {
        template<typename Env, typename PtrActor, typename MemPtrActor>
        struct result
        {
            typedef typename detail::member_type<
                typename eval_result<MemPtrActor, Env>::type>::type member_type;

            typedef typename meta::pointed_type<
                typename remove_reference<
                typename eval_result<PtrActor, Env>::type>::type>::type object_type;

            typedef typename add_reference<
                typename mpl::eval_if<
                is_const<object_type>,
                add_const<member_type>,
                mpl::identity<member_type> >::type>::type type;
        };

        template<typename Rt, typename Env, typename PtrActor, typename MemPtrActor>
        static typename result<Env,PtrActor,MemPtrActor>::type
        eval(const Env& env, PtrActor& ptrActor, MemPtrActor& memPtrActor)
        {
            return get_pointer(ptrActor.eval(env))->*memPtrActor.eval(env);
        }
    };

    namespace member_object
    {
        template<typename T0, typename MemObjPtr>
        typename enable_if<
            mpl::and_<is_member_pointer<MemObjPtr>, mpl::not_<is_member_function_pointer<MemObjPtr> > >,
            actor<typename as_composite<
            member_object_eval, actor<T0>,
            typename as_actor<MemObjPtr>::type>::type> >::type
        operator->*(
            const actor<T0>& ptrActor, 
            MemObjPtr memObjPtr)
        {
            return compose<member_object_eval>(
                ptrActor,
                as_actor<MemObjPtr>::convert(memObjPtr));
        }
    }

    namespace member_function
    {
        template<typename T0, typename MemFunPtr>
        typename enable_if<
            is_member_function_pointer<MemFunPtr>,
            mem_fun_ptr_gen<actor<T0>, MemFunPtr> >::type
        operator->*(const actor<T0>& ptrActor, MemFunPtr memFunPtr)
        {
            return mem_fun_ptr_gen<actor<T0>, MemFunPtr>(
                ptrActor, memFunPtr);
        }
    }

    using member_object::operator->*;
    using member_function::operator->*;
}}

#endif