]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
b32b8144
FG
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
19namespace boost {
20namespace beast {
21namespace 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//
31template<class... TN>
32class variant
33{
11fdf7f2 34 detail::aligned_union_t<1, TN...> buf_;
b32b8144
FG
35 unsigned char i_ = 0;
36
37 template<std::size_t I>
38 using type = typename std::tuple_element<
11fdf7f2 39 I, std::tuple<TN...>>::type;
b32b8144
FG
40
41 template<std::size_t I>
42 using C = std::integral_constant<std::size_t, I>;
43
44public:
45 variant() = default;
46
47 ~variant()
48 {
11fdf7f2
TL
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>{});
b32b8144
FG
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>{});
11fdf7f2 71 other.i_ = 0;
b32b8144
FG
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 {
11fdf7f2
TL
82 if(this != &other)
83 {
b32b8144 84 destroy(C<0>{});
11fdf7f2
TL
85 i_ = other.move(&buf_, C<0>{});
86 other.i_ = 0;
87 }
b32b8144
FG
88 return *this;
89 }
90
91 variant& operator=(variant const& other)
92 {
11fdf7f2
TL
93 if(this != &other)
94 {
b32b8144 95 destroy(C<0>{});
11fdf7f2
TL
96 i_ = other.copy(&buf_, C<0>{});
97 }
b32b8144
FG
98 return *this;
99 }
100
101 template<std::size_t I, class... Args>
102 void
103 emplace(Args&&... args)
104 {
11fdf7f2 105 destroy(C<0>{});
b32b8144
FG
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 {
b32b8144
FG
132 destroy(C<0>{});
133 }
134
135private:
136 void
11fdf7f2 137 destroy(C<0>)
b32b8144 138 {
11fdf7f2
TL
139 auto const I = 0;
140 if(i_ == I)
141 return;
142 destroy(C<I+1>{});
143 i_ = 0;
b32b8144
FG
144 }
145
146 template<std::size_t I>
147 void
148 destroy(C<I>)
149 {
11fdf7f2 150 if(i_ == I)
b32b8144 151 {
11fdf7f2
TL
152 using T = type<I-1>;
153 get<I>().~T();
b32b8144
FG
154 return;
155 }
156 destroy(C<I+1>{});
157 }
158
11fdf7f2
TL
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
b32b8144 168 unsigned char
11fdf7f2 169 move(void* dest, C<0>)
b32b8144 170 {
11fdf7f2
TL
171 auto const I = 0;
172 if(i_ == I)
173 return I;
174 return move(dest, C<I+1>{});
b32b8144
FG
175 }
176
177 template<std::size_t I>
178 unsigned char
179 move(void* dest, C<I>)
180 {
11fdf7f2 181 if(i_ == I)
b32b8144 182 {
11fdf7f2
TL
183 using T = type<I-1>;
184 new(dest) T(std::move(get<I>()));
185 get<I>().~T();
186 return I;
b32b8144
FG
187 }
188 return move(dest, C<I+1>{});
189 }
190
191 unsigned char
11fdf7f2
TL
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
b32b8144 204 {
11fdf7f2
TL
205 auto const I = 0;
206 if(i_ == I)
207 return I;
208 return copy(dest, C<I+1>{});
b32b8144
FG
209 }
210
211 template<std::size_t I>
212 unsigned char
213 copy(void* dest, C<I>) const
214 {
11fdf7f2 215 if(i_ == I)
b32b8144 216 {
11fdf7f2
TL
217 using T = type<I-1>;
218 auto const& t = get<I>();
219 new(dest) T(t);
220 return I;
b32b8144
FG
221 }
222 return copy(dest, C<I+1>{});
223 }
11fdf7f2
TL
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 }
b32b8144
FG
261};
262
263} // detail
264} // beast
265} // boost
266
267#endif