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 13 #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP 14 #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP 15 16 #if defined(_MSC_VER) 17 # pragma once 18 #endif 19 20 #include <boost/variant/detail/multivisitors_cpp14_based.hpp> 21 #include <tuple> 22 23 namespace boost { 24 25 namespace detail { namespace variant { 26 27 // Forward declaration 28 template <typename Visitor, typename Visitables, typename... Values> 29 class one_by_one_visitor_and_value_referer_cpp14; 30 31 template <typename Visitor, typename Visitables, typename... Values> 32 inline one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... > make_one_by_one_visitor_and_value_referer_cpp14(Visitor & visitor,Visitables visitables,std::tuple<Values...> values)33 make_one_by_one_visitor_and_value_referer_cpp14( 34 Visitor& visitor, Visitables visitables, std::tuple<Values...> values 35 ) 36 { 37 return one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... > ( 38 visitor, visitables, values 39 ); 40 } 41 42 template <typename Visitor, typename Visitables, typename... Values> 43 class one_by_one_visitor_and_value_referer_cpp14 44 { 45 Visitor& visitor_; 46 std::tuple<Values...> values_; 47 Visitables visitables_; 48 49 public: // structors one_by_one_visitor_and_value_referer_cpp14(Visitor & visitor,Visitables visitables,std::tuple<Values...> values)50 one_by_one_visitor_and_value_referer_cpp14( 51 Visitor& visitor, Visitables visitables, std::tuple<Values...> values 52 ) BOOST_NOEXCEPT 53 : visitor_(visitor) 54 , values_(values) 55 , visitables_(visitables) 56 {} 57 58 public: // visitor interfaces 59 template <typename Value> operator ()(Value && value) const60 decltype(auto) operator()(Value&& value) const 61 { 62 return ::boost::apply_visitor( 63 make_one_by_one_visitor_and_value_referer_cpp14( 64 visitor_, 65 tuple_tail(visitables_), 66 std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))) 67 ) 68 , unwrap(std::get<0>(visitables_)) // getting Head element 69 ); 70 } 71 72 private: 73 one_by_one_visitor_and_value_referer_cpp14& operator=(const one_by_one_visitor_and_value_referer_cpp14&); 74 }; 75 76 template <typename Visitor, typename... Values> 77 class one_by_one_visitor_and_value_referer_cpp14<Visitor, std::tuple<>, Values...> 78 { 79 Visitor& visitor_; 80 std::tuple<Values...> values_; 81 82 public: 83 one_by_one_visitor_and_value_referer_cpp14( 84 Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values 85 ) BOOST_NOEXCEPT 86 : visitor_(visitor) 87 , values_(values) 88 {} 89 90 template <class Tuple, std::size_t... I> 91 decltype(auto) do_call(Tuple t, index_sequence<I...>) const { 92 return visitor_(unwrap(std::get<I>(t))...); 93 } 94 95 template <typename Value> 96 decltype(auto) operator()(Value&& value) const 97 { 98 return do_call( 99 std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))), 100 make_index_sequence<sizeof...(Values) + 1>() 101 ); 102 } 103 }; 104 105 }} // namespace detail::variant 106 107 template <class Visitor, class T1, class T2, class T3, class... TN> apply_visitor(const Visitor & visitor,T1 && v1,T2 && v2,T3 && v3,TN &&...vn,typename boost::disable_if<boost::detail::variant::has_result_type<Visitor>,bool>::type=true)108 inline decltype(auto) apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn, 109 typename boost::disable_if< 110 boost::detail::variant::has_result_type<Visitor>, 111 bool 112 >::type = true) 113 { 114 return boost::apply_visitor( 115 ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14( 116 visitor, 117 std::make_tuple( 118 ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2), 119 ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3), 120 ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)... 121 ), 122 std::tuple<>() 123 ), 124 ::boost::forward<T1>(v1) 125 ); 126 } 127 128 129 template <class Visitor, class T1, class T2, class T3, class... TN> apply_visitor(Visitor & visitor,T1 && v1,T2 && v2,T3 && v3,TN &&...vn,typename boost::disable_if<boost::detail::variant::has_result_type<Visitor>,bool>::type=true)130 inline decltype(auto) apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn, 131 typename boost::disable_if< 132 boost::detail::variant::has_result_type<Visitor>, 133 bool 134 >::type = true) 135 { 136 return ::boost::apply_visitor( 137 ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14( 138 visitor, 139 std::make_tuple( 140 ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2), 141 ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3), 142 ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)... 143 ), 144 std::tuple<>() 145 ), 146 ::boost::forward<T1>(v1) 147 ); 148 } 149 150 } // namespace boost 151 152 #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP 153 154