]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/detail/variant.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / beast / core / detail / variant.hpp
1 //
2 // Copyright (c) 2016-2019 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 <boost/mp11/algorithm.hpp>
16
17 namespace boost {
18 namespace beast {
19 namespace detail {
20
21 // This simple variant gets the job done without
22 // causing too much trouble with template depth:
23 //
24 // * Always allows an empty state I==0
25 // * emplace() and get() support 1-based indexes only
26 // * Basic exception guarantee
27 // * Max 255 types
28 //
29 template<class... TN>
30 class variant
31 {
32 detail::aligned_union_t<1, TN...> buf_;
33 unsigned char i_ = 0;
34
35 struct destroy
36 {
37 variant& self;
38
39 void operator()(mp11::mp_size_t<0>)
40 {
41 }
42
43 template<class I>
44 void operator()(I) noexcept
45 {
46 using T =
47 mp11::mp_at_c<variant, I::value - 1>;
48 detail::launder_cast<T*>(&self.buf_)->~T();
49 }
50 };
51
52 struct copy
53 {
54 variant& self;
55 variant const& other;
56
57 void operator()(mp11::mp_size_t<0>)
58 {
59 }
60
61 template<class I>
62 void operator()(I)
63 {
64 using T =
65 mp11::mp_at_c<variant, I::value - 1>;
66 ::new(&self.buf_) T(
67 *detail::launder_cast<T const*>(&other.buf_));
68 self.i_ = I::value;
69 }
70 };
71
72 struct move
73 {
74 variant& self;
75 variant& other;
76
77 void operator()(mp11::mp_size_t<0>)
78 {
79 }
80
81 template<class I>
82 void operator()(I)
83 {
84 using T =
85 mp11::mp_at_c<variant, I::value - 1>;
86 ::new(&self.buf_) T(std::move(
87 *detail::launder_cast<T*>(&other.buf_)));
88 detail::launder_cast<T*>(&other.buf_)->~T();
89 self.i_ = I::value;
90 }
91 };
92
93 struct equals
94 {
95 variant const& self;
96 variant const& other;
97
98 bool operator()(mp11::mp_size_t<0>)
99 {
100 return true;
101 }
102
103 template<class I>
104 bool operator()(I)
105 {
106 using T =
107 mp11::mp_at_c<variant, I::value - 1>;
108 return
109 *detail::launder_cast<T const*>(&self.buf_) ==
110 *detail::launder_cast<T const*>(&other.buf_);
111 }
112 };
113
114
115 void destruct()
116 {
117 mp11::mp_with_index<
118 sizeof...(TN) + 1>(
119 i_, destroy{*this});
120 i_ = 0;
121 }
122
123 void copy_construct(variant const& other)
124 {
125 mp11::mp_with_index<
126 sizeof...(TN) + 1>(
127 other.i_, copy{*this, other});
128 }
129
130 void move_construct(variant& other)
131 {
132 mp11::mp_with_index<
133 sizeof...(TN) + 1>(
134 other.i_, move{*this, other});
135 other.i_ = 0;
136 }
137
138 public:
139 variant() = default;
140
141 ~variant()
142 {
143 destruct();
144 }
145
146 bool
147 operator==(variant const& other) const
148 {
149 if(i_ != other.i_)
150 return false;
151 return mp11::mp_with_index<
152 sizeof...(TN) + 1>(
153 i_, equals{*this, other});
154 }
155
156 // 0 = empty
157 unsigned char
158 index() const
159 {
160 return i_;
161 }
162
163 // moved-from object becomes empty
164 variant(variant&& other) noexcept
165 {
166 move_construct(other);
167 }
168
169 variant(variant const& other)
170 {
171 copy_construct(other);
172 }
173
174 // moved-from object becomes empty
175 variant& operator=(variant&& other)
176 {
177 if(this != &other)
178 {
179 destruct();
180 move_construct(other);
181 }
182 return *this;
183 }
184
185 variant& operator=(variant const& other)
186 {
187 if(this != &other)
188 {
189 destruct();
190 copy_construct(other);
191
192 }
193 return *this;
194 }
195
196 template<std::size_t I, class... Args>
197 void
198 emplace(Args&&... args) noexcept
199 {
200 destruct();
201 ::new(&buf_) mp11::mp_at_c<variant, I - 1>(
202 std::forward<Args>(args)...);
203 i_ = I;
204 }
205
206 template<std::size_t I>
207 mp11::mp_at_c<variant, I - 1>&
208 get()
209 {
210 BOOST_ASSERT(i_ == I);
211 return *detail::launder_cast<
212 mp11::mp_at_c<variant, I - 1>*>(&buf_);
213 }
214
215 template<std::size_t I>
216 mp11::mp_at_c<variant, I - 1> const&
217 get() const
218 {
219 BOOST_ASSERT(i_ == I);
220 return *detail::launder_cast<
221 mp11::mp_at_c<variant, I - 1> const*>(&buf_);
222 }
223
224 void
225 reset()
226 {
227 destruct();
228 }
229 };
230
231 } // detail
232 } // beast
233 } // boost
234
235 #endif