]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | /// \file poly_function.hpp | |
3 | /// A wrapper that makes a tr1-style function object that handles const | |
4 | /// and non-const refs and reference_wrapper arguments, too, and forwards | |
5 | /// the arguments on to the specified implementation. | |
6 | // | |
7 | // Copyright 2008 Eric Niebler. Distributed under the Boost | |
8 | // Software License, Version 1.0. (See accompanying file | |
9 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
10 | ||
11 | #ifndef BOOST_PROTO_DETAIL_POLY_FUNCTION_EAN_2008_05_02 | |
12 | #define BOOST_PROTO_DETAIL_POLY_FUNCTION_EAN_2008_05_02 | |
13 | ||
14 | #include <boost/ref.hpp> | |
15 | #include <boost/mpl/bool.hpp> | |
16 | #include <boost/mpl/void.hpp> | |
17 | #include <boost/mpl/size_t.hpp> | |
18 | #include <boost/mpl/eval_if.hpp> | |
19 | #include <boost/preprocessor/cat.hpp> | |
20 | #include <boost/preprocessor/facilities/intercept.hpp> | |
21 | #include <boost/preprocessor/iteration/iterate.hpp> | |
22 | #include <boost/preprocessor/repetition/enum.hpp> | |
23 | #include <boost/preprocessor/repetition/enum_params.hpp> | |
24 | #include <boost/preprocessor/repetition/enum_trailing_params.hpp> | |
25 | #include <boost/preprocessor/repetition/enum_binary_params.hpp> | |
26 | #include <boost/proto/proto_fwd.hpp> | |
27 | #include <boost/proto/detail/is_noncopyable.hpp> | |
28 | ||
29 | #ifdef _MSC_VER | |
30 | # pragma warning(push) | |
31 | # pragma warning(disable: 4181) // const applied to reference type | |
32 | #endif | |
33 | ||
34 | namespace boost { namespace proto { namespace detail | |
35 | { | |
36 | ||
37 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
38 | template<typename T> | |
39 | struct normalize_arg | |
40 | { | |
41 | typedef typename mpl::if_c<is_noncopyable<T>::value, T &, T>::type type; | |
42 | typedef T &reference; | |
43 | }; | |
44 | ||
45 | template<typename T> | |
46 | struct normalize_arg<T const> | |
47 | { | |
48 | typedef typename mpl::if_c<is_noncopyable<T>::value, T const &, T>::type type; | |
49 | typedef T const &reference; | |
50 | }; | |
51 | ||
52 | template<typename T> | |
53 | struct normalize_arg<T &> | |
54 | { | |
55 | typedef typename mpl::if_c<is_noncopyable<T>::value, T &, T>::type type; | |
56 | typedef T &reference; | |
57 | }; | |
58 | ||
59 | template<typename T> | |
60 | struct normalize_arg<T const &> | |
61 | { | |
62 | typedef typename mpl::if_c<is_noncopyable<T>::value, T const &, T>::type type; | |
63 | typedef T const &reference; | |
64 | }; | |
65 | ||
66 | template<typename T> | |
67 | struct normalize_arg<boost::reference_wrapper<T> > | |
68 | { | |
69 | typedef T &type; | |
70 | typedef T &reference; | |
71 | }; | |
72 | ||
73 | template<typename T> | |
74 | struct normalize_arg<boost::reference_wrapper<T> const> | |
75 | { | |
76 | typedef T &type; | |
77 | typedef T &reference; | |
78 | }; | |
79 | ||
80 | template<typename T> | |
81 | struct normalize_arg<boost::reference_wrapper<T> &> | |
82 | { | |
83 | typedef T &type; | |
84 | typedef T &reference; | |
85 | }; | |
86 | ||
87 | template<typename T> | |
88 | struct normalize_arg<boost::reference_wrapper<T> const &> | |
89 | { | |
90 | typedef T &type; | |
91 | typedef T &reference; | |
92 | }; | |
93 | ||
94 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
95 | template<typename T> | |
96 | struct arg | |
97 | { | |
98 | typedef T const &type; | |
99 | ||
100 | arg(type t) | |
101 | : value(t) | |
102 | {} | |
103 | ||
104 | operator type() const | |
105 | { | |
106 | return this->value; | |
107 | } | |
108 | ||
109 | type operator()() const | |
110 | { | |
111 | return this->value; | |
112 | } | |
113 | ||
20effc67 | 114 | BOOST_DELETED_FUNCTION(arg &operator =(arg const &)) |
7c673cae | 115 | private: |
7c673cae FG |
116 | type value; |
117 | }; | |
118 | ||
119 | template<typename T> | |
120 | struct arg<T &> | |
121 | { | |
122 | typedef T &type; | |
123 | ||
124 | arg(type t) | |
125 | : value(t) | |
126 | {} | |
127 | ||
128 | operator type() const | |
129 | { | |
130 | return this->value; | |
131 | } | |
132 | ||
133 | type operator()() const | |
134 | { | |
135 | return this->value; | |
136 | } | |
137 | ||
20effc67 | 138 | BOOST_DELETED_FUNCTION(arg &operator =(arg const &)) |
7c673cae | 139 | private: |
7c673cae FG |
140 | type value; |
141 | }; | |
142 | ||
143 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
144 | template<typename T, typename Void = void> | |
145 | struct is_poly_function | |
146 | : mpl::false_ | |
147 | {}; | |
148 | ||
149 | template<typename T> | |
150 | struct is_poly_function<T, typename T::is_poly_function_base_> | |
151 | : mpl::true_ | |
152 | {}; | |
153 | ||
154 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
155 | #define BOOST_PROTO_POLY_FUNCTION() \ | |
156 | typedef void is_poly_function_base_; \ | |
157 | /**/ | |
158 | ||
159 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
160 | struct poly_function_base | |
161 | { | |
162 | /// INTERNAL ONLY | |
163 | BOOST_PROTO_POLY_FUNCTION() | |
164 | }; | |
165 | ||
166 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
167 | template<typename Derived, typename NullaryResult = void> | |
168 | struct poly_function | |
169 | : poly_function_base | |
170 | { | |
171 | template<typename Sig> | |
172 | struct result; | |
173 | ||
174 | template<typename This> | |
175 | struct result<This()> | |
176 | : Derived::template impl<> | |
177 | { | |
178 | typedef typename result::result_type type; | |
179 | }; | |
180 | ||
181 | NullaryResult operator()() const | |
182 | { | |
183 | result<Derived const()> impl; | |
184 | return impl(); | |
185 | } | |
186 | ||
187 | #include <boost/proto/detail/poly_function_funop.hpp> | |
188 | }; | |
189 | ||
190 | template<typename T> | |
191 | struct wrap_t; | |
192 | ||
193 | typedef char poly_function_t; | |
194 | typedef char (&mono_function_t)[2]; | |
195 | typedef char (&unknown_function_t)[3]; | |
196 | ||
197 | template<typename T> poly_function_t test_poly_function(T *, wrap_t<typename T::is_poly_function_base_> * = 0); | |
198 | template<typename T> mono_function_t test_poly_function(T *, wrap_t<typename T::result_type> * = 0); | |
199 | template<typename T> unknown_function_t test_poly_function(T *, ...); | |
200 | ||
201 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
202 | template<typename Fun, typename Sig, typename Switch = mpl::size_t<sizeof(test_poly_function<Fun>(0,0))> > | |
203 | struct poly_function_traits | |
204 | { | |
205 | typedef typename Fun::template result<Sig>::type result_type; | |
206 | typedef Fun function_type; | |
207 | }; | |
208 | ||
209 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
210 | template<typename Fun, typename Sig> | |
211 | struct poly_function_traits<Fun, Sig, mpl::size_t<sizeof(mono_function_t)> > | |
212 | { | |
213 | typedef typename Fun::result_type result_type; | |
214 | typedef Fun function_type; | |
215 | }; | |
216 | ||
217 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
218 | template<typename PolyFunSig, bool IsPolyFunction> | |
219 | struct as_mono_function_impl; | |
220 | ||
221 | //////////////////////////////////////////////////////////////////////////////////////////////// | |
222 | template<typename PolyFunSig> | |
223 | struct as_mono_function; | |
224 | ||
225 | #include <boost/proto/detail/poly_function_traits.hpp> | |
226 | ||
227 | }}} // namespace boost::proto::detail | |
228 | ||
229 | #ifdef _MSC_VER | |
230 | # pragma warning(pop) | |
231 | #endif | |
232 | ||
233 | #endif | |
234 |