apply_visitor_binary.hpp 8.7 KB

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