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