Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / lambda / detail / return_type_traits.hpp
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