Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:25

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
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 // This simple variant gets the job done without
0022 // causing too much trouble with template depth:
0023 //
0024 // * Always allows an empty state I==0
0025 // * emplace() and get() support 1-based indexes only
0026 // * Basic exception guarantee
0027 // * Max 255 types
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     // 0 = empty
0157     unsigned char
0158     index() const
0159     {
0160         return i_;
0161     }
0162 
0163     // moved-from object becomes empty
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     // moved-from object becomes empty
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 } // detail
0232 } // beast
0233 } // boost
0234 
0235 #endif