multivisitors_cpp11_based.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // Boost.Varaint
  2. // Contains multivisitors that are implemented via variadic templates and std::tuple
  3. //
  4. // See http://www.boost.org for most recent version, including documentation.
  5. //
  6. // Copyright Antony Polukhin, 2013-2024.
  7. //
  8. // Distributed under the Boost
  9. // Software License, Version 1.0. (See accompanying file
  10. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
  11. #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
  12. #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
  13. #if defined(_MSC_VER)
  14. # pragma once
  15. #endif
  16. #include <boost/variant/detail/apply_visitor_unary.hpp>
  17. #include <boost/variant/variant_fwd.hpp>
  18. #include <boost/type_traits/is_lvalue_reference.hpp>
  19. #include <boost/core/enable_if.hpp>
  20. #include <tuple>
  21. namespace boost {
  22. namespace detail { namespace variant {
  23. // Implementing some of the C++14 features in C++11
  24. template <std::size_t... I> class index_sequence {};
  25. template <std::size_t N, std::size_t... I>
  26. struct make_index_sequence
  27. : make_index_sequence<N-1, N-1, I...>
  28. {};
  29. template <std::size_t... I>
  30. struct make_index_sequence<0, I...>
  31. : index_sequence<I...>
  32. {};
  33. template <typename T_, bool MoveSemantics_>
  34. struct MoveableWrapper //Just a reference with some metadata
  35. {
  36. typedef T_ T;
  37. static constexpr bool MoveSemantics = MoveSemantics_;
  38. T& v;
  39. };
  40. template <typename Tp, bool MoveSemantics>
  41. MoveableWrapper<Tp, MoveSemantics>
  42. wrap(Tp& t)
  43. {
  44. return MoveableWrapper<Tp, MoveSemantics>{t};
  45. }
  46. template <typename Wrapper>
  47. typename enable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type
  48. unwrap(Wrapper& w)
  49. {
  50. return std::move(w.v);
  51. }
  52. template <typename Wrapper>
  53. typename disable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type &
  54. unwrap(Wrapper& w)
  55. {
  56. return w.v;
  57. }
  58. // Implementing some of the helper tuple methods
  59. template <std::size_t... I, typename Tuple>
  60. std::tuple<typename std::tuple_element<I + 1, Tuple>::type...>
  61. tuple_tail_impl(const Tuple& tpl, index_sequence<I...>)
  62. {
  63. return std::tuple<
  64. typename std::tuple_element<I + 1, Tuple>::type...
  65. > (std::get<I + 1>(tpl)...);
  66. }
  67. template <typename Head, typename... Tail>
  68. std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl)
  69. {
  70. return tuple_tail_impl(tpl, make_index_sequence<sizeof...(Tail)>());
  71. }
  72. // Forward declaration
  73. template <typename Visitor, typename Visitables, typename... Values>
  74. class one_by_one_visitor_and_value_referer;
  75. template <typename Visitor, typename Visitables, typename... Values>
  76. inline one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... >
  77. make_one_by_one_visitor_and_value_referer(
  78. Visitor& visitor, Visitables visitables, std::tuple<Values...> values
  79. )
  80. {
  81. return one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... > (
  82. visitor, visitables, values
  83. );
  84. }
  85. template <typename Visitor, typename Visitables, typename... Values>
  86. class one_by_one_visitor_and_value_referer
  87. {
  88. Visitor& visitor_;
  89. std::tuple<Values...> values_;
  90. Visitables visitables_;
  91. public: // structors
  92. one_by_one_visitor_and_value_referer(
  93. Visitor& visitor, Visitables visitables, std::tuple<Values...> values
  94. ) BOOST_NOEXCEPT
  95. : visitor_(visitor)
  96. , values_(values)
  97. , visitables_(visitables)
  98. {}
  99. public: // visitor interfaces
  100. typedef typename Visitor::result_type result_type;
  101. template <typename Value>
  102. result_type operator()(Value&& value) const
  103. {
  104. return ::boost::apply_visitor(
  105. make_one_by_one_visitor_and_value_referer(
  106. visitor_,
  107. tuple_tail(visitables_),
  108. std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
  109. )
  110. , unwrap(std::get<0>(visitables_)) // getting Head element
  111. );
  112. }
  113. private:
  114. one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&);
  115. };
  116. template <typename Visitor, typename... Values>
  117. class one_by_one_visitor_and_value_referer<Visitor, std::tuple<>, Values...>
  118. {
  119. Visitor& visitor_;
  120. std::tuple<Values...> values_;
  121. public:
  122. one_by_one_visitor_and_value_referer(
  123. Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
  124. ) BOOST_NOEXCEPT
  125. : visitor_(visitor)
  126. , values_(values)
  127. {}
  128. typedef typename Visitor::result_type result_type;
  129. template <class Tuple, std::size_t... I>
  130. result_type do_call(Tuple t, index_sequence<I...>) const {
  131. return visitor_(unwrap(std::get<I>(t))...);
  132. }
  133. template <typename Value>
  134. result_type operator()(Value&& value) const
  135. {
  136. return do_call(
  137. std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
  138. make_index_sequence<sizeof...(Values) + 1>()
  139. );
  140. }
  141. };
  142. }} // namespace detail::variant
  143. template <class Visitor, class T1, class T2, class T3, class... TN>
  144. inline typename Visitor::result_type
  145. apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
  146. {
  147. return ::boost::apply_visitor(
  148. ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
  149. visitor,
  150. std::make_tuple(
  151. ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
  152. ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
  153. ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
  154. ),
  155. std::tuple<>()
  156. ),
  157. std::forward<T1>(v1)
  158. );
  159. }
  160. template <class Visitor, class T1, class T2, class T3, class... TN>
  161. inline typename Visitor::result_type
  162. apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
  163. {
  164. return ::boost::apply_visitor(
  165. ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
  166. visitor,
  167. std::make_tuple(
  168. ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
  169. ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
  170. ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
  171. ),
  172. std::tuple<>()
  173. ),
  174. std::forward<T1>(v1)
  175. );
  176. }
  177. } // namespace boost
  178. #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP