apply_visitor_binary.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. //-----------------------------------------------------------------------------
  2. // boost variant/detail/apply_visitor_binary.hpp header file
  3. // See http://www.boost.org for updates, documentation, and revision history.
  4. //-----------------------------------------------------------------------------
  5. //
  6. // Copyright (c) 2002-2003 Eric Friedman
  7. // Copyright (c) 2014-2020 Antony Polukhin
  8. //
  9. // Distributed under the Boost Software License, Version 1.0. (See
  10. // accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt)
  12. #ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
  13. #define BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
  14. #include <boost/config.hpp>
  15. #include <boost/variant/detail/apply_visitor_unary.hpp>
  16. #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  17. # include <boost/variant/detail/has_result_type.hpp>
  18. #endif
  19. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  20. # include <boost/core/enable_if.hpp>
  21. # include <boost/type_traits/is_lvalue_reference.hpp>
  22. # include <boost/type_traits/is_same.hpp>
  23. # include <boost/move/utility_core.hpp> // for boost::move, boost::forward
  24. #endif
  25. namespace boost {
  26. //////////////////////////////////////////////////////////////////////////
  27. // function template apply_visitor(visitor, visitable1, visitable2)
  28. //
  29. // Visits visitable1 and visitable2 such that their values (which we
  30. // shall call x and y, respectively) are used as arguments in the
  31. // expression visitor(x, y).
  32. //
  33. namespace detail { namespace variant {
  34. template <typename Visitor, typename Value1, bool MoveSemantics>
  35. class apply_visitor_binary_invoke
  36. {
  37. public: // visitor typedefs
  38. typedef typename Visitor::result_type
  39. result_type;
  40. private: // representation
  41. Visitor& visitor_;
  42. Value1& value1_;
  43. public: // structors
  44. apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
  45. : visitor_(visitor)
  46. , value1_(value1)
  47. {
  48. }
  49. public: // visitor interfaces
  50. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  51. template <typename Value2>
  52. typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value, result_type>::type
  53. operator()(Value2&& value2)
  54. {
  55. return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
  56. }
  57. template <typename Value2>
  58. typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value, result_type>::type
  59. operator()(Value2&& value2)
  60. {
  61. return visitor_(value1_, ::boost::forward<Value2>(value2));
  62. }
  63. #else
  64. template <typename Value2>
  65. result_type
  66. operator()(Value2& value2)
  67. {
  68. return visitor_(value1_, value2);
  69. }
  70. #endif
  71. private:
  72. apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
  73. };
  74. template <typename Visitor, typename Visitable2, bool MoveSemantics>
  75. class apply_visitor_binary_unwrap
  76. {
  77. public: // visitor typedefs
  78. typedef typename Visitor::result_type
  79. result_type;
  80. private: // representation
  81. Visitor& visitor_;
  82. Visitable2& visitable2_;
  83. public: // structors
  84. apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
  85. : visitor_(visitor)
  86. , visitable2_(visitable2)
  87. {
  88. }
  89. public: // visitor interfaces
  90. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  91. template <typename Value1>
  92. typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value, result_type>::type
  93. operator()(Value1&& value1)
  94. {
  95. apply_visitor_binary_invoke<
  96. Visitor
  97. , Value1
  98. , ! ::boost::is_lvalue_reference<Value1>::value
  99. > invoker(visitor_, value1);
  100. return boost::apply_visitor(invoker, ::boost::move(visitable2_));
  101. }
  102. template <typename Value1>
  103. typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value, result_type>::type
  104. operator()(Value1&& value1)
  105. {
  106. apply_visitor_binary_invoke<
  107. Visitor
  108. , Value1
  109. , ! ::boost::is_lvalue_reference<Value1>::value
  110. > invoker(visitor_, value1);
  111. return boost::apply_visitor(invoker, visitable2_);
  112. }
  113. #else
  114. template <typename Value1>
  115. result_type
  116. operator()(Value1& value1)
  117. {
  118. apply_visitor_binary_invoke<
  119. Visitor
  120. , Value1
  121. , false
  122. > invoker(visitor_, value1);
  123. return boost::apply_visitor(invoker, visitable2_);
  124. }
  125. #endif
  126. private:
  127. apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&);
  128. };
  129. }} // namespace detail::variant
  130. //
  131. // nonconst-visitor version:
  132. //
  133. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  134. template <typename Visitor, typename Visitable1, typename Visitable2>
  135. inline typename Visitor::result_type
  136. apply_visitor( Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2)
  137. {
  138. ::boost::detail::variant::apply_visitor_binary_unwrap<
  139. Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
  140. > unwrapper(visitor, visitable2);
  141. return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
  142. }
  143. #else
  144. template <typename Visitor, typename Visitable1, typename Visitable2>
  145. inline typename Visitor::result_type
  146. apply_visitor( Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2)
  147. {
  148. ::boost::detail::variant::apply_visitor_binary_unwrap<
  149. Visitor, Visitable2, false
  150. > unwrapper(visitor, visitable2);
  151. return boost::apply_visitor(unwrapper, visitable1);
  152. }
  153. #endif
  154. //
  155. // const-visitor version:
  156. //
  157. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  158. template <typename Visitor, typename Visitable1, typename Visitable2>
  159. inline typename Visitor::result_type
  160. apply_visitor( const Visitor& visitor , Visitable1&& visitable1 , Visitable2&& visitable2)
  161. {
  162. ::boost::detail::variant::apply_visitor_binary_unwrap<
  163. const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
  164. > unwrapper(visitor, visitable2);
  165. return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
  166. }
  167. #else
  168. template <typename Visitor, typename Visitable1, typename Visitable2>
  169. inline typename Visitor::result_type
  170. apply_visitor( const Visitor& visitor , Visitable1& visitable1 , Visitable2& visitable2)
  171. {
  172. ::boost::detail::variant::apply_visitor_binary_unwrap<
  173. const Visitor, Visitable2, false
  174. > unwrapper(visitor, visitable2);
  175. return boost::apply_visitor(unwrapper, visitable1);
  176. }
  177. #endif
  178. #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  179. //////////////////////////////////////////////////////////////////////////
  180. // function template apply_visitor(visitor, visitable1, visitable2)
  181. //
  182. // C++14 part.
  183. //
  184. namespace detail { namespace variant {
  185. template <typename Visitor, typename Value1, bool MoveSemantics>
  186. class apply_visitor_binary_invoke_cpp14
  187. {
  188. Visitor& visitor_;
  189. Value1& value1_;
  190. public: // structors
  191. apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
  192. : visitor_(visitor)
  193. , value1_(value1)
  194. {
  195. }
  196. public: // visitor interfaces
  197. template <typename Value2>
  198. decltype(auto) operator()(Value2&& value2, typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value, bool>::type = true)
  199. {
  200. return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
  201. }
  202. template <typename Value2>
  203. decltype(auto) operator()(Value2&& value2, typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value, bool>::type = true)
  204. {
  205. return visitor_(value1_, ::boost::forward<Value2>(value2));
  206. }
  207. private:
  208. apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
  209. };
  210. template <typename Visitor, typename Visitable2, bool MoveSemantics>
  211. class apply_visitor_binary_unwrap_cpp14
  212. {
  213. Visitor& visitor_;
  214. Visitable2& visitable2_;
  215. public: // structors
  216. apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
  217. : visitor_(visitor)
  218. , visitable2_(visitable2)
  219. {
  220. }
  221. public: // visitor interfaces
  222. template <typename Value1>
  223. decltype(auto) operator()(Value1&& value1, typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value, bool>::type = true)
  224. {
  225. apply_visitor_binary_invoke_cpp14<
  226. Visitor
  227. , Value1
  228. , ! ::boost::is_lvalue_reference<Value1>::value
  229. > invoker(visitor_, value1);
  230. return boost::apply_visitor(invoker, ::boost::move(visitable2_));
  231. }
  232. template <typename Value1>
  233. decltype(auto) operator()(Value1&& value1, typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value, bool>::type = true)
  234. {
  235. apply_visitor_binary_invoke_cpp14<
  236. Visitor
  237. , Value1
  238. , ! ::boost::is_lvalue_reference<Value1>::value
  239. > invoker(visitor_, value1);
  240. return boost::apply_visitor(invoker, visitable2_);
  241. }
  242. private:
  243. apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&);
  244. };
  245. }} // namespace detail::variant
  246. template <typename Visitor, typename Visitable1, typename Visitable2>
  247. inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
  248. typename boost::disable_if<
  249. boost::detail::variant::has_result_type<Visitor>,
  250. bool
  251. >::type = true)
  252. {
  253. ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
  254. Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
  255. > unwrapper(visitor, visitable2);
  256. return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
  257. }
  258. template <typename Visitor, typename Visitable1, typename Visitable2>
  259. inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
  260. typename boost::disable_if<
  261. boost::detail::variant::has_result_type<Visitor>,
  262. bool
  263. >::type = true)
  264. {
  265. ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
  266. const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
  267. > unwrapper(visitor, visitable2);
  268. return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
  269. }
  270. #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
  271. } // namespace boost
  272. #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP