apply_visitor_binary.hpp 10 KB

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