apply_visitor_binary.hpp 11 KB

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