123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- //
- // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // Official repository: https://github.com/boostorg/beast
- //
- #ifndef BHO_BEAST_DETAIL_VARIANT_HPP
- #define BHO_BEAST_DETAIL_VARIANT_HPP
- #include <asio2/bho/beast/core/detail/type_traits.hpp>
- #include <asio2/bho/assert.hpp>
- #include <asio2/bho/mp11/algorithm.hpp>
- namespace bho {
- namespace beast {
- namespace detail {
- // This simple variant gets the job done without
- // causing too much trouble with template depth:
- //
- // * Always allows an empty state I==0
- // * emplace() and get() support 1-based indexes only
- // * Basic exception guarantee
- // * Max 255 types
- //
- template<class... TN>
- class variant
- {
- detail::aligned_union_t<1, TN...> buf_;
- unsigned char i_ = 0;
- struct destroy
- {
- variant& self;
- void operator()(mp11::mp_size_t<0>)
- {
- }
- template<class I>
- void operator()(I) noexcept
- {
- using T =
- mp11::mp_at_c<variant, I::value - 1>;
- detail::launder_cast<T*>(&self.buf_)->~T();
- }
- };
- struct copy
- {
- variant& self;
- variant const& other;
- void operator()(mp11::mp_size_t<0>)
- {
- }
- template<class I>
- void operator()(I)
- {
- using T =
- mp11::mp_at_c<variant, I::value - 1>;
- ::new(&self.buf_) T(
- *detail::launder_cast<T const*>(&other.buf_));
- self.i_ = I::value;
- }
- };
- struct move
- {
- variant& self;
- variant& other;
- void operator()(mp11::mp_size_t<0>)
- {
- }
- template<class I>
- void operator()(I)
- {
- using T =
- mp11::mp_at_c<variant, I::value - 1>;
- ::new(&self.buf_) T(std::move(
- *detail::launder_cast<T*>(&other.buf_)));
- detail::launder_cast<T*>(&other.buf_)->~T();
- self.i_ = I::value;
- }
- };
- struct equals
- {
- variant const& self;
- variant const& other;
- bool operator()(mp11::mp_size_t<0>)
- {
- return true;
- }
- template<class I>
- bool operator()(I)
- {
- using T =
- mp11::mp_at_c<variant, I::value - 1>;
- return
- *detail::launder_cast<T const*>(&self.buf_) ==
- *detail::launder_cast<T const*>(&other.buf_);
- }
- };
- void destruct()
- {
- mp11::mp_with_index<
- sizeof...(TN) + 1>(
- i_, destroy{*this});
- i_ = 0;
- }
- void copy_construct(variant const& other)
- {
- mp11::mp_with_index<
- sizeof...(TN) + 1>(
- other.i_, copy{*this, other});
- }
- void move_construct(variant& other)
- {
- mp11::mp_with_index<
- sizeof...(TN) + 1>(
- other.i_, move{*this, other});
- other.i_ = 0;
- }
- public:
- variant() = default;
- ~variant()
- {
- destruct();
- }
- bool
- operator==(variant const& other) const
- {
- if(i_ != other.i_)
- return false;
- return mp11::mp_with_index<
- sizeof...(TN) + 1>(
- i_, equals{*this, other});
- }
- // 0 = empty
- unsigned char
- index() const
- {
- return i_;
- }
- // moved-from object becomes empty
- variant(variant&& other) noexcept
- {
- move_construct(other);
- }
- variant(variant const& other)
- {
- copy_construct(other);
- }
- // moved-from object becomes empty
- variant& operator=(variant&& other)
- {
- if(this != &other)
- {
- destruct();
- move_construct(other);
- }
- return *this;
- }
- variant& operator=(variant const& other)
- {
- if(this != &other)
- {
- destruct();
- copy_construct(other);
- }
- return *this;
- }
- template<std::size_t I, class... Args>
- void
- emplace(Args&&... args) noexcept
- {
- destruct();
- ::new(&buf_) mp11::mp_at_c<variant, I - 1>(
- std::forward<Args>(args)...);
- i_ = I;
- }
- template<std::size_t I>
- mp11::mp_at_c<variant, I - 1>&
- get()
- {
- BHO_ASSERT(i_ == I);
- return *detail::launder_cast<
- mp11::mp_at_c<variant, I - 1>*>(&buf_);
- }
- template<std::size_t I>
- mp11::mp_at_c<variant, I - 1> const&
- get() const
- {
- BHO_ASSERT(i_ == I);
- return *detail::launder_cast<
- mp11::mp_at_c<variant, I - 1> const*>(&buf_);
- }
- void
- reset()
- {
- destruct();
- }
- };
- } // detail
- } // beast
- } // bho
- #endif
|