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