1 | // return_type_traits.hpp -- Boost Lambda Library ---------------------------
|
---|
2 |
|
---|
3 | // Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
|
---|
4 | //
|
---|
5 | // Distributed under the Boost Software License, Version 1.0. (See
|
---|
6 | // accompanying file LICENSE_1_0.txt or copy at
|
---|
7 | // http://www.boost.org/LICENSE_1_0.txt)
|
---|
8 | //
|
---|
9 | // For more information, see www.boost.org
|
---|
10 |
|
---|
11 |
|
---|
12 | #ifndef BOOST_LAMBDA_RETURN_TYPE_TRAITS_HPP
|
---|
13 | #define BOOST_LAMBDA_RETURN_TYPE_TRAITS_HPP
|
---|
14 |
|
---|
15 | #include "boost/mpl/has_xxx.hpp"
|
---|
16 |
|
---|
17 | #include <cstddef> // needed for the ptrdiff_t
|
---|
18 |
|
---|
19 | namespace boost {
|
---|
20 | namespace lambda {
|
---|
21 |
|
---|
22 | using ::boost::type_traits::ice_and;
|
---|
23 | using ::boost::type_traits::ice_or;
|
---|
24 | using ::boost::type_traits::ice_not;
|
---|
25 |
|
---|
26 | // Much of the type deduction code for standard arithmetic types
|
---|
27 | // from Gary Powell
|
---|
28 |
|
---|
29 | // different arities:
|
---|
30 | template <class Act, class A1> struct return_type_1; // 1-ary actions
|
---|
31 | template <class Act, class A1, class A2> struct return_type_2; // 2-ary
|
---|
32 | template <class Act, class Args> struct return_type_N; // >3- ary
|
---|
33 |
|
---|
34 | template <class Act, class A1> struct return_type_1_prot;
|
---|
35 | template <class Act, class A1, class A2> struct return_type_2_prot; // 2-ary
|
---|
36 | template <class Act, class A1> struct return_type_N_prot; // >3-ary
|
---|
37 |
|
---|
38 |
|
---|
39 | namespace detail {
|
---|
40 |
|
---|
41 | template<class> class return_type_deduction_failure {};
|
---|
42 |
|
---|
43 | // In some cases return type deduction should fail (an invalid lambda
|
---|
44 | // expression). Sometimes the lambda expression can be ok, the return type
|
---|
45 | // just is not deducible (user defined operators). Then return type deduction
|
---|
46 | // should never be entered at all, and the use of ret<> does this.
|
---|
47 | // However, for nullary lambda functors, return type deduction is always
|
---|
48 | // entered, and there seems to be no way around this.
|
---|
49 |
|
---|
50 | // (the return type is part of the prototype of the non-template
|
---|
51 | // operator()(). The prototype is instantiated, even though the body
|
---|
52 | // is not.)
|
---|
53 |
|
---|
54 | // So, in the case the return type deduction should fail, it should not
|
---|
55 | // fail directly, but rather result in a valid but wrong return type,
|
---|
56 | // causing a compile time error only if the function is really called.
|
---|
57 |
|
---|
58 |
|
---|
59 |
|
---|
60 | } // end detail
|
---|
61 |
|
---|
62 |
|
---|
63 |
|
---|
64 | // return_type_X_prot classes --------------------------------------------
|
---|
65 | // These classes are the first layer that gets instantiated from the
|
---|
66 | // lambda_functor_base sig templates. It will check whether
|
---|
67 | // the action is protectable and one of arguments is "protected" or its
|
---|
68 | // evaluation will otherwise result in another lambda functor.
|
---|
69 | // If this is a case, the result type will be another lambda functor.
|
---|
70 |
|
---|
71 | // The arguments are always non-reference types, except for comma action
|
---|
72 | // where the right argument can be a reference too. This is because it
|
---|
73 | // matters (in the builtin case) whether the argument is an lvalue or
|
---|
74 | // rvalue: int i; i, 1 -> rvalue; 1, i -> lvalue
|
---|
75 |
|
---|
76 | template <class Act, class A> struct return_type_1_prot {
|
---|
77 | public:
|
---|
78 | typedef typename
|
---|
79 | detail::IF<
|
---|
80 | // is_protectable<Act>::value && is_lambda_functor<A>::value,
|
---|
81 | ice_and<is_protectable<Act>::value, is_lambda_functor<A>::value>::value,
|
---|
82 | lambda_functor<
|
---|
83 | lambda_functor_base<
|
---|
84 | Act,
|
---|
85 | tuple<typename detail::remove_reference_and_cv<A>::type>
|
---|
86 | >
|
---|
87 | >,
|
---|
88 | typename return_type_1<Act, A>::type
|
---|
89 | >::RET type;
|
---|
90 | };
|
---|
91 |
|
---|
92 | // take care of the unavoidable instantiation for nullary case
|
---|
93 | template<class Act> struct return_type_1_prot<Act, null_type> {
|
---|
94 | typedef null_type type;
|
---|
95 | };
|
---|
96 |
|
---|
97 | // Unary actions (result from unary operators)
|
---|
98 | // do not have a default return type.
|
---|
99 | template<class Act, class A> struct return_type_1 {
|
---|
100 | typedef typename
|
---|
101 | detail::return_type_deduction_failure<return_type_1> type;
|
---|
102 | };
|
---|
103 |
|
---|
104 |
|
---|
105 | namespace detail {
|
---|
106 |
|
---|
107 | template <class T>
|
---|
108 | class protect_conversion {
|
---|
109 | typedef typename boost::remove_reference<T>::type non_ref_T;
|
---|
110 | public:
|
---|
111 |
|
---|
112 | // add const to rvalues, so that all rvalues are stored as const in
|
---|
113 | // the args tuple
|
---|
114 | typedef typename detail::IF_type<
|
---|
115 | // boost::is_reference<T>::value && !boost::is_const<non_ref_T>::value,
|
---|
116 | ice_and<boost::is_reference<T>::value,
|
---|
117 | ice_not<boost::is_const<non_ref_T>::value>::value>::value,
|
---|
118 | detail::identity_mapping<T>,
|
---|
119 | const_copy_argument<non_ref_T> // handles funtion and array
|
---|
120 | >::type type; // types correctly
|
---|
121 | };
|
---|
122 |
|
---|
123 | } // end detail
|
---|
124 |
|
---|
125 | template <class Act, class A, class B> struct return_type_2_prot {
|
---|
126 |
|
---|
127 | // experimental feature
|
---|
128 | // We may have a lambda functor as a result type of a subexpression
|
---|
129 | // (if protect) has been used.
|
---|
130 | // Thus, if one of the parameter types is a lambda functor, the result
|
---|
131 | // is a lambda functor as well.
|
---|
132 | // We need to make a conservative choise here.
|
---|
133 | // The resulting lambda functor stores all const reference arguments as
|
---|
134 | // const copies. References to non-const are stored as such.
|
---|
135 | // So if the source of the argument is a const open argument, a bound
|
---|
136 | // argument stored as a const reference, or a function returning a
|
---|
137 | // const reference, that information is lost. There is no way of
|
---|
138 | // telling apart 'real const references' from just 'LL internal
|
---|
139 | // const references' (or it would be really hard)
|
---|
140 |
|
---|
141 | // The return type is a subclass of lambda_functor, which has a converting
|
---|
142 | // copy constructor. It can copy any lambda functor, that has the same
|
---|
143 | // action type and code, and a copy compatible argument tuple.
|
---|
144 |
|
---|
145 |
|
---|
146 | typedef typename boost::remove_reference<A>::type non_ref_A;
|
---|
147 | typedef typename boost::remove_reference<B>::type non_ref_B;
|
---|
148 |
|
---|
149 | typedef typename
|
---|
150 | detail::IF<
|
---|
151 | // is_protectable<Act>::value &&
|
---|
152 | // (is_lambda_functor<A>::value || is_lambda_functor<B>::value),
|
---|
153 | ice_and<is_protectable<Act>::value,
|
---|
154 | ice_or<is_lambda_functor<A>::value,
|
---|
155 | is_lambda_functor<B>::value>::value>::value,
|
---|
156 | lambda_functor<
|
---|
157 | lambda_functor_base<
|
---|
158 | Act,
|
---|
159 | tuple<typename detail::protect_conversion<A>::type,
|
---|
160 | typename detail::protect_conversion<B>::type>
|
---|
161 | >
|
---|
162 | >,
|
---|
163 | typename return_type_2<Act, non_ref_A, non_ref_B>::type
|
---|
164 | >::RET type;
|
---|
165 | };
|
---|
166 |
|
---|
167 | // take care of the unavoidable instantiation for nullary case
|
---|
168 | template<class Act> struct return_type_2_prot<Act, null_type, null_type> {
|
---|
169 | typedef null_type type;
|
---|
170 | };
|
---|
171 | // take care of the unavoidable instantiation for nullary case
|
---|
172 | template<class Act, class Other> struct return_type_2_prot<Act, Other, null_type> {
|
---|
173 | typedef null_type type;
|
---|
174 | };
|
---|
175 | // take care of the unavoidable instantiation for nullary case
|
---|
176 | template<class Act, class Other> struct return_type_2_prot<Act, null_type, Other> {
|
---|
177 | typedef null_type type;
|
---|
178 | };
|
---|
179 |
|
---|
180 | // comma is a special case, as the user defined operator can return
|
---|
181 | // an lvalue (reference) too, hence it must be handled at this level.
|
---|
182 | template<class A, class B>
|
---|
183 | struct return_type_2_comma
|
---|
184 | {
|
---|
185 | typedef typename boost::remove_reference<A>::type non_ref_A;
|
---|
186 | typedef typename boost::remove_reference<B>::type non_ref_B;
|
---|
187 |
|
---|
188 | typedef typename
|
---|
189 | detail::IF<
|
---|
190 | // is_protectable<other_action<comma_action> >::value && // it is protectable
|
---|
191 | // (is_lambda_functor<A>::value || is_lambda_functor<B>::value),
|
---|
192 | ice_and<is_protectable<other_action<comma_action> >::value, // it is protectable
|
---|
193 | ice_or<is_lambda_functor<A>::value,
|
---|
194 | is_lambda_functor<B>::value>::value>::value,
|
---|
195 | lambda_functor<
|
---|
196 | lambda_functor_base<
|
---|
197 | other_action<comma_action>,
|
---|
198 | tuple<typename detail::protect_conversion<A>::type,
|
---|
199 | typename detail::protect_conversion<B>::type>
|
---|
200 | >
|
---|
201 | >,
|
---|
202 | typename
|
---|
203 | return_type_2<other_action<comma_action>, non_ref_A, non_ref_B>::type
|
---|
204 | >::RET type1;
|
---|
205 |
|
---|
206 | // if no user defined return_type_2 (or plain_return_type_2) specialization
|
---|
207 | // matches, then return the righthand argument
|
---|
208 | typedef typename
|
---|
209 | detail::IF<
|
---|
210 | boost::is_same<type1, detail::unspecified>::value,
|
---|
211 | B,
|
---|
212 | type1
|
---|
213 | >::RET type;
|
---|
214 |
|
---|
215 | };
|
---|
216 |
|
---|
217 |
|
---|
218 | // currently there are no protectable actions with > 2 args
|
---|
219 | // Note, that if there will be, lambda_functor_base will have to be
|
---|
220 | // changed to not get rid of references in Args elements
|
---|
221 |
|
---|
222 | template<class Act, class Args> struct return_type_N_prot {
|
---|
223 | typedef typename return_type_N<Act, Args>::type type;
|
---|
224 | };
|
---|
225 |
|
---|
226 | // take care of the unavoidable instantiation for nullary case
|
---|
227 | template<class Act> struct return_type_N_prot<Act, null_type> {
|
---|
228 | typedef null_type type;
|
---|
229 | };
|
---|
230 |
|
---|
231 | // handle different kind of actions ------------------------
|
---|
232 |
|
---|
233 | // use the return type given in the bind invocation as bind<Ret>(...)
|
---|
234 | template<int I, class Args, class Ret>
|
---|
235 | struct return_type_N<function_action<I, Ret>, Args> {
|
---|
236 | typedef Ret type;
|
---|
237 | };
|
---|
238 |
|
---|
239 | // ::result_type support
|
---|
240 |
|
---|
241 | namespace detail
|
---|
242 | {
|
---|
243 |
|
---|
244 | BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
|
---|
245 |
|
---|
246 | template<class F> struct get_result_type
|
---|
247 | {
|
---|
248 | typedef typename F::result_type type;
|
---|
249 | };
|
---|
250 |
|
---|
251 | template<class F, class A> struct get_sig
|
---|
252 | {
|
---|
253 | typedef typename function_adaptor<F>::template sig<A>::type type;
|
---|
254 | };
|
---|
255 |
|
---|
256 | } // namespace detail
|
---|
257 |
|
---|
258 | // Ret is detail::unspecified, so try to deduce return type
|
---|
259 | template<int I, class Args>
|
---|
260 | struct return_type_N<function_action<I, detail::unspecified>, Args > {
|
---|
261 |
|
---|
262 | // in the case of function action, the first element in Args is
|
---|
263 | // some type of function
|
---|
264 | typedef typename Args::head_type Func;
|
---|
265 | typedef typename detail::remove_reference_and_cv<Func>::type plain_Func;
|
---|
266 |
|
---|
267 | public:
|
---|
268 | // pass the function to function_adaptor, and get the return type from
|
---|
269 | // that
|
---|
270 | typedef typename detail::IF<
|
---|
271 | detail::has_result_type<plain_Func>::value,
|
---|
272 | detail::get_result_type<plain_Func>,
|
---|
273 | detail::get_sig<plain_Func, Args>
|
---|
274 | >::RET::type type;
|
---|
275 | };
|
---|
276 |
|
---|
277 |
|
---|
278 | } // namespace lambda
|
---|
279 | } // namespace boost
|
---|
280 |
|
---|
281 | #endif
|
---|
282 |
|
---|
283 |
|
---|
284 |
|
---|