]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/detail/variant.hpp
update sources to v12.2.3
[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 typename std::aligned_storage<
35 max_sizeof<TN...>(),
36 max_alignof<TN...>()
37 >::type buf_;
38 unsigned char i_ = 0;
39
40 template<std::size_t I>
41 using type = typename std::tuple_element<
42 I , std::tuple<TN...>>::type;
43
44 template<std::size_t I>
45 using C = std::integral_constant<std::size_t, I>;
46
47 public:
48 variant() = default;
49
50 ~variant()
51 {
52 if(i_)
53 destroy(C<0>{});
54 }
55
56 // 0 = empty
57 unsigned char
58 index() const
59 {
60 return i_;
61 }
62
63 // moved-from object becomes empty
64 variant(variant&& other)
65 {
66 i_ = other.move(&buf_, C<0>{});
67 }
68
69 variant(variant const& other)
70 {
71 i_ = other.copy(&buf_, C<0>{});
72 }
73
74 // moved-from object becomes empty
75 variant& operator=(variant&& other)
76 {
77 if(i_ != 0)
78 destroy(C<0>{});
79 i_ = other.move(&buf_, C<0>{});
80 return *this;
81 }
82
83 variant& operator=(variant const& other)
84 {
85 if(i_ != 0)
86 destroy(C<0>{});
87 i_ = other.copy(&buf_, C<0>{});
88 return *this;
89 }
90
91 template<std::size_t I, class... Args>
92 void
93 emplace(Args&&... args)
94 {
95 if(i_ != 0)
96 destroy(C<0>{});
97 new(&buf_) type<I-1>(
98 std::forward<Args>(args)...);
99 i_ = I;
100 }
101
102 template<std::size_t I>
103 type<I-1>&
104 get()
105 {
106 BOOST_ASSERT(i_ == I);
107 return *reinterpret_cast<
108 type<I-1>*>(&buf_);
109 }
110
111 template<std::size_t I>
112 type<I-1> const&
113 get() const
114 {
115 BOOST_ASSERT(i_ == I);
116 return *reinterpret_cast<
117 type<I-1> const*>(&buf_);
118 }
119
120 void
121 reset()
122 {
123 if(i_ == 0)
124 return;
125 destroy(C<0>{});
126 }
127
128 private:
129 void
130 destroy(C<sizeof...(TN)>)
131 {
132 return;
133 }
134
135 template<std::size_t I>
136 void
137 destroy(C<I>)
138 {
139 if(i_ == I+1)
140 {
141 using T = type<I>;
142 get<I+1>().~T();
143 i_ = 0;
144 return;
145 }
146 destroy(C<I+1>{});
147 }
148
149 unsigned char
150 move(void*, C<sizeof...(TN)>)
151 {
152 return 0;
153 }
154
155 template<std::size_t I>
156 unsigned char
157 move(void* dest, C<I>)
158 {
159 if(i_ == I+1)
160 {
161 using T = type<I>;
162 new(dest) T{std::move(get<I+1>())};
163 get<I+1>().~T();
164 i_ = 0;
165 return I+1;
166 }
167 return move(dest, C<I+1>{});
168 }
169
170 unsigned char
171 copy(void*, C<sizeof...(TN)>) const
172 {
173 return 0;
174 }
175
176 template<std::size_t I>
177 unsigned char
178 copy(void* dest, C<I>) const
179 {
180 if(i_ == I+1)
181 {
182 using T = type<I>;
183 auto const& t = get<I+1>();
184 new(dest) T{t};
185 return I+1;
186 }
187 return copy(dest, C<I+1>{});
188 }
189 };
190
191 } // detail
192 } // beast
193 } // boost
194
195 #endif