multivisitors_cpp14_based.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Boost.Varaint
  2. // Contains multivisitors that are implemented via variadic templates, std::tuple
  3. // and decltype(auto)
  4. //
  5. // See http://www.boost.org for most recent version, including documentation.
  6. //
  7. // Copyright Antony Polukhin, 2013-2014.
  8. //
  9. // Distributed under the Boost
  10. // Software License, Version 1.0. (See accompanying file
  11. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
  12. #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP
  13. #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP
  14. #if defined(_MSC_VER)
  15. # pragma once
  16. #endif
  17. #include <tuple>
  18. namespace boost {
  19. namespace detail { namespace variant {
  20. // Forward declaration
  21. template <typename Visitor, typename Visitables, typename... Values>
  22. class one_by_one_visitor_and_value_referer_cpp14;
  23. template <typename Visitor, typename Visitables, typename... Values>
  24. inline one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... >
  25. make_one_by_one_visitor_and_value_referer_cpp14(
  26. Visitor& visitor, Visitables visitables, std::tuple<Values...> values
  27. )
  28. {
  29. return one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... > (
  30. visitor, visitables, values
  31. );
  32. }
  33. template <typename Visitor, typename Visitables, typename... Values>
  34. class one_by_one_visitor_and_value_referer_cpp14
  35. {
  36. Visitor& visitor_;
  37. std::tuple<Values...> values_;
  38. Visitables visitables_;
  39. public: // structors
  40. one_by_one_visitor_and_value_referer_cpp14(
  41. Visitor& visitor, Visitables visitables, std::tuple<Values...> values
  42. ) BOOST_NOEXCEPT
  43. : visitor_(visitor)
  44. , values_(values)
  45. , visitables_(visitables)
  46. {}
  47. public: // visitor interfaces
  48. template <typename Value>
  49. decltype(auto) operator()(Value&& value) const
  50. {
  51. return ::boost::apply_visitor(
  52. make_one_by_one_visitor_and_value_referer_cpp14(
  53. visitor_,
  54. tuple_tail(visitables_),
  55. std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
  56. )
  57. , unwrap(std::get<0>(visitables_)) // getting Head element
  58. );
  59. }
  60. private:
  61. one_by_one_visitor_and_value_referer_cpp14& operator=(const one_by_one_visitor_and_value_referer_cpp14&);
  62. };
  63. template <typename Visitor, typename... Values>
  64. class one_by_one_visitor_and_value_referer_cpp14<Visitor, std::tuple<>, Values...>
  65. {
  66. Visitor& visitor_;
  67. std::tuple<Values...> values_;
  68. public:
  69. one_by_one_visitor_and_value_referer_cpp14(
  70. Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
  71. ) BOOST_NOEXCEPT
  72. : visitor_(visitor)
  73. , values_(values)
  74. {}
  75. template <class Tuple, std::size_t... I>
  76. decltype(auto) do_call(Tuple t, index_sequence<I...>) const {
  77. return visitor_(unwrap(std::get<I>(t))...);
  78. }
  79. template <typename Value>
  80. decltype(auto) operator()(Value&& value) const
  81. {
  82. return do_call(
  83. std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
  84. make_index_sequence<sizeof...(Values) + 1>()
  85. );
  86. }
  87. };
  88. }} // namespace detail::variant
  89. template <class Visitor, class T1, class T2, class T3, class... TN>
  90. inline decltype(auto) apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
  91. typename boost::disable_if<
  92. boost::detail::variant::has_result_type<Visitor>,
  93. bool
  94. >::type = true)
  95. {
  96. return boost::apply_visitor(
  97. ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
  98. visitor,
  99. std::make_tuple(
  100. ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
  101. ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
  102. ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
  103. ),
  104. std::tuple<>()
  105. ),
  106. std::forward<T1>(v1)
  107. );
  108. }
  109. template <class Visitor, class T1, class T2, class T3, class... TN>
  110. inline decltype(auto) apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
  111. typename boost::disable_if<
  112. boost::detail::variant::has_result_type<Visitor>,
  113. bool
  114. >::type = true)
  115. {
  116. return ::boost::apply_visitor(
  117. ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
  118. visitor,
  119. std::make_tuple(
  120. ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
  121. ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
  122. ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
  123. ),
  124. std::tuple<>()
  125. ),
  126. std::forward<T1>(v1)
  127. );
  128. }
  129. } // namespace boost
  130. #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP