]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/detail/variant.hpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / boost / beast / core / detail / variant.hpp
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_DETAIL_VARIANT_HPP
11 #define BOOST_BEAST_DETAIL_VARIANT_HPP
12
13 #include <boost/beast/core/detail/type_traits.hpp>
14 #include <boost/assert.hpp>
15 #include <cstddef>
16 #include <tuple>
17 #include <type_traits>
18
19 namespace boost {
20 namespace beast {
21 namespace detail {
22
23 // This simple variant gets the job done without
24 // causing too much trouble with template depth:
25 //
26 // * Always allows an empty state I==0
27 // * emplace() and get() support 1-based indexes only
28 // * Basic exception guarantee
29 // * Max 255 types
30 //
31 template<class... TN>
32 class variant
33 {
34 detail::aligned_union_t<1, TN...> buf_;
35 unsigned char i_ = 0;
36
37 template<std::size_t I>
38 using type = typename std::tuple_element<
39 I, std::tuple<TN...>>::type;
40
41 template<std::size_t I>
42 using C = std::integral_constant<std::size_t, I>;
43
44 public:
45 variant() = default;
46
47 ~variant()
48 {
49 destroy(C<0>{});
50 }
51
52 bool
53 operator==(variant const& other) const
54 {
55 if(i_ != other.i_)
56 return false;
57 return equal(other, C<0>{});
58 }
59
60 // 0 = empty
61 unsigned char
62 index() const
63 {
64 return i_;
65 }
66
67 // moved-from object becomes empty
68 variant(variant&& other)
69 {
70 i_ = other.move(&buf_, C<0>{});
71 other.i_ = 0;
72 }
73
74 variant(variant const& other)
75 {
76 i_ = other.copy(&buf_, C<0>{});
77 }
78
79 // moved-from object becomes empty
80 variant& operator=(variant&& other)
81 {
82 if(this != &other)
83 {
84 destroy(C<0>{});
85 i_ = other.move(&buf_, C<0>{});
86 other.i_ = 0;
87 }
88 return *this;
89 }
90
91 variant& operator=(variant const& other)
92 {
93 if(this != &other)
94 {
95 destroy(C<0>{});
96 i_ = other.copy(&buf_, C<0>{});
97 }
98 return *this;
99 }
100
101 template<std::size_t I, class... Args>
102 void
103 emplace(Args&&... args)
104 {
105 destroy(C<0>{});
106 new(&buf_) type<I-1>(
107 std::forward<Args>(args)...);
108 i_ = I;
109 }
110
111 template<std::size_t I>
112 type<I-1>&
113 get()
114 {
115 BOOST_ASSERT(i_ == I);
116 return *reinterpret_cast<
117 type<I-1>*>(&buf_);
118 }
119
120 template<std::size_t I>
121 type<I-1> const&
122 get() const
123 {
124 BOOST_ASSERT(i_ == I);
125 return *reinterpret_cast<
126 type<I-1> const*>(&buf_);
127 }
128
129 void
130 reset()
131 {
132 destroy(C<0>{});
133 }
134
135 private:
136 void
137 destroy(C<0>)
138 {
139 auto const I = 0;
140 if(i_ == I)
141 return;
142 destroy(C<I+1>{});
143 i_ = 0;
144 }
145
146 template<std::size_t I>
147 void
148 destroy(C<I>)
149 {
150 if(i_ == I)
151 {
152 using T = type<I-1>;
153 get<I>().~T();
154 return;
155 }
156 destroy(C<I+1>{});
157 }
158
159 void
160 destroy(C<sizeof...(TN)>)
161 {
162 auto const I = sizeof...(TN);
163 BOOST_ASSERT(i_ == I);
164 using T = type<I-1>;
165 get<I>().~T();
166 }
167
168 unsigned char
169 move(void* dest, C<0>)
170 {
171 auto const I = 0;
172 if(i_ == I)
173 return I;
174 return move(dest, C<I+1>{});
175 }
176
177 template<std::size_t I>
178 unsigned char
179 move(void* dest, C<I>)
180 {
181 if(i_ == I)
182 {
183 using T = type<I-1>;
184 new(dest) T(std::move(get<I>()));
185 get<I>().~T();
186 return I;
187 }
188 return move(dest, C<I+1>{});
189 }
190
191 unsigned char
192 move(void* dest, C<sizeof...(TN)>)
193 {
194 auto const I = sizeof...(TN);
195 BOOST_ASSERT(i_ == I);
196 using T = type<I-1>;
197 new(dest) T(std::move(get<I>()));
198 get<I>().~T();
199 return I;
200 }
201
202 unsigned char
203 copy(void* dest, C<0>) const
204 {
205 auto const I = 0;
206 if(i_ == I)
207 return I;
208 return copy(dest, C<I+1>{});
209 }
210
211 template<std::size_t I>
212 unsigned char
213 copy(void* dest, C<I>) const
214 {
215 if(i_ == I)
216 {
217 using T = type<I-1>;
218 auto const& t = get<I>();
219 new(dest) T(t);
220 return I;
221 }
222 return copy(dest, C<I+1>{});
223 }
224
225 unsigned char
226 copy(void* dest, C<sizeof...(TN)>) const
227 {
228 auto const I = sizeof...(TN);
229 BOOST_ASSERT(i_ == I);
230 using T = type<I-1>;
231 auto const& t = get<I>();
232 new(dest) T(t);
233 return I;
234 }
235
236 bool
237 equal(variant const& other, C<0>) const
238 {
239 auto constexpr I = 0;
240 if(i_ == I)
241 return true;
242 return equal(other, C<I+1>{});
243 }
244
245 template<std::size_t I>
246 bool
247 equal(variant const& other, C<I>) const
248 {
249 if(i_ == I)
250 return get<I>() == other.get<I>();
251 return equal(other, C<I+1>{});
252 }
253
254 bool
255 equal(variant const& other, C<sizeof...(TN)>) const
256 {
257 auto constexpr I = sizeof...(TN);
258 BOOST_ASSERT(i_ == I);
259 return get<I>() == other.get<I>();
260 }
261 };
262
263 } // detail
264 } // beast
265 } // boost
266
267 #endif