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