• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  extending_return_type_traits.cpp  -- The Boost Lambda Library --------
2 //
3 // Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
4 // Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // For more information, see www.boost.org
11 
12 // -----------------------------------------------------------------------
13 
14 
15 #include <boost/core/lightweight_test.hpp>
16 
17 #include "boost/lambda/bind.hpp"
18 #include "boost/lambda/lambda.hpp"
19 #include "boost/lambda/detail/suppress_unused.hpp"
20 
21 #include <iostream>
22 
23 #include <functional>
24 
25 #include <algorithm>
26 
27 using boost::lambda::detail::suppress_unused_variable_warnings;
28 
29 class A {};
30 class B {};
31 
32 using namespace boost::lambda;
33 
34 
operator --(const A &,int)35 B operator--(const A&, int) { return B(); }
operator --(A &)36 B operator--(A&) { return B(); }
operator ++(const A &,int)37 B operator++(const A&, int) { return B(); }
operator ++(A &)38 B operator++(A&) { return B(); }
operator -(const A &)39 B operator-(const A&) { return B(); }
operator +(const A &)40 B operator+(const A&) { return B(); }
41 
operator !(const A &)42 B operator!(const A&) { return B(); }
43 
operator &(const A &)44 B operator&(const A&) { return B(); }
operator *(const A &)45 B operator*(const A&) { return B(); }
46 
47 namespace boost {
48 namespace lambda {
49 
50   // unary + and -
51 template<class Act>
52 struct plain_return_type_1<unary_arithmetic_action<Act>, A > {
53   typedef B type;
54 };
55 
56   // post incr/decr
57 template<class Act>
58 struct plain_return_type_1<post_increment_decrement_action<Act>, A > {
59   typedef B type;
60 };
61 
62   // pre incr/decr
63 template<class Act>
64 struct plain_return_type_1<pre_increment_decrement_action<Act>, A > {
65   typedef B type;
66 };
67   // !
68 template<>
69 struct plain_return_type_1<logical_action<not_action>, A> {
70   typedef B type;
71 };
72   // &
73 template<>
74 struct plain_return_type_1<other_action<addressof_action>, A> {
75   typedef B type;
76 };
77   // *
78 template<>
79 struct plain_return_type_1<other_action<contentsof_action>, A> {
80   typedef B type;
81 };
82 
83 
84 } // lambda
85 } // boost
86 
ok(B)87 void ok(B /*b*/) {}
88 
test_unary_operators()89 void test_unary_operators()
90 {
91   A a; int i = 1;
92   ok((++_1)(a));
93   ok((--_1)(a));
94   ok((_1++)(a));
95   ok((_1--)(a));
96   ok((+_1)(a));
97   ok((-_1)(a));
98   ok((!_1)(a));
99   ok((&_1)(a));
100   ok((*_1)(a));
101 
102   BOOST_TEST_EQ((*_1)(make_const(&i)), 1);
103 }
104 
105 class X {};
106 class Y {};
107 class Z {};
108 
operator +(const X &,const Y &)109 Z operator+(const X&, const Y&) { return Z(); }
operator -(const X &,const Y &)110 Z operator-(const X&, const Y&) { return Z(); }
operator *(const X &,const Y &)111 X operator*(const X&, const Y&) { return X(); }
112 
operator /(const X &,const Y &)113 Z operator/(const X&, const Y&) { return Z(); }
operator %(const X &,const Y &)114 Z operator%(const X&, const Y&) { return Z(); }
115 
116 class XX {};
117 class YY {};
118 class ZZ {};
119 class VV {};
120 
121 // it is possible to support differently cv-qualified versions
operator *(XX &,YY &)122 YY operator*(XX&, YY&) { return YY(); }
operator *(const XX &,const YY &)123 ZZ operator*(const XX&, const YY&) { return ZZ(); }
operator *(volatile XX &,volatile YY &)124 XX operator*(volatile XX&, volatile YY&) { return XX(); }
operator *(const volatile XX &,const volatile YY &)125 VV operator*(const volatile XX&, const volatile YY&) { return VV(); }
126 
127 // the traits can be more complex:
128 template <class T>
129 class my_vector {};
130 
131 template<class A, class B>
132 my_vector<typename return_type_2<arithmetic_action<plus_action>, A&, B&>::type>
operator +(const my_vector<A> &,const my_vector<B> &)133 operator+(const my_vector<A>& /*a*/, const my_vector<B>& /*b*/)
134 {
135   typedef typename
136     return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
137   return my_vector<res_type>();
138 }
139 
140 
141 
142 // bitwise ops:
operator <<(const X &,const Y &)143 X operator<<(const X&, const Y&) { return X(); }
operator >>(const X &,const Y &)144 Z operator>>(const X&, const Y&) { return Z(); }
operator &(const X &,const Y &)145 Z operator&(const X&, const Y&) { return Z(); }
operator |(const X &,const Y &)146 Z operator|(const X&, const Y&) { return Z(); }
operator ^(const X &,const Y &)147 Z operator^(const X&, const Y&) { return Z(); }
148 
149 // comparison ops:
150 
operator <(const X &,const Y &)151 X operator<(const X&, const Y&) { return X(); }
operator >(const X &,const Y &)152 Z operator>(const X&, const Y&) { return Z(); }
operator <=(const X &,const Y &)153 Z operator<=(const X&, const Y&) { return Z(); }
operator >=(const X &,const Y &)154 Z operator>=(const X&, const Y&) { return Z(); }
operator ==(const X &,const Y &)155 Z operator==(const X&, const Y&) { return Z(); }
operator !=(const X &,const Y &)156 Z operator!=(const X&, const Y&) { return Z(); }
157 
158 // logical
159 
operator &&(const X &,const Y &)160 X operator&&(const X&, const Y&) { return X(); }
operator ||(const X &,const Y &)161 Z operator||(const X&, const Y&) { return Z(); }
162 
163 // arithh assignment
164 
operator +=(X &,const Y &)165 Z operator+=( X&, const Y&) { return Z(); }
operator -=(X &,const Y &)166 Z operator-=( X&, const Y&) { return Z(); }
operator *=(X &,const Y &)167 Y operator*=( X&, const Y&) { return Y(); }
operator /=(X &,const Y &)168 Z operator/=( X&, const Y&) { return Z(); }
operator %=(X &,const Y &)169 Z operator%=( X&, const Y&) { return Z(); }
170 
171 // bitwise assignment
operator <<=(X &,const Y &)172 Z operator<<=( X&, const Y&) { return Z(); }
operator >>=(X &,const Y &)173 Z operator>>=( X&, const Y&) { return Z(); }
operator &=(X &,const Y &)174 Y operator&=( X&, const Y&) { return Y(); }
operator |=(X &,const Y &)175 Z operator|=( X&, const Y&) { return Z(); }
operator ^=(X &,const Y &)176 Z operator^=( X&, const Y&) { return Z(); }
177 
178 // assignment
179 class Assign {
180 public:
operator =(const Assign &)181   void operator=(const Assign& /*a*/) {}
operator [](const int &)182   X operator[](const int& /*i*/) { return X(); }
183 };
184 
185 
186 
187 namespace boost {
188 namespace lambda {
189 
190   // you can do action groups
191 template<class Act>
192 struct plain_return_type_2<arithmetic_action<Act>, X, Y> {
193   typedef Z type;
194 };
195 
196   // or specialize the exact action
197 template<>
198 struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
199   typedef X type;
200 };
201 
202   // if you want to make a distinction between differently cv-qualified
203   // types, you need to specialize on a different level:
204 template<>
205 struct return_type_2<arithmetic_action<multiply_action>, XX, YY> {
206   typedef YY type;
207 };
208 template<>
209 struct return_type_2<arithmetic_action<multiply_action>, const XX, const YY> {
210   typedef ZZ type;
211 };
212 template<>
213 struct return_type_2<arithmetic_action<multiply_action>, volatile XX, volatile YY> {
214   typedef XX type;
215 };
216 template<>
217 struct return_type_2<arithmetic_action<multiply_action>, volatile const XX, const volatile YY> {
218   typedef VV type;
219 };
220 
221   // the mapping can be more complex:
222 template<class A, class B>
223 struct plain_return_type_2<arithmetic_action<plus_action>, my_vector<A>, my_vector<B> > {
224   typedef typename
225     return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
226   typedef my_vector<res_type> type;
227 };
228 
229   // bitwise binary:
230   // you can do action groups
231 template<class Act>
232 struct plain_return_type_2<bitwise_action<Act>, X, Y> {
233   typedef Z type;
234 };
235 
236   // or specialize the exact action
237 template<>
238 struct plain_return_type_2<bitwise_action<leftshift_action>, X, Y> {
239   typedef X type;
240 };
241 
242   // comparison binary:
243   // you can do action groups
244 template<class Act>
245 struct plain_return_type_2<relational_action<Act>, X, Y> {
246   typedef Z type;
247 };
248 
249   // or specialize the exact action
250 template<>
251 struct plain_return_type_2<relational_action<less_action>, X, Y> {
252   typedef X type;
253 };
254 
255   // logical binary:
256   // you can do action groups
257 template<class Act>
258 struct plain_return_type_2<logical_action<Act>, X, Y> {
259   typedef Z type;
260 };
261 
262   // or specialize the exact action
263 template<>
264 struct plain_return_type_2<logical_action<and_action>, X, Y> {
265   typedef X type;
266 };
267 
268   // arithmetic assignment :
269   // you can do action groups
270 template<class Act>
271 struct plain_return_type_2<arithmetic_assignment_action<Act>, X, Y> {
272   typedef Z type;
273 };
274 
275   // or specialize the exact action
276 template<>
277 struct plain_return_type_2<arithmetic_assignment_action<multiply_action>, X, Y> {
278   typedef Y type;
279 };
280 
281   // arithmetic assignment :
282   // you can do action groups
283 template<class Act>
284 struct plain_return_type_2<bitwise_assignment_action<Act>, X, Y> {
285   typedef Z type;
286 };
287 
288   // or specialize the exact action
289 template<>
290 struct plain_return_type_2<bitwise_assignment_action<and_action>, X, Y> {
291   typedef Y type;
292 };
293 
294   // assignment
295 template<>
296 struct plain_return_type_2<other_action<assignment_action>, Assign, Assign> {
297   typedef void type;
298 };
299   // subscript
300 template<>
301 struct plain_return_type_2<other_action<subscript_action>, Assign, int> {
302   typedef X type;
303 };
304 
305 
306 } // end lambda
307 } // end boost
308 
309 
310 
test_binary_operators()311 void test_binary_operators() {
312 
313   X x; Y y;
314   (_1 + _2)(x, y);
315   (_1 - _2)(x, y);
316   (_1 * _2)(x, y);
317   (_1 / _2)(x, y);
318   (_1 % _2)(x, y);
319 
320 
321   // make a distinction between differently cv-qualified operators
322   XX xx; YY yy;
323   const XX& cxx = xx;
324   const YY& cyy = yy;
325   volatile XX& vxx = xx;
326   volatile YY& vyy = yy;
327   const volatile XX& cvxx = xx;
328   const volatile YY& cvyy = yy;
329 
330   ZZ dummy1 = (_1 * _2)(cxx, cyy);
331   YY dummy2 = (_1 * _2)(xx, yy);
332   XX dummy3 = (_1 * _2)(vxx, vyy);
333   VV dummy4 = (_1 * _2)(cvxx, cvyy);
334 
335   suppress_unused_variable_warnings(dummy1);
336   suppress_unused_variable_warnings(dummy2);
337   suppress_unused_variable_warnings(dummy3);
338   suppress_unused_variable_warnings(dummy4);
339 
340   my_vector<int> v1; my_vector<double> v2;
341   my_vector<double> d = (_1 + _2)(v1, v2);
342 
343   suppress_unused_variable_warnings(d);
344 
345   // bitwise
346 
347   (_1 << _2)(x, y);
348   (_1 >> _2)(x, y);
349   (_1 | _2)(x, y);
350   (_1 & _2)(x, y);
351   (_1 ^ _2)(x, y);
352 
353   // comparison
354 
355   (_1 < _2)(x, y);
356   (_1 > _2)(x, y);
357   (_1 <= _2)(x, y);
358   (_1 >= _2)(x, y);
359   (_1 == _2)(x, y);
360   (_1 != _2)(x, y);
361 
362   // logical
363 
364   (_1 || _2)(x, y);
365   (_1 && _2)(x, y);
366 
367   // arithmetic assignment
368   (_1 += _2)(x, y);
369   (_1 -= _2)(x, y);
370   (_1 *= _2)(x, y);
371   (_1 /= _2)(x, y);
372   (_1 %= _2)(x, y);
373 
374   // bitwise assignment
375   (_1 <<= _2)(x, y);
376   (_1 >>= _2)(x, y);
377   (_1 |= _2)(x, y);
378   (_1 &= _2)(x, y);
379   (_1 ^= _2)(x, y);
380 
381 }
382 
383 
main()384 int main()
385 {
386   test_unary_operators();
387   test_binary_operators();
388   return boost::report_errors();
389 }
390