operators.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // Boost Lambda Library - operators.hpp --------------------------------------
  2. // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // For more information, see www.boost.org
  9. // ---------------------------------------------------------------
  10. #ifndef BOOST_LAMBDA_OPERATORS_HPP
  11. #define BOOST_LAMBDA_OPERATORS_HPP
  12. #include "boost/lambda/detail/is_instance_of.hpp"
  13. namespace boost {
  14. namespace lambda {
  15. #if defined BOOST_LAMBDA_BE1
  16. #error "Multiple defines of BOOST_LAMBDA_BE1"
  17. #endif
  18. // For all BOOSTA_LAMBDA_BE* macros:
  19. // CONSTA must be either 'A' or 'const A'
  20. // CONSTB must be either 'B' or 'const B'
  21. // It is stupid to have the names A and B as macro arguments, but it avoids
  22. // the need to pass in emtpy macro arguments, which gives warnings on some
  23. // compilers
  24. #define BOOST_LAMBDA_BE1(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \
  25. template<class Arg, class B> \
  26. inline const \
  27. lambda_functor< \
  28. lambda_functor_base< \
  29. ACTION, \
  30. tuple<lambda_functor<Arg>, typename const_copy_argument <CONSTB>::type> \
  31. > \
  32. > \
  33. OPER_NAME (const lambda_functor<Arg>& a, CONSTB& b) { \
  34. return \
  35. lambda_functor_base< \
  36. ACTION, \
  37. tuple<lambda_functor<Arg>, typename const_copy_argument <CONSTB>::type>\
  38. > \
  39. (tuple<lambda_functor<Arg>, typename const_copy_argument <CONSTB>::type>(a, b)); \
  40. }
  41. #if defined BOOST_LAMBDA_BE2
  42. #error "Multiple defines of BOOST_LAMBDA_BE2"
  43. #endif
  44. #define BOOST_LAMBDA_BE2(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \
  45. template<class A, class Arg> \
  46. inline const \
  47. lambda_functor< \
  48. lambda_functor_base< \
  49. ACTION, \
  50. tuple<typename CONVERSION <CONSTA>::type, lambda_functor<Arg> > \
  51. > \
  52. > \
  53. OPER_NAME (CONSTA& a, const lambda_functor<Arg>& b) { \
  54. return \
  55. lambda_functor_base< \
  56. ACTION, \
  57. tuple<typename CONVERSION <CONSTA>::type, lambda_functor<Arg> > \
  58. > \
  59. (tuple<typename CONVERSION <CONSTA>::type, lambda_functor<Arg> >(a, b)); \
  60. }
  61. #if defined BOOST_LAMBDA_BE3
  62. #error "Multiple defines of BOOST_LAMBDA_BE3"
  63. #endif
  64. #define BOOST_LAMBDA_BE3(OPER_NAME, ACTION, CONSTA, CONSTB, CONVERSION) \
  65. template<class ArgA, class ArgB> \
  66. inline const \
  67. lambda_functor< \
  68. lambda_functor_base< \
  69. ACTION, \
  70. tuple<lambda_functor<ArgA>, lambda_functor<ArgB> > \
  71. > \
  72. > \
  73. OPER_NAME (const lambda_functor<ArgA>& a, const lambda_functor<ArgB>& b) { \
  74. return \
  75. lambda_functor_base< \
  76. ACTION, \
  77. tuple<lambda_functor<ArgA>, lambda_functor<ArgB> > \
  78. > \
  79. (tuple<lambda_functor<ArgA>, lambda_functor<ArgB> >(a, b)); \
  80. }
  81. #if defined BOOST_LAMBDA_BE
  82. #error "Multiple defines of BOOST_LAMBDA_BE"
  83. #endif
  84. #define BOOST_LAMBDA_BE(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \
  85. BOOST_LAMBDA_BE1(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \
  86. BOOST_LAMBDA_BE2(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION) \
  87. BOOST_LAMBDA_BE3(OPER_NAME, ACTION, CONSTA, CONSTB, CONST_CONVERSION)
  88. #define BOOST_LAMBDA_EMPTY()
  89. BOOST_LAMBDA_BE(operator+, arithmetic_action<plus_action>, const A, const B, const_copy_argument)
  90. BOOST_LAMBDA_BE(operator-, arithmetic_action<minus_action>, const A, const B, const_copy_argument)
  91. BOOST_LAMBDA_BE(operator*, arithmetic_action<multiply_action>, const A, const B, const_copy_argument)
  92. BOOST_LAMBDA_BE(operator/, arithmetic_action<divide_action>, const A, const B, const_copy_argument)
  93. BOOST_LAMBDA_BE(operator%, arithmetic_action<remainder_action>, const A, const B, const_copy_argument)
  94. BOOST_LAMBDA_BE(operator<<, bitwise_action<leftshift_action>, const A, const B, const_copy_argument)
  95. BOOST_LAMBDA_BE(operator>>, bitwise_action<rightshift_action>, const A, const B, const_copy_argument)
  96. BOOST_LAMBDA_BE(operator&, bitwise_action<and_action>, const A, const B, const_copy_argument)
  97. BOOST_LAMBDA_BE(operator|, bitwise_action<or_action>, const A, const B, const_copy_argument)
  98. BOOST_LAMBDA_BE(operator^, bitwise_action<xor_action>, const A, const B, const_copy_argument)
  99. BOOST_LAMBDA_BE(operator&&, logical_action<and_action>, const A, const B, const_copy_argument)
  100. BOOST_LAMBDA_BE(operator||, logical_action<or_action>, const A, const B, const_copy_argument)
  101. BOOST_LAMBDA_BE(operator<, relational_action<less_action>, const A, const B, const_copy_argument)
  102. BOOST_LAMBDA_BE(operator>, relational_action<greater_action>, const A, const B, const_copy_argument)
  103. BOOST_LAMBDA_BE(operator<=, relational_action<lessorequal_action>, const A, const B, const_copy_argument)
  104. BOOST_LAMBDA_BE(operator>=, relational_action<greaterorequal_action>, const A, const B, const_copy_argument)
  105. BOOST_LAMBDA_BE(operator==, relational_action<equal_action>, const A, const B, const_copy_argument)
  106. BOOST_LAMBDA_BE(operator!=, relational_action<notequal_action>, const A, const B, const_copy_argument)
  107. BOOST_LAMBDA_BE(operator+=, arithmetic_assignment_action<plus_action>, A, const B, reference_argument)
  108. BOOST_LAMBDA_BE(operator-=, arithmetic_assignment_action<minus_action>, A, const B, reference_argument)
  109. BOOST_LAMBDA_BE(operator*=, arithmetic_assignment_action<multiply_action>, A, const B, reference_argument)
  110. BOOST_LAMBDA_BE(operator/=, arithmetic_assignment_action<divide_action>, A, const B, reference_argument)
  111. BOOST_LAMBDA_BE(operator%=, arithmetic_assignment_action<remainder_action>, A, const B, reference_argument)
  112. BOOST_LAMBDA_BE(operator<<=, bitwise_assignment_action<leftshift_action>, A, const B, reference_argument)
  113. BOOST_LAMBDA_BE(operator>>=, bitwise_assignment_action<rightshift_action>, A, const B, reference_argument)
  114. BOOST_LAMBDA_BE(operator&=, bitwise_assignment_action<and_action>, A, const B, reference_argument)
  115. BOOST_LAMBDA_BE(operator|=, bitwise_assignment_action<or_action>, A, const B, reference_argument)
  116. BOOST_LAMBDA_BE(operator^=, bitwise_assignment_action<xor_action>, A, const B, reference_argument)
  117. // A special trick for comma operator for correct preprocessing
  118. #if defined BOOST_LAMBDA_COMMA_OPERATOR_NAME
  119. #error "Multiple defines of BOOST_LAMBDA_COMMA_OPERATOR_NAME"
  120. #endif
  121. #define BOOST_LAMBDA_COMMA_OPERATOR_NAME operator,
  122. BOOST_LAMBDA_BE1(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const A, const B, const_copy_argument)
  123. BOOST_LAMBDA_BE2(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const A, const B, const_copy_argument)
  124. BOOST_LAMBDA_BE3(BOOST_LAMBDA_COMMA_OPERATOR_NAME, other_action<comma_action>, const A, const B, const_copy_argument)
  125. namespace detail {
  126. // special cases for ostream& << Any and istream& >> Any ---------------
  127. // the actual stream classes may vary and thus a specialisation for,
  128. // say ostream& does not match (the general case above is chosen).
  129. // Therefore we specialise for non-const reference:
  130. // if the left argument is a stream, we store the stream as reference
  131. // if it is something else, we store a const plain by default
  132. // Note that the overloading is const vs. non-const first argument
  133. template<class T> struct convert_ostream_to_ref_others_to_c_plain_by_default {
  134. typedef typename detail::IF<
  135. is_instance_of_2<
  136. T, std::basic_ostream
  137. >::value,
  138. T&,
  139. typename const_copy_argument <T>::type
  140. >::RET type;
  141. };
  142. template<class T> struct convert_istream_to_ref_others_to_c_plain_by_default {
  143. typedef typename detail::IF<
  144. is_instance_of_2<
  145. T, std::basic_istream
  146. >::value,
  147. T&,
  148. typename const_copy_argument <T>::type
  149. >::RET type;
  150. };
  151. } // detail
  152. BOOST_LAMBDA_BE2(operator<<, bitwise_action< leftshift_action>, A, const B, detail::convert_ostream_to_ref_others_to_c_plain_by_default)
  153. BOOST_LAMBDA_BE2(operator>>, bitwise_action< rightshift_action>, A, const B, detail::convert_istream_to_ref_others_to_c_plain_by_default)
  154. // special case for io_manipulators.
  155. // function references cannot be given as arguments to lambda operator
  156. // expressions in general. With << and >> the use of manipulators is
  157. // so common, that specializations are provided to make them work.
  158. template<class Arg, class Ret, class ManipArg>
  159. inline const
  160. lambda_functor<
  161. lambda_functor_base<
  162. bitwise_action<leftshift_action>,
  163. tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
  164. >
  165. >
  166. operator<<(const lambda_functor<Arg>& a, Ret(&b)(ManipArg))
  167. {
  168. return
  169. lambda_functor_base<
  170. bitwise_action<leftshift_action>,
  171. tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
  172. >
  173. ( tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>(a, b) );
  174. }
  175. template<class Arg, class Ret, class ManipArg>
  176. inline const
  177. lambda_functor<
  178. lambda_functor_base<
  179. bitwise_action<rightshift_action>,
  180. tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
  181. >
  182. >
  183. operator>>(const lambda_functor<Arg>& a, Ret(&b)(ManipArg))
  184. {
  185. return
  186. lambda_functor_base<
  187. bitwise_action<rightshift_action>,
  188. tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>
  189. >
  190. ( tuple<lambda_functor<Arg>, Ret(&)(ManipArg)>(a, b) );
  191. }
  192. // (+ and -) take their arguments as const references.
  193. // This has consquences with pointer artihmetic
  194. // E.g int a[]; ... *a = 1 works but not *(a+1) = 1.
  195. // the result of a+1 would be const
  196. // To make the latter work too,
  197. // non-const arrays are taken as non-const and stored as non-const as well.
  198. #if defined BOOST_LAMBDA_PTR_ARITHMETIC_E1
  199. #error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_E1"
  200. #endif
  201. #define BOOST_LAMBDA_PTR_ARITHMETIC_E1(OPER_NAME, ACTION, CONSTB) \
  202. template<class Arg, int N, class B> \
  203. inline const \
  204. lambda_functor< \
  205. lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONSTB(&)[N]> > \
  206. > \
  207. OPER_NAME (const lambda_functor<Arg>& a, CONSTB(&b)[N]) \
  208. { \
  209. return \
  210. lambda_functor_base<ACTION, tuple<lambda_functor<Arg>, CONSTB(&)[N]> > \
  211. (tuple<lambda_functor<Arg>, CONSTB(&)[N]>(a, b)); \
  212. }
  213. #if defined BOOST_LAMBDA_PTR_ARITHMETIC_E2
  214. #error "Multiple defines of BOOST_LAMBDA_PTR_ARITHMETIC_E2"
  215. #endif
  216. #define BOOST_LAMBDA_PTR_ARITHMETIC_E2(OPER_NAME, ACTION, CONSTA) \
  217. template<int N, class A, class Arg> \
  218. inline const \
  219. lambda_functor< \
  220. lambda_functor_base<ACTION, tuple<CONSTA(&)[N], lambda_functor<Arg> > > \
  221. > \
  222. OPER_NAME (CONSTA(&a)[N], const lambda_functor<Arg>& b) \
  223. { \
  224. return \
  225. lambda_functor_base<ACTION, tuple<CONSTA(&)[N], lambda_functor<Arg> > > \
  226. (tuple<CONSTA(&)[N], lambda_functor<Arg> >(a, b)); \
  227. }
  228. BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action<plus_action>, B)
  229. BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action<plus_action>, A)
  230. BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator+, arithmetic_action<plus_action>,const B)
  231. BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator+, arithmetic_action<plus_action>,const A)
  232. //BOOST_LAMBDA_PTR_ARITHMETIC_E1(operator-, arithmetic_action<minus_action>)
  233. // This is not needed, since the result of ptr-ptr is an rvalue anyway
  234. BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action<minus_action>, A)
  235. BOOST_LAMBDA_PTR_ARITHMETIC_E2(operator-, arithmetic_action<minus_action>, const A)
  236. #undef BOOST_LAMBDA_BE1
  237. #undef BOOST_LAMBDA_BE2
  238. #undef BOOST_LAMBDA_BE3
  239. #undef BOOST_LAMBDA_BE
  240. #undef BOOST_LAMBDA_COMMA_OPERATOR_NAME
  241. #undef BOOST_LAMBDA_PTR_ARITHMETIC_E1
  242. #undef BOOST_LAMBDA_PTR_ARITHMETIC_E2
  243. // ---------------------------------------------------------------------
  244. // unary operators -----------------------------------------------------
  245. // ---------------------------------------------------------------------
  246. #if defined BOOST_LAMBDA_UE
  247. #error "Multiple defines of BOOST_LAMBDA_UE"
  248. #endif
  249. #define BOOST_LAMBDA_UE(OPER_NAME, ACTION) \
  250. template<class Arg> \
  251. inline const \
  252. lambda_functor<lambda_functor_base<ACTION, tuple<lambda_functor<Arg> > > > \
  253. OPER_NAME (const lambda_functor<Arg>& a) \
  254. { \
  255. return \
  256. lambda_functor_base<ACTION, tuple<lambda_functor<Arg> > > \
  257. ( tuple<lambda_functor<Arg> >(a) ); \
  258. }
  259. BOOST_LAMBDA_UE(operator+, unary_arithmetic_action<plus_action>)
  260. BOOST_LAMBDA_UE(operator-, unary_arithmetic_action<minus_action>)
  261. BOOST_LAMBDA_UE(operator~, bitwise_action<not_action>)
  262. BOOST_LAMBDA_UE(operator!, logical_action<not_action>)
  263. BOOST_LAMBDA_UE(operator++, pre_increment_decrement_action<increment_action>)
  264. BOOST_LAMBDA_UE(operator--, pre_increment_decrement_action<decrement_action>)
  265. BOOST_LAMBDA_UE(operator*, other_action<contentsof_action>)
  266. BOOST_LAMBDA_UE(operator&, other_action<addressof_action>)
  267. #if defined BOOST_LAMBDA_POSTFIX_UE
  268. #error "Multiple defines of BOOST_LAMBDA_POSTFIX_UE"
  269. #endif
  270. #define BOOST_LAMBDA_POSTFIX_UE(OPER_NAME, ACTION) \
  271. template<class Arg> \
  272. inline const \
  273. lambda_functor<lambda_functor_base<ACTION, tuple<lambda_functor<Arg> > > > \
  274. OPER_NAME (const lambda_functor<Arg>& a, int) \
  275. { \
  276. return \
  277. lambda_functor_base<ACTION, tuple<lambda_functor<Arg> > > \
  278. ( tuple<lambda_functor<Arg> >(a) ); \
  279. }
  280. BOOST_LAMBDA_POSTFIX_UE(operator++, post_increment_decrement_action<increment_action>)
  281. BOOST_LAMBDA_POSTFIX_UE(operator--, post_increment_decrement_action<decrement_action>)
  282. #undef BOOST_LAMBDA_UE
  283. #undef BOOST_LAMBDA_POSTFIX_UE
  284. } // namespace lambda
  285. } // namespace boost
  286. #endif