user_macros.hpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. // Copyright (C) 2016-2018 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_YAP_USER_MACROS_HPP_INCLUDED
  7. #define BOOST_YAP_USER_MACROS_HPP_INCLUDED
  8. #include <boost/preprocessor/cat.hpp>
  9. #include <boost/preprocessor/repetition/enum_params.hpp>
  10. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  11. #include <boost/preprocessor/repetition/enum.hpp>
  12. #ifndef BOOST_YAP_DOXYGEN
  13. // unary
  14. #define BOOST_YAP_OPERATOR_unary_plus(...) +(__VA_ARGS__)
  15. #define BOOST_YAP_OPERATOR_negate(...) -(__VA_ARGS__)
  16. #define BOOST_YAP_OPERATOR_dereference(...) *(__VA_ARGS__)
  17. #define BOOST_YAP_OPERATOR_complement(...) ~(__VA_ARGS__)
  18. #define BOOST_YAP_OPERATOR_address_of(...) &(__VA_ARGS__)
  19. #define BOOST_YAP_OPERATOR_logical_not(...) !(__VA_ARGS__)
  20. #define BOOST_YAP_OPERATOR_pre_inc(...) ++(__VA_ARGS__)
  21. #define BOOST_YAP_OPERATOR_pre_dec(...) --(__VA_ARGS__)
  22. #define BOOST_YAP_OPERATOR_post_inc(...) ++(__VA_ARGS__, int)
  23. #define BOOST_YAP_OPERATOR_post_dec(...) --(__VA_ARGS__, int)
  24. // binary
  25. #define BOOST_YAP_OPERATOR_shift_left(...) <<(__VA_ARGS__)
  26. #define BOOST_YAP_OPERATOR_shift_right(...) >>(__VA_ARGS__)
  27. #define BOOST_YAP_OPERATOR_multiplies(...) *(__VA_ARGS__)
  28. #define BOOST_YAP_OPERATOR_divides(...) /(__VA_ARGS__)
  29. #define BOOST_YAP_OPERATOR_modulus(...) %(__VA_ARGS__)
  30. #define BOOST_YAP_OPERATOR_plus(...) +(__VA_ARGS__)
  31. #define BOOST_YAP_OPERATOR_minus(...) -(__VA_ARGS__)
  32. #define BOOST_YAP_OPERATOR_less(...) <(__VA_ARGS__)
  33. #define BOOST_YAP_OPERATOR_greater(...) >(__VA_ARGS__)
  34. #define BOOST_YAP_OPERATOR_less_equal(...) <=(__VA_ARGS__)
  35. #define BOOST_YAP_OPERATOR_greater_equal(...) >=(__VA_ARGS__)
  36. #define BOOST_YAP_OPERATOR_equal_to(...) ==(__VA_ARGS__)
  37. #define BOOST_YAP_OPERATOR_not_equal_to(...) !=(__VA_ARGS__)
  38. #define BOOST_YAP_OPERATOR_logical_or(...) ||(__VA_ARGS__)
  39. #define BOOST_YAP_OPERATOR_logical_and(...) &&(__VA_ARGS__)
  40. #define BOOST_YAP_OPERATOR_bitwise_and(...) &(__VA_ARGS__)
  41. #define BOOST_YAP_OPERATOR_bitwise_or(...) |(__VA_ARGS__)
  42. #define BOOST_YAP_OPERATOR_bitwise_xor(...) ^(__VA_ARGS__)
  43. #define BOOST_YAP_OPERATOR_comma(...) ,(__VA_ARGS__)
  44. #define BOOST_YAP_OPERATOR_mem_ptr(...) ->*(__VA_ARGS__)
  45. #define BOOST_YAP_OPERATOR_assign(...) =(__VA_ARGS__)
  46. #define BOOST_YAP_OPERATOR_shift_left_assign(...) <<=(__VA_ARGS__)
  47. #define BOOST_YAP_OPERATOR_shift_right_assign(...) >>=(__VA_ARGS__)
  48. #define BOOST_YAP_OPERATOR_multiplies_assign(...) *=(__VA_ARGS__)
  49. #define BOOST_YAP_OPERATOR_divides_assign(...) /=(__VA_ARGS__)
  50. #define BOOST_YAP_OPERATOR_modulus_assign(...) %=(__VA_ARGS__)
  51. #define BOOST_YAP_OPERATOR_plus_assign(...) +=(__VA_ARGS__)
  52. #define BOOST_YAP_OPERATOR_minus_assign(...) -=(__VA_ARGS__)
  53. #define BOOST_YAP_OPERATOR_bitwise_and_assign(...) &=(__VA_ARGS__)
  54. #define BOOST_YAP_OPERATOR_bitwise_or_assign(...) |=(__VA_ARGS__)
  55. #define BOOST_YAP_OPERATOR_bitwise_xor_assign(...) ^=(__VA_ARGS__)
  56. #define BOOST_YAP_OPERATOR_subscript(...) [](__VA_ARGS__)
  57. #define BOOST_YAP_INDIRECT_CALL(macro) BOOST_PP_CAT(BOOST_YAP_OPERATOR_, macro)
  58. #endif // BOOST_YAP_DOXYGEN
  59. /** Defines operator overloads for unary operator \a op_name that each take an
  60. expression instantiated from \a expr_template and return an expression
  61. instantiated from the \a result_expr_template expression template. One
  62. overload is defined for each of the qualifiers <code>const &</code>,
  63. <code>&</code>, and <code>&&</code>. For the lvalue reference overloads,
  64. the argument is captured by reference into the resulting expression. For
  65. the rvalue reference overload, the argument is moved into the resulting
  66. expression.
  67. Example:
  68. \snippet user_macros_snippets.cpp USER_UNARY_OPERATOR
  69. \param op_name The operator to be overloaded; this must be one of the \b
  70. unary enumerators in <code>expr_kind</code>, without the
  71. <code>expr_kind::</code> qualification.
  72. \param expr_template The expression template to which the overloads apply.
  73. \a expr_template must be an \ref ExpressionTemplate.
  74. \param result_expr_template The expression template to use to instantiate
  75. the result expression. \a result_expr_template must be an \ref
  76. ExpressionTemplate.
  77. */
  78. #define BOOST_YAP_USER_UNARY_OPERATOR( \
  79. op_name, expr_template, result_expr_template) \
  80. template<::boost::yap::expr_kind Kind, typename Tuple> \
  81. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
  82. expr_template<Kind, Tuple> const & x) \
  83. { \
  84. using lhs_type = ::boost::yap::detail::operand_type_t< \
  85. result_expr_template, \
  86. expr_template<Kind, Tuple> const &>; \
  87. using tuple_type = ::boost::hana::tuple<lhs_type>; \
  88. return result_expr_template< \
  89. ::boost::yap::expr_kind::op_name, \
  90. tuple_type>{ \
  91. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}}; \
  92. } \
  93. template<::boost::yap::expr_kind Kind, typename Tuple> \
  94. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
  95. expr_template<Kind, Tuple> & x) \
  96. { \
  97. using lhs_type = ::boost::yap::detail::operand_type_t< \
  98. result_expr_template, \
  99. expr_template<Kind, Tuple> &>; \
  100. using tuple_type = ::boost::hana::tuple<lhs_type>; \
  101. return result_expr_template< \
  102. ::boost::yap::expr_kind::op_name, \
  103. tuple_type>{ \
  104. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}}; \
  105. } \
  106. template<::boost::yap::expr_kind Kind, typename Tuple> \
  107. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
  108. expr_template<Kind, Tuple> && x) \
  109. { \
  110. using tuple_type = ::boost::hana::tuple<expr_template<Kind, Tuple>>; \
  111. return result_expr_template< \
  112. ::boost::yap::expr_kind::op_name, \
  113. tuple_type>{tuple_type{std::move(x)}}; \
  114. }
  115. /** Defines operator overloads for binary operator \a op_name that each
  116. produce an expression instantiated from the \a expr_template expression
  117. template. One overload is defined for each of the qualifiers <code>const
  118. &</code>, <code>&</code>, and <code>&&</code>. For the lvalue reference
  119. overloads, <code>*this</code> is captured by reference into the resulting
  120. expression. For the rvalue reference overload, <code>*this</code> is
  121. moved into the resulting expression.
  122. Note that this does not work for yap::expr_kinds assign, subscript, or
  123. call. Use BOOST_YAP_USER_ASSIGN_OPERATOR,
  124. BOOST_YAP_USER_SUBSCRIPT_OPERATOR, or BOOST_YAP_USER_CALL_OPERATOR for
  125. those, respectively.
  126. Example:
  127. \snippet user_macros_snippets.cpp USER_BINARY_OPERATOR
  128. \param op_name The operator to be overloaded; this must be one of the \b
  129. binary enumerators in <code>expr_kind</code>, except assign, subscript, or
  130. call, without the <code>expr_kind::</code> qualification.
  131. \param expr_template The expression template to which the overloads apply.
  132. \a expr_template must be an \ref ExpressionTemplate.
  133. \param result_expr_template The expression template to use to instantiate
  134. the result expression. \a result_expr_template must be an \ref
  135. ExpressionTemplate.
  136. */
  137. #define BOOST_YAP_USER_BINARY_OPERATOR( \
  138. op_name, expr_template, result_expr_template) \
  139. template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \
  140. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
  141. expr_template<Kind, Tuple> const & lhs, Expr && rhs) \
  142. { \
  143. using lhs_type = ::boost::yap::detail::operand_type_t< \
  144. result_expr_template, \
  145. expr_template<Kind, Tuple> const &>; \
  146. using rhs_type = \
  147. ::boost::yap::detail::operand_type_t<result_expr_template, Expr>; \
  148. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  149. return result_expr_template< \
  150. ::boost::yap::expr_kind::op_name, \
  151. tuple_type>{ \
  152. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs), \
  153. ::boost::yap::detail::make_operand<rhs_type>{}( \
  154. static_cast<Expr &&>(rhs))}}; \
  155. } \
  156. template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \
  157. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
  158. expr_template<Kind, Tuple> & lhs, Expr && rhs) \
  159. { \
  160. using lhs_type = ::boost::yap::detail::operand_type_t< \
  161. result_expr_template, \
  162. expr_template<Kind, Tuple> &>; \
  163. using rhs_type = \
  164. ::boost::yap::detail::operand_type_t<result_expr_template, Expr>; \
  165. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  166. return result_expr_template< \
  167. ::boost::yap::expr_kind::op_name, \
  168. tuple_type>{ \
  169. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs), \
  170. ::boost::yap::detail::make_operand<rhs_type>{}( \
  171. static_cast<Expr &&>(rhs))}}; \
  172. } \
  173. template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \
  174. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
  175. expr_template<Kind, Tuple> && lhs, Expr && rhs) \
  176. { \
  177. using lhs_type = ::boost::yap::detail::remove_cv_ref_t< \
  178. expr_template<Kind, Tuple> &&>; \
  179. using rhs_type = \
  180. ::boost::yap::detail::operand_type_t<result_expr_template, Expr>; \
  181. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  182. return result_expr_template< \
  183. ::boost::yap::expr_kind::op_name, \
  184. tuple_type>{ \
  185. tuple_type{std::move(lhs), \
  186. ::boost::yap::detail::make_operand<rhs_type>{}( \
  187. static_cast<Expr &&>(rhs))}}; \
  188. } \
  189. template<typename T, ::boost::yap::expr_kind Kind, typename Tuple> \
  190. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
  191. T && lhs, expr_template<Kind, Tuple> && rhs) \
  192. ->::boost::yap::detail::free_binary_op_result_t< \
  193. result_expr_template, \
  194. ::boost::yap::expr_kind::op_name, \
  195. T, \
  196. expr_template<Kind, Tuple> &&> \
  197. { \
  198. using result_types = ::boost::yap::detail::free_binary_op_result< \
  199. result_expr_template, \
  200. ::boost::yap::expr_kind::op_name, \
  201. T, \
  202. expr_template<Kind, Tuple> &&>; \
  203. using lhs_type = typename result_types::lhs_type; \
  204. using rhs_type = typename result_types::rhs_type; \
  205. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  206. return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, std::move(rhs)}}; \
  207. } \
  208. template<typename T, ::boost::yap::expr_kind Kind, typename Tuple> \
  209. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
  210. T && lhs, expr_template<Kind, Tuple> const & rhs) \
  211. ->::boost::yap::detail::free_binary_op_result_t< \
  212. result_expr_template, \
  213. ::boost::yap::expr_kind::op_name, \
  214. T, \
  215. expr_template<Kind, Tuple> const &> \
  216. { \
  217. using result_types = ::boost::yap::detail::free_binary_op_result< \
  218. result_expr_template, \
  219. ::boost::yap::expr_kind::op_name, \
  220. T, \
  221. expr_template<Kind, Tuple> const &>; \
  222. using lhs_type = typename result_types::lhs_type; \
  223. using rhs_type = typename result_types::rhs_type; \
  224. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  225. using rhs_tuple_type = typename result_types::rhs_tuple_type; \
  226. return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, \
  227. rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \
  228. } \
  229. template<typename T, ::boost::yap::expr_kind Kind, typename Tuple> \
  230. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
  231. T && lhs, expr_template<Kind, Tuple> & rhs) \
  232. ->::boost::yap::detail::free_binary_op_result_t< \
  233. result_expr_template, \
  234. ::boost::yap::expr_kind::op_name, \
  235. T, \
  236. expr_template<Kind, Tuple> &> \
  237. { \
  238. using result_types = ::boost::yap::detail::free_binary_op_result< \
  239. result_expr_template, \
  240. ::boost::yap::expr_kind::op_name, \
  241. T, \
  242. expr_template<Kind, Tuple> &>; \
  243. using lhs_type = typename result_types::lhs_type; \
  244. using rhs_type = typename result_types::rhs_type; \
  245. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  246. using rhs_tuple_type = typename result_types::rhs_tuple_type; \
  247. return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, \
  248. rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \
  249. }
  250. /** Defines operator overloads for \a operator=() that each produce an
  251. expression instantiated from the \a expr_template expression template.
  252. One overload is defined for each of the qualifiers <code>const &</code>,
  253. <code>&</code>, and <code>&&</code>. For the lvalue reference overloads,
  254. <code>*this</code> is captured by reference into the resulting expression.
  255. For the rvalue reference overload, <code>*this</code> is moved into the
  256. resulting expression.
  257. The \a rhs parameter to each of the defined overloads may be any type,
  258. including an expression, except that the overloads are constrained by
  259. std::enable_if<> not to conflict with the assignment and move assignement
  260. operators. If \a rhs is a non-expression, it is wrapped in a terminal
  261. expression.
  262. Example:
  263. \snippet user_macros_snippets.cpp USER_ASSIGN_OPERATOR
  264. \param this_type The type of the class the operator is a member of; this
  265. is required to avoid clashing with the assignment and move assignement
  266. operators.
  267. \param expr_template The expression template to use to instantiate the
  268. result expression. \a expr_template must be an \ref
  269. ExpressionTemplate.
  270. */
  271. #define BOOST_YAP_USER_ASSIGN_OPERATOR(this_type, expr_template) \
  272. template< \
  273. typename Expr, \
  274. typename = std::enable_if_t< \
  275. !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>> \
  276. constexpr auto operator=(Expr && rhs) const & \
  277. { \
  278. using lhs_type = ::boost::yap::detail:: \
  279. operand_type_t<expr_template, this_type const &>; \
  280. using rhs_type = \
  281. ::boost::yap::detail::operand_type_t<expr_template, Expr>; \
  282. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  283. return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \
  284. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
  285. ::boost::yap::detail::make_operand<rhs_type>{}( \
  286. static_cast<Expr &&>(rhs))}}; \
  287. } \
  288. template< \
  289. typename Expr, \
  290. typename = std::enable_if_t< \
  291. !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>> \
  292. constexpr auto operator=(Expr && rhs) & \
  293. { \
  294. using lhs_type = ::boost::yap::detail:: \
  295. operand_type_t<expr_template, decltype(*this)>; \
  296. using rhs_type = \
  297. ::boost::yap::detail::operand_type_t<expr_template, Expr>; \
  298. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  299. return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \
  300. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
  301. ::boost::yap::detail::make_operand<rhs_type>{}( \
  302. static_cast<Expr &&>(rhs))}}; \
  303. } \
  304. template< \
  305. typename Expr, \
  306. typename = std::enable_if_t< \
  307. !::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>> \
  308. constexpr auto operator=(Expr && rhs) && \
  309. { \
  310. using rhs_type = \
  311. ::boost::yap::detail::operand_type_t<expr_template, Expr>; \
  312. using tuple_type = ::boost::hana::tuple<this_type, rhs_type>; \
  313. return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \
  314. tuple_type{std::move(*this), \
  315. ::boost::yap::detail::make_operand<rhs_type>{}( \
  316. static_cast<Expr &&>(rhs))}}; \
  317. }
  318. /** Defines operator overloads for \a operator[]() that each produce an
  319. expression instantiated from the \a expr_template expression template.
  320. One overload is defined for each of the qualifiers <code>const &</code>,
  321. <code>&</code>, and <code>&&</code>. For the lvalue reference overloads,
  322. <code>*this</code> is captured by reference into the resulting expression.
  323. For the rvalue reference overload, <code>*this</code> is moved into the
  324. resulting expression.
  325. The \a rhs parameter to each of the defined overloads may be any type,
  326. including an expression, except that the overloads are constrained by
  327. std::enable_if<> not to conflict with the assignment and move assignement
  328. operators. If \a rhs is a non-expression, it is wrapped in a terminal
  329. expression.
  330. Example:
  331. \snippet user_macros_snippets.cpp USER_SUBSCRIPT_OPERATOR
  332. \param expr_template The expression template to use to instantiate the
  333. result expression. \a expr_template must be an \ref
  334. ExpressionTemplate.
  335. */
  336. #define BOOST_YAP_USER_SUBSCRIPT_OPERATOR(expr_template) \
  337. template<typename Expr> \
  338. constexpr auto operator[](Expr && rhs) const & \
  339. { \
  340. using lhs_type = ::boost::yap::detail:: \
  341. operand_type_t<expr_template, decltype(*this)>; \
  342. using rhs_type = \
  343. ::boost::yap::detail::operand_type_t<expr_template, Expr>; \
  344. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  345. return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \
  346. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
  347. ::boost::yap::detail::make_operand<rhs_type>{}( \
  348. static_cast<Expr &&>(rhs))}}; \
  349. } \
  350. template<typename Expr> \
  351. constexpr auto operator[](Expr && rhs) & \
  352. { \
  353. using lhs_type = ::boost::yap::detail:: \
  354. operand_type_t<expr_template, decltype(*this)>; \
  355. using rhs_type = \
  356. ::boost::yap::detail::operand_type_t<expr_template, Expr>; \
  357. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  358. return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \
  359. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
  360. ::boost::yap::detail::make_operand<rhs_type>{}( \
  361. static_cast<Expr &&>(rhs))}}; \
  362. } \
  363. template<typename Expr> \
  364. constexpr auto operator[](Expr && rhs) && \
  365. { \
  366. using lhs_type = \
  367. ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>; \
  368. using rhs_type = \
  369. ::boost::yap::detail::operand_type_t<expr_template, Expr>; \
  370. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  371. return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \
  372. tuple_type{std::move(*this), \
  373. ::boost::yap::detail::make_operand<rhs_type>{}( \
  374. static_cast<Expr &&>(rhs))}}; \
  375. }
  376. /** Defines operator overloads for the call operator taking any number of
  377. parameters ("operator()") that each produce an expression instantiated
  378. from the \a expr_template expression template. One overload is defined
  379. for each of the qualifiers <code>const &</code>, <code>&</code>, and
  380. <code>&&</code>. For the lvalue reference overloads, <code>*this</code>
  381. is captured by reference into the resulting expression. For the rvalue
  382. reference overload, <code>*this</code> is moved into the resulting
  383. expression.
  384. The \a u parameters to each of the defined overloads may be any type,
  385. including an expression. Each non-expression is wrapped in a terminal
  386. expression.
  387. Example:
  388. \snippet user_macros_snippets.cpp USER_CALL_OPERATOR
  389. \param expr_template The expression template to use to instantiate the
  390. result expression. \a expr_template must be an \ref
  391. ExpressionTemplate.
  392. */
  393. #define BOOST_YAP_USER_CALL_OPERATOR(expr_template) \
  394. template<typename... U> \
  395. constexpr auto operator()(U &&... u) const & \
  396. { \
  397. using lhs_type = ::boost::yap::detail:: \
  398. operand_type_t<expr_template, decltype(*this)>; \
  399. using tuple_type = ::boost::hana::tuple< \
  400. lhs_type, \
  401. ::boost::yap::detail::operand_type_t<expr_template, U>...>; \
  402. return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
  403. tuple_type{ \
  404. ::boost::yap::detail::make_operand<lhs_type>{}(*this), \
  405. ::boost::yap::detail::make_operand< \
  406. ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
  407. static_cast<U &&>(u))...}}; \
  408. } \
  409. template<typename... U> \
  410. constexpr auto operator()(U &&... u) & \
  411. { \
  412. using lhs_type = ::boost::yap::detail:: \
  413. operand_type_t<expr_template, decltype(*this)>; \
  414. using tuple_type = ::boost::hana::tuple< \
  415. lhs_type, \
  416. ::boost::yap::detail::operand_type_t<expr_template, U>...>; \
  417. return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
  418. tuple_type{ \
  419. ::boost::yap::detail::make_operand<lhs_type>{}(*this), \
  420. ::boost::yap::detail::make_operand< \
  421. ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
  422. static_cast<U &&>(u))...}}; \
  423. } \
  424. template<typename... U> \
  425. constexpr auto operator()(U &&... u) && \
  426. { \
  427. using this_type = \
  428. ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>; \
  429. using tuple_type = ::boost::hana::tuple< \
  430. this_type, \
  431. ::boost::yap::detail::operand_type_t<expr_template, U>...>; \
  432. return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
  433. tuple_type{ \
  434. std::move(*this), \
  435. ::boost::yap::detail::make_operand< \
  436. ::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
  437. static_cast<U &&>(u))...}}; \
  438. }
  439. #ifndef BOOST_YAP_DOXYGEN
  440. #define BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T(z, n, expr_template) \
  441. ::boost::yap::detail::operand_type_t<expr_template, BOOST_PP_CAT(U, n)>
  442. #define BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND(z, n, expr_template) \
  443. ::boost::yap::detail::make_operand<::boost::yap::detail::operand_type_t< \
  444. expr_template, \
  445. BOOST_PP_CAT(U, n)>>{}( \
  446. static_cast<BOOST_PP_CAT(U, n) &&>(BOOST_PP_CAT(u, n)))
  447. #endif
  448. /** Defines operator overloads for the call operator taking N parameters
  449. ("operator()(t0, t1, ... tn-1)") that each produce an expression
  450. instantiated from the \a expr_template expression template. One overload
  451. is defined for each of the qualifiers <code>const &</code>,
  452. <code>&</code>, and <code>&&</code>. For the lvalue reference overloads,
  453. <code>*this</code> is captured by reference into the resulting expression.
  454. For the rvalue reference overload, <code>*this</code> is moved into the
  455. resulting expression.
  456. The \a u parameters to each of the defined overloads may be any type,
  457. including an expression. Each non-expression is wrapped in a terminal
  458. expression.
  459. Example:
  460. \snippet user_macros_snippets.cpp USER_CALL_OPERATOR
  461. \param expr_template The expression template to use to instantiate the
  462. result expression. \a expr_template must be an \ref
  463. ExpressionTemplate.
  464. \param n The number of parameters accepted by the operator() overloads. n
  465. must be <= BOOST_PP_LIMIT_REPEAT.
  466. */
  467. #define BOOST_YAP_USER_CALL_OPERATOR_N(expr_template, n) \
  468. template<BOOST_PP_ENUM_PARAMS(n, typename U)> \
  469. constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) const & \
  470. { \
  471. using lhs_type = ::boost::yap::detail:: \
  472. operand_type_t<expr_template, decltype(*this)>; \
  473. using tuple_type = ::boost::hana::tuple< \
  474. lhs_type, \
  475. BOOST_PP_ENUM( \
  476. n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \
  477. return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
  478. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
  479. BOOST_PP_ENUM( \
  480. n, \
  481. BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \
  482. expr_template)}}; \
  483. } \
  484. template<BOOST_PP_ENUM_PARAMS(n, typename U)> \
  485. constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) & \
  486. { \
  487. using lhs_type = ::boost::yap::detail:: \
  488. operand_type_t<expr_template, decltype(*this)>; \
  489. using tuple_type = ::boost::hana::tuple< \
  490. lhs_type, \
  491. BOOST_PP_ENUM( \
  492. n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \
  493. return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
  494. tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
  495. BOOST_PP_ENUM( \
  496. n, \
  497. BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \
  498. expr_template)}}; \
  499. } \
  500. template<BOOST_PP_ENUM_PARAMS(n, typename U)> \
  501. constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) && \
  502. { \
  503. using this_type = \
  504. ::boost::yap::detail::remove_cv_ref_t<decltype(*this)>; \
  505. using tuple_type = ::boost::hana::tuple< \
  506. this_type, \
  507. BOOST_PP_ENUM( \
  508. n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \
  509. return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
  510. tuple_type{std::move(*this), \
  511. BOOST_PP_ENUM( \
  512. n, \
  513. BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \
  514. expr_template)}}; \
  515. }
  516. /** Defines a 3-parameter function <code>if_else()</code> that acts as an
  517. analogue to the ternary operator (<code>?:</code>), since the ternary
  518. operator is not user-overloadable. The return type of
  519. <code>if_else()</code> is an expression instantiated from the \a
  520. expr_template expression template.
  521. At least one parameter to <code>if_else()</code> must be an expression.
  522. For each parameter E passed to <code>if_else()</code>, if E is an rvalue,
  523. E is moved into the result, and otherwise E is captured by reference into
  524. the result.
  525. Example:
  526. \snippet user_macros_snippets.cpp USER_EXPR_IF_ELSE
  527. \param expr_template The expression template to use to instantiate the
  528. result expression. \a expr_template must be an \ref
  529. ExpressionTemplate.
  530. */
  531. #define BOOST_YAP_USER_EXPR_IF_ELSE(expr_template) \
  532. template<typename Expr1, typename Expr2, typename Expr3> \
  533. constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \
  534. ->::boost::yap::detail:: \
  535. ternary_op_result_t<expr_template, Expr1, Expr2, Expr3> \
  536. { \
  537. using result_types = ::boost::yap::detail:: \
  538. ternary_op_result<expr_template, Expr1, Expr2, Expr3>; \
  539. using cond_type = typename result_types::cond_type; \
  540. using then_type = typename result_types::then_type; \
  541. using else_type = typename result_types::else_type; \
  542. using tuple_type = \
  543. ::boost::hana::tuple<cond_type, then_type, else_type>; \
  544. return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}( \
  545. static_cast<Expr1 &&>(expr1)), \
  546. ::boost::yap::detail::make_operand<then_type>{}( \
  547. static_cast<Expr2 &&>(expr2)), \
  548. ::boost::yap::detail::make_operand<else_type>{}( \
  549. static_cast<Expr3 &&>(expr3))}}; \
  550. }
  551. /** Defines a function <code>if_else()</code> that acts as an analogue to the
  552. ternary operator (<code>?:</code>), since the ternary operator is not
  553. user-overloadable. The return type of <code>if_else()</code> is an
  554. expression instantiated from the \a expr_template expression template.
  555. Each parameter to <code>if_else()</code> may be any type that is \b not an
  556. expression. At least on parameter must be a type <code>T</code> for which
  557. \code udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value
  558. \endcode is true. Each parameter is wrapped in a terminal expression.
  559. Example:
  560. \snippet user_macros_snippets.cpp USER_UDT_ANY_IF_ELSE
  561. \param expr_template The expression template to use to instantiate the
  562. result expression. \a expr_template must be an \ref
  563. ExpressionTemplate.
  564. \param udt_trait A trait template to use to constrain which types are
  565. accepted as template parameters to <code>if_else()</code>.
  566. */
  567. #define BOOST_YAP_USER_UDT_ANY_IF_ELSE(expr_template, udt_trait) \
  568. template<typename Expr1, typename Expr2, typename Expr3> \
  569. constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \
  570. ->::boost::yap::detail::udt_any_ternary_op_result_t< \
  571. expr_template, \
  572. Expr1, \
  573. Expr2, \
  574. Expr3, \
  575. udt_trait> \
  576. { \
  577. using result_types = ::boost::yap::detail::udt_any_ternary_op_result< \
  578. expr_template, \
  579. Expr1, \
  580. Expr2, \
  581. Expr3, \
  582. udt_trait>; \
  583. using cond_type = typename result_types::cond_type; \
  584. using then_type = typename result_types::then_type; \
  585. using else_type = typename result_types::else_type; \
  586. using tuple_type = \
  587. ::boost::hana::tuple<cond_type, then_type, else_type>; \
  588. return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}( \
  589. static_cast<Expr1 &&>(expr1)), \
  590. ::boost::yap::detail::make_operand<then_type>{}( \
  591. static_cast<Expr2 &&>(expr2)), \
  592. ::boost::yap::detail::make_operand<else_type>{}( \
  593. static_cast<Expr3 &&>(expr3))}}; \
  594. }
  595. /** Defines a free/non-member operator overload for unary operator \a op_name
  596. that produces an expression instantiated from the \a expr_template
  597. expression template.
  598. The parameter to the defined operator overload may be any type that is \b
  599. not an expression and for which \code
  600. udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
  601. true. The parameter is wrapped in a terminal expression.
  602. Example:
  603. \snippet user_macros_snippets.cpp USER_UDT_UNARY_OPERATOR
  604. \param op_name The operator to be overloaded; this must be one of the \b
  605. unary enumerators in <code>expr_kind</code>, without the
  606. <code>expr_kind::</code> qualification.
  607. \param expr_template The expression template to use to instantiate the
  608. result expression. \a expr_template must be an \ref
  609. ExpressionTemplate.
  610. \param udt_trait A trait template to use to constrain which types are
  611. accepted as template parameters to the defined operator overload.
  612. */
  613. #define BOOST_YAP_USER_UDT_UNARY_OPERATOR(op_name, expr_template, udt_trait) \
  614. template<typename T> \
  615. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && x) \
  616. ->::boost::yap::detail::udt_unary_op_result_t< \
  617. expr_template, \
  618. ::boost::yap::expr_kind::op_name, \
  619. T, \
  620. udt_trait> \
  621. { \
  622. using result_types = ::boost::yap::detail::udt_unary_op_result< \
  623. expr_template, \
  624. ::boost::yap::expr_kind::op_name, \
  625. T, \
  626. udt_trait>; \
  627. using x_type = typename result_types::x_type; \
  628. using tuple_type = ::boost::hana::tuple<x_type>; \
  629. return {tuple_type{x_type{static_cast<T &&>(x)}}}; \
  630. }
  631. /** Defines a free/non-member operator overload for binary operator \a op_name
  632. that produces an expression instantiated from the \a expr_template
  633. expression template.
  634. The \a lhs parameter to the defined operator overload may be any type that
  635. is \b not an expression and for which \code
  636. t_udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
  637. true. The parameter is wrapped in a terminal expression.
  638. The \a rhs parameter to the defined operator overload may be any type that
  639. is \b not an expression and for which \code
  640. u_udt_trait<std::remove_cv_t<std::remove_reference_t<U>>>::value \endcode is
  641. true. The parameter is wrapped in a terminal expression.
  642. Example:
  643. \snippet user_macros_snippets.cpp USER_UDT_UDT_BINARY_OPERATOR
  644. \param op_name The operator to be overloaded; this must be one of the \b
  645. binary enumerators in <code>expr_kind</code>, without the
  646. <code>expr_kind::</code> qualification.
  647. \param expr_template The expression template to use to instantiate the
  648. result expression. \a expr_template must be an \ref
  649. ExpressionTemplate.
  650. \param t_udt_trait A trait template to use to constrain which types are
  651. accepted as \a T template parameters to the defined operator overload.
  652. \param u_udt_trait A trait template to use to constrain which types are
  653. accepted as \a U template parameters to the defined operator overload.
  654. */
  655. #define BOOST_YAP_USER_UDT_UDT_BINARY_OPERATOR( \
  656. op_name, expr_template, t_udt_trait, u_udt_trait) \
  657. template<typename T, typename U> \
  658. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \
  659. ->::boost::yap::detail::udt_udt_binary_op_result_t< \
  660. expr_template, \
  661. ::boost::yap::expr_kind::op_name, \
  662. T, \
  663. U, \
  664. t_udt_trait, \
  665. u_udt_trait> \
  666. { \
  667. using result_types = ::boost::yap::detail::udt_udt_binary_op_result< \
  668. expr_template, \
  669. ::boost::yap::expr_kind::op_name, \
  670. T, \
  671. U, \
  672. t_udt_trait, \
  673. u_udt_trait>; \
  674. using lhs_type = typename result_types::lhs_type; \
  675. using rhs_type = typename result_types::rhs_type; \
  676. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  677. return {tuple_type{ \
  678. lhs_type{static_cast<T &&>(lhs)}, \
  679. rhs_type{static_cast<U &&>(rhs)}, \
  680. }}; \
  681. }
  682. /** Defines a free/non-member operator overload for binary operator \a op_name
  683. that produces an expression instantiated from the \a expr_template
  684. expression template.
  685. The \a lhs and \a rhs parameters to the defined operator overload may be any
  686. types that are \b not expressions. Each parameter is wrapped in a terminal
  687. expression.
  688. At least one of the parameters to the defined operator overload must be a
  689. type \c T for which \code
  690. udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
  691. true.
  692. Example:
  693. \snippet user_macros_snippets.cpp USER_UDT_ANY_BINARY_OPERATOR
  694. \param op_name The operator to be overloaded; this must be one of the \b
  695. binary enumerators in <code>expr_kind</code>, without the
  696. <code>expr_kind::</code> qualification.
  697. \param expr_template The expression template to use to instantiate the
  698. result expression. \a expr_template must be an \ref
  699. ExpressionTemplate.
  700. \param udt_trait A trait template to use to constrain which types are
  701. accepted as template parameters to the defined operator overload.
  702. */
  703. #define BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( \
  704. op_name, expr_template, udt_trait) \
  705. template<typename T, typename U> \
  706. constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \
  707. ->::boost::yap::detail::udt_any_binary_op_result_t< \
  708. expr_template, \
  709. ::boost::yap::expr_kind::op_name, \
  710. T, \
  711. U, \
  712. udt_trait> \
  713. { \
  714. using result_types = ::boost::yap::detail::udt_any_binary_op_result< \
  715. expr_template, \
  716. ::boost::yap::expr_kind::op_name, \
  717. T, \
  718. U, \
  719. udt_trait>; \
  720. using lhs_type = typename result_types::lhs_type; \
  721. using rhs_type = typename result_types::rhs_type; \
  722. using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
  723. return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, \
  724. rhs_type{static_cast<U &&>(rhs)}}}; \
  725. }
  726. /** Defines user defined literal template that creates literal placeholders
  727. instantiated from the \a expr_template expression template. It is
  728. recommended that you put this in its own namespace.
  729. \param expr_template The expression template to use to instantiate the
  730. result expression. \a expr_template must be an \ref
  731. ExpressionTemplate.
  732. */
  733. #define BOOST_YAP_USER_LITERAL_PLACEHOLDER_OPERATOR(expr_template) \
  734. template<char... c> \
  735. constexpr auto operator"" _p() \
  736. { \
  737. using i = ::boost::hana::llong< \
  738. ::boost::hana::ic_detail::parse<sizeof...(c)>({c...})>; \
  739. static_assert(1 <= i::value, "Placeholders must be >= 1."); \
  740. return expr_template< \
  741. ::boost::yap::expr_kind::terminal, \
  742. ::boost::hana::tuple<::boost::yap::placeholder<i::value>>>{}; \
  743. }
  744. #endif