multivisitors_cpp11_based.hpp 7.4 KB

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