extending_rt_traits.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  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. #include <boost/test/minimal.hpp> // see "Header Implementation Option"
  13. #include "boost/lambda/bind.hpp"
  14. #include "boost/lambda/lambda.hpp"
  15. #include "boost/lambda/detail/suppress_unused.hpp"
  16. #include <iostream>
  17. #include <functional>
  18. #include <algorithm>
  19. using boost::lambda::detail::suppress_unused_variable_warnings;
  20. class A {};
  21. class B {};
  22. using namespace boost::lambda;
  23. B operator--(const A&, int) { return B(); }
  24. B operator--(A&) { return B(); }
  25. B operator++(const A&, int) { return B(); }
  26. B operator++(A&) { return B(); }
  27. B operator-(const A&) { return B(); }
  28. B operator+(const A&) { return B(); }
  29. B operator!(const A&) { return B(); }
  30. B operator&(const A&) { return B(); }
  31. B operator*(const A&) { return B(); }
  32. namespace boost {
  33. namespace lambda {
  34. // unary + and -
  35. template<class Act>
  36. struct plain_return_type_1<unary_arithmetic_action<Act>, A > {
  37. typedef B type;
  38. };
  39. // post incr/decr
  40. template<class Act>
  41. struct plain_return_type_1<post_increment_decrement_action<Act>, A > {
  42. typedef B type;
  43. };
  44. // pre incr/decr
  45. template<class Act>
  46. struct plain_return_type_1<pre_increment_decrement_action<Act>, A > {
  47. typedef B type;
  48. };
  49. // !
  50. template<>
  51. struct plain_return_type_1<logical_action<not_action>, A> {
  52. typedef B type;
  53. };
  54. // &
  55. template<>
  56. struct plain_return_type_1<other_action<addressof_action>, A> {
  57. typedef B type;
  58. };
  59. // *
  60. template<>
  61. struct plain_return_type_1<other_action<contentsof_action>, A> {
  62. typedef B type;
  63. };
  64. } // lambda
  65. } // boost
  66. void ok(B /*b*/) {}
  67. void test_unary_operators()
  68. {
  69. A a; int i = 1;
  70. ok((++_1)(a));
  71. ok((--_1)(a));
  72. ok((_1++)(a));
  73. ok((_1--)(a));
  74. ok((+_1)(a));
  75. ok((-_1)(a));
  76. ok((!_1)(a));
  77. ok((&_1)(a));
  78. ok((*_1)(a));
  79. BOOST_CHECK((*_1)(make_const(&i)) == 1);
  80. }
  81. class X {};
  82. class Y {};
  83. class Z {};
  84. Z operator+(const X&, const Y&) { return Z(); }
  85. Z operator-(const X&, const Y&) { return Z(); }
  86. X operator*(const X&, const Y&) { return X(); }
  87. Z operator/(const X&, const Y&) { return Z(); }
  88. Z operator%(const X&, const Y&) { return Z(); }
  89. class XX {};
  90. class YY {};
  91. class ZZ {};
  92. class VV {};
  93. // it is possible to support differently cv-qualified versions
  94. YY operator*(XX&, YY&) { return YY(); }
  95. ZZ operator*(const XX&, const YY&) { return ZZ(); }
  96. XX operator*(volatile XX&, volatile YY&) { return XX(); }
  97. VV operator*(const volatile XX&, const volatile YY&) { return VV(); }
  98. // the traits can be more complex:
  99. template <class T>
  100. class my_vector {};
  101. template<class A, class B>
  102. my_vector<typename return_type_2<arithmetic_action<plus_action>, A&, B&>::type>
  103. operator+(const my_vector<A>& /*a*/, const my_vector<B>& /*b*/)
  104. {
  105. typedef typename
  106. return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
  107. return my_vector<res_type>();
  108. }
  109. // bitwise ops:
  110. X operator<<(const X&, const Y&) { return X(); }
  111. Z operator>>(const X&, const Y&) { return Z(); }
  112. Z operator&(const X&, const Y&) { return Z(); }
  113. Z operator|(const X&, const Y&) { return Z(); }
  114. Z operator^(const X&, const Y&) { return Z(); }
  115. // comparison ops:
  116. X operator<(const X&, const Y&) { return X(); }
  117. Z operator>(const X&, const Y&) { return Z(); }
  118. Z operator<=(const X&, const Y&) { return Z(); }
  119. Z operator>=(const X&, const Y&) { return Z(); }
  120. Z operator==(const X&, const Y&) { return Z(); }
  121. Z operator!=(const X&, const Y&) { return Z(); }
  122. // logical
  123. X operator&&(const X&, const Y&) { return X(); }
  124. Z operator||(const X&, const Y&) { return Z(); }
  125. // arithh assignment
  126. Z operator+=( X&, const Y&) { return Z(); }
  127. Z operator-=( X&, const Y&) { return Z(); }
  128. Y operator*=( X&, const Y&) { return Y(); }
  129. Z operator/=( X&, const Y&) { return Z(); }
  130. Z operator%=( X&, const Y&) { return Z(); }
  131. // bitwise assignment
  132. Z operator<<=( X&, const Y&) { return Z(); }
  133. Z operator>>=( X&, const Y&) { return Z(); }
  134. Y operator&=( X&, const Y&) { return Y(); }
  135. Z operator|=( X&, const Y&) { return Z(); }
  136. Z operator^=( X&, const Y&) { return Z(); }
  137. // assignment
  138. class Assign {
  139. public:
  140. void operator=(const Assign& /*a*/) {}
  141. X operator[](const int& /*i*/) { return X(); }
  142. };
  143. namespace boost {
  144. namespace lambda {
  145. // you can do action groups
  146. template<class Act>
  147. struct plain_return_type_2<arithmetic_action<Act>, X, Y> {
  148. typedef Z type;
  149. };
  150. // or specialize the exact action
  151. template<>
  152. struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
  153. typedef X type;
  154. };
  155. // if you want to make a distinction between differently cv-qualified
  156. // types, you need to specialize on a different level:
  157. template<>
  158. struct return_type_2<arithmetic_action<multiply_action>, XX, YY> {
  159. typedef YY type;
  160. };
  161. template<>
  162. struct return_type_2<arithmetic_action<multiply_action>, const XX, const YY> {
  163. typedef ZZ type;
  164. };
  165. template<>
  166. struct return_type_2<arithmetic_action<multiply_action>, volatile XX, volatile YY> {
  167. typedef XX type;
  168. };
  169. template<>
  170. struct return_type_2<arithmetic_action<multiply_action>, volatile const XX, const volatile YY> {
  171. typedef VV type;
  172. };
  173. // the mapping can be more complex:
  174. template<class A, class B>
  175. struct plain_return_type_2<arithmetic_action<plus_action>, my_vector<A>, my_vector<B> > {
  176. typedef typename
  177. return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
  178. typedef my_vector<res_type> type;
  179. };
  180. // bitwise binary:
  181. // you can do action groups
  182. template<class Act>
  183. struct plain_return_type_2<bitwise_action<Act>, X, Y> {
  184. typedef Z type;
  185. };
  186. // or specialize the exact action
  187. template<>
  188. struct plain_return_type_2<bitwise_action<leftshift_action>, X, Y> {
  189. typedef X type;
  190. };
  191. // comparison binary:
  192. // you can do action groups
  193. template<class Act>
  194. struct plain_return_type_2<relational_action<Act>, X, Y> {
  195. typedef Z type;
  196. };
  197. // or specialize the exact action
  198. template<>
  199. struct plain_return_type_2<relational_action<less_action>, X, Y> {
  200. typedef X type;
  201. };
  202. // logical binary:
  203. // you can do action groups
  204. template<class Act>
  205. struct plain_return_type_2<logical_action<Act>, X, Y> {
  206. typedef Z type;
  207. };
  208. // or specialize the exact action
  209. template<>
  210. struct plain_return_type_2<logical_action<and_action>, X, Y> {
  211. typedef X type;
  212. };
  213. // arithmetic assignment :
  214. // you can do action groups
  215. template<class Act>
  216. struct plain_return_type_2<arithmetic_assignment_action<Act>, X, Y> {
  217. typedef Z type;
  218. };
  219. // or specialize the exact action
  220. template<>
  221. struct plain_return_type_2<arithmetic_assignment_action<multiply_action>, X, Y> {
  222. typedef Y type;
  223. };
  224. // arithmetic assignment :
  225. // you can do action groups
  226. template<class Act>
  227. struct plain_return_type_2<bitwise_assignment_action<Act>, X, Y> {
  228. typedef Z type;
  229. };
  230. // or specialize the exact action
  231. template<>
  232. struct plain_return_type_2<bitwise_assignment_action<and_action>, X, Y> {
  233. typedef Y type;
  234. };
  235. // assignment
  236. template<>
  237. struct plain_return_type_2<other_action<assignment_action>, Assign, Assign> {
  238. typedef void type;
  239. };
  240. // subscript
  241. template<>
  242. struct plain_return_type_2<other_action<subscript_action>, Assign, int> {
  243. typedef X type;
  244. };
  245. } // end lambda
  246. } // end boost
  247. void test_binary_operators() {
  248. X x; Y y;
  249. (_1 + _2)(x, y);
  250. (_1 - _2)(x, y);
  251. (_1 * _2)(x, y);
  252. (_1 / _2)(x, y);
  253. (_1 % _2)(x, y);
  254. // make a distinction between differently cv-qualified operators
  255. XX xx; YY yy;
  256. const XX& cxx = xx;
  257. const YY& cyy = yy;
  258. volatile XX& vxx = xx;
  259. volatile YY& vyy = yy;
  260. const volatile XX& cvxx = xx;
  261. const volatile YY& cvyy = yy;
  262. ZZ dummy1 = (_1 * _2)(cxx, cyy);
  263. YY dummy2 = (_1 * _2)(xx, yy);
  264. XX dummy3 = (_1 * _2)(vxx, vyy);
  265. VV dummy4 = (_1 * _2)(cvxx, cvyy);
  266. suppress_unused_variable_warnings(dummy1);
  267. suppress_unused_variable_warnings(dummy2);
  268. suppress_unused_variable_warnings(dummy3);
  269. suppress_unused_variable_warnings(dummy4);
  270. my_vector<int> v1; my_vector<double> v2;
  271. my_vector<double> d = (_1 + _2)(v1, v2);
  272. suppress_unused_variable_warnings(d);
  273. // bitwise
  274. (_1 << _2)(x, y);
  275. (_1 >> _2)(x, y);
  276. (_1 | _2)(x, y);
  277. (_1 & _2)(x, y);
  278. (_1 ^ _2)(x, y);
  279. // comparison
  280. (_1 < _2)(x, y);
  281. (_1 > _2)(x, y);
  282. (_1 <= _2)(x, y);
  283. (_1 >= _2)(x, y);
  284. (_1 == _2)(x, y);
  285. (_1 != _2)(x, y);
  286. // logical
  287. (_1 || _2)(x, y);
  288. (_1 && _2)(x, y);
  289. // arithmetic assignment
  290. (_1 += _2)(x, y);
  291. (_1 -= _2)(x, y);
  292. (_1 *= _2)(x, y);
  293. (_1 /= _2)(x, y);
  294. (_1 %= _2)(x, y);
  295. // bitwise assignment
  296. (_1 <<= _2)(x, y);
  297. (_1 >>= _2)(x, y);
  298. (_1 |= _2)(x, y);
  299. (_1 &= _2)(x, y);
  300. (_1 ^= _2)(x, y);
  301. }
  302. int test_main(int, char *[]) {
  303. test_unary_operators();
  304. test_binary_operators();
  305. return 0;
  306. }