File indexing completed on 2025-01-18 09:53:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
0013 #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
0014
0015 #if defined(_MSC_VER)
0016 # pragma once
0017 #endif
0018
0019 #include <boost/variant/detail/apply_visitor_unary.hpp>
0020 #include <boost/variant/variant_fwd.hpp>
0021 #include <boost/type_traits/is_lvalue_reference.hpp>
0022 #include <boost/core/enable_if.hpp>
0023
0024 #include <tuple>
0025
0026 namespace boost {
0027
0028 namespace detail { namespace variant {
0029
0030
0031 template <std::size_t... I> class index_sequence {};
0032
0033 template <std::size_t N, std::size_t... I>
0034 struct make_index_sequence
0035 : make_index_sequence<N-1, N-1, I...>
0036 {};
0037 template <std::size_t... I>
0038 struct make_index_sequence<0, I...>
0039 : index_sequence<I...>
0040 {};
0041
0042 template <typename T_, bool MoveSemantics_>
0043 struct MoveableWrapper
0044 {
0045 typedef T_ T;
0046 static constexpr bool MoveSemantics = MoveSemantics_;
0047
0048 T& v;
0049 };
0050
0051 template <typename Tp, bool MoveSemantics>
0052 MoveableWrapper<Tp, MoveSemantics>
0053 wrap(Tp& t)
0054 {
0055 return MoveableWrapper<Tp, MoveSemantics>{t};
0056 }
0057
0058 template <typename Wrapper>
0059 typename enable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type
0060 unwrap(Wrapper& w)
0061 {
0062 return std::move(w.v);
0063 }
0064
0065 template <typename Wrapper>
0066 typename disable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type &
0067 unwrap(Wrapper& w)
0068 {
0069 return w.v;
0070 }
0071
0072
0073 template <std::size_t... I, typename Tuple>
0074 std::tuple<typename std::tuple_element<I + 1, Tuple>::type...>
0075 tuple_tail_impl(const Tuple& tpl, index_sequence<I...>)
0076 {
0077 return std::tuple<
0078 typename std::tuple_element<I + 1, Tuple>::type...
0079 > (std::get<I + 1>(tpl)...);
0080 }
0081
0082 template <typename Head, typename... Tail>
0083 std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl)
0084 {
0085 return tuple_tail_impl(tpl, make_index_sequence<sizeof...(Tail)>());
0086 }
0087
0088
0089
0090 template <typename Visitor, typename Visitables, typename... Values>
0091 class one_by_one_visitor_and_value_referer;
0092
0093 template <typename Visitor, typename Visitables, typename... Values>
0094 inline one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... >
0095 make_one_by_one_visitor_and_value_referer(
0096 Visitor& visitor, Visitables visitables, std::tuple<Values...> values
0097 )
0098 {
0099 return one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... > (
0100 visitor, visitables, values
0101 );
0102 }
0103
0104 template <typename Visitor, typename Visitables, typename... Values>
0105 class one_by_one_visitor_and_value_referer
0106 {
0107 Visitor& visitor_;
0108 std::tuple<Values...> values_;
0109 Visitables visitables_;
0110
0111 public:
0112 one_by_one_visitor_and_value_referer(
0113 Visitor& visitor, Visitables visitables, std::tuple<Values...> values
0114 ) BOOST_NOEXCEPT
0115 : visitor_(visitor)
0116 , values_(values)
0117 , visitables_(visitables)
0118 {}
0119
0120 public:
0121 typedef typename Visitor::result_type result_type;
0122
0123 template <typename Value>
0124 result_type operator()(Value&& value) const
0125 {
0126 return ::boost::apply_visitor(
0127 make_one_by_one_visitor_and_value_referer(
0128 visitor_,
0129 tuple_tail(visitables_),
0130 std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
0131 )
0132 , unwrap(std::get<0>(visitables_))
0133 );
0134 }
0135
0136 private:
0137 one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&);
0138 };
0139
0140 template <typename Visitor, typename... Values>
0141 class one_by_one_visitor_and_value_referer<Visitor, std::tuple<>, Values...>
0142 {
0143 Visitor& visitor_;
0144 std::tuple<Values...> values_;
0145
0146 public:
0147 one_by_one_visitor_and_value_referer(
0148 Visitor& visitor, std::tuple<> , std::tuple<Values...> values
0149 ) BOOST_NOEXCEPT
0150 : visitor_(visitor)
0151 , values_(values)
0152 {}
0153
0154 typedef typename Visitor::result_type result_type;
0155
0156 template <class Tuple, std::size_t... I>
0157 result_type do_call(Tuple t, index_sequence<I...>) const {
0158 return visitor_(unwrap(std::get<I>(t))...);
0159 }
0160
0161 template <typename Value>
0162 result_type operator()(Value&& value) const
0163 {
0164 return do_call(
0165 std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
0166 make_index_sequence<sizeof...(Values) + 1>()
0167 );
0168 }
0169 };
0170
0171 }}
0172
0173 template <class Visitor, class T1, class T2, class T3, class... TN>
0174 inline typename Visitor::result_type
0175 apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
0176 {
0177 return ::boost::apply_visitor(
0178 ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
0179 visitor,
0180 std::make_tuple(
0181 ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
0182 ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
0183 ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
0184 ),
0185 std::tuple<>()
0186 ),
0187 std::forward<T1>(v1)
0188 );
0189 }
0190
0191 template <class Visitor, class T1, class T2, class T3, class... TN>
0192 inline typename Visitor::result_type
0193 apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
0194 {
0195 return ::boost::apply_visitor(
0196 ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
0197 visitor,
0198 std::make_tuple(
0199 ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
0200 ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
0201 ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
0202 ),
0203 std::tuple<>()
0204 ),
0205 std::forward<T1>(v1)
0206 );
0207 }
0208
0209 }
0210
0211 #endif
0212