File indexing completed on 2025-01-18 09:29:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_DETAIL_VARIANT_HPP
0011 #define BOOST_BEAST_DETAIL_VARIANT_HPP
0012
0013 #include <boost/beast/core/detail/type_traits.hpp>
0014 #include <boost/assert.hpp>
0015 #include <boost/mp11/algorithm.hpp>
0016
0017 namespace boost {
0018 namespace beast {
0019 namespace detail {
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 template<class... TN>
0030 class variant
0031 {
0032 detail::aligned_union_t<1, TN...> buf_;
0033 unsigned char i_ = 0;
0034
0035 struct destroy
0036 {
0037 variant& self;
0038
0039 void operator()(mp11::mp_size_t<0>)
0040 {
0041 }
0042
0043 template<class I>
0044 void operator()(I) noexcept
0045 {
0046 using T =
0047 mp11::mp_at_c<variant, I::value - 1>;
0048 detail::launder_cast<T*>(&self.buf_)->~T();
0049 }
0050 };
0051
0052 struct copy
0053 {
0054 variant& self;
0055 variant const& other;
0056
0057 void operator()(mp11::mp_size_t<0>)
0058 {
0059 }
0060
0061 template<class I>
0062 void operator()(I)
0063 {
0064 using T =
0065 mp11::mp_at_c<variant, I::value - 1>;
0066 ::new(&self.buf_) T(
0067 *detail::launder_cast<T const*>(&other.buf_));
0068 self.i_ = I::value;
0069 }
0070 };
0071
0072 struct move
0073 {
0074 variant& self;
0075 variant& other;
0076
0077 void operator()(mp11::mp_size_t<0>)
0078 {
0079 }
0080
0081 template<class I>
0082 void operator()(I)
0083 {
0084 using T =
0085 mp11::mp_at_c<variant, I::value - 1>;
0086 ::new(&self.buf_) T(std::move(
0087 *detail::launder_cast<T*>(&other.buf_)));
0088 detail::launder_cast<T*>(&other.buf_)->~T();
0089 self.i_ = I::value;
0090 }
0091 };
0092
0093 struct equals
0094 {
0095 variant const& self;
0096 variant const& other;
0097
0098 bool operator()(mp11::mp_size_t<0>)
0099 {
0100 return true;
0101 }
0102
0103 template<class I>
0104 bool operator()(I)
0105 {
0106 using T =
0107 mp11::mp_at_c<variant, I::value - 1>;
0108 return
0109 *detail::launder_cast<T const*>(&self.buf_) ==
0110 *detail::launder_cast<T const*>(&other.buf_);
0111 }
0112 };
0113
0114
0115 void destruct()
0116 {
0117 mp11::mp_with_index<
0118 sizeof...(TN) + 1>(
0119 i_, destroy{*this});
0120 i_ = 0;
0121 }
0122
0123 void copy_construct(variant const& other)
0124 {
0125 mp11::mp_with_index<
0126 sizeof...(TN) + 1>(
0127 other.i_, copy{*this, other});
0128 }
0129
0130 void move_construct(variant& other)
0131 {
0132 mp11::mp_with_index<
0133 sizeof...(TN) + 1>(
0134 other.i_, move{*this, other});
0135 other.i_ = 0;
0136 }
0137
0138 public:
0139 variant() = default;
0140
0141 ~variant()
0142 {
0143 destruct();
0144 }
0145
0146 bool
0147 operator==(variant const& other) const
0148 {
0149 if(i_ != other.i_)
0150 return false;
0151 return mp11::mp_with_index<
0152 sizeof...(TN) + 1>(
0153 i_, equals{*this, other});
0154 }
0155
0156
0157 unsigned char
0158 index() const
0159 {
0160 return i_;
0161 }
0162
0163
0164 variant(variant&& other) noexcept
0165 {
0166 move_construct(other);
0167 }
0168
0169 variant(variant const& other)
0170 {
0171 copy_construct(other);
0172 }
0173
0174
0175 variant& operator=(variant&& other)
0176 {
0177 if(this != &other)
0178 {
0179 destruct();
0180 move_construct(other);
0181 }
0182 return *this;
0183 }
0184
0185 variant& operator=(variant const& other)
0186 {
0187 if(this != &other)
0188 {
0189 destruct();
0190 copy_construct(other);
0191
0192 }
0193 return *this;
0194 }
0195
0196 template<std::size_t I, class... Args>
0197 void
0198 emplace(Args&&... args) noexcept
0199 {
0200 destruct();
0201 ::new(&buf_) mp11::mp_at_c<variant, I - 1>(
0202 std::forward<Args>(args)...);
0203 i_ = I;
0204 }
0205
0206 template<std::size_t I>
0207 mp11::mp_at_c<variant, I - 1>&
0208 get()
0209 {
0210 BOOST_ASSERT(i_ == I);
0211 return *detail::launder_cast<
0212 mp11::mp_at_c<variant, I - 1>*>(&buf_);
0213 }
0214
0215 template<std::size_t I>
0216 mp11::mp_at_c<variant, I - 1> const&
0217 get() const
0218 {
0219 BOOST_ASSERT(i_ == I);
0220 return *detail::launder_cast<
0221 mp11::mp_at_c<variant, I - 1> const*>(&buf_);
0222 }
0223
0224 void
0225 reset()
0226 {
0227 destruct();
0228 }
0229 };
0230
0231 }
0232 }
0233 }
0234
0235 #endif