From 13322fa4bb7986ad540db2edbe5f4a598ff36d1c Mon Sep 17 00:00:00 2001 From: Damian Jarek Date: Sun, 18 Nov 2018 18:42:39 +0100 Subject: [PATCH] Use mp11 in detail::variant Reduce compilation cost for all components dependent on variant. Signed-off-by: Damian Jarek --- CHANGELOG.md | 1 + include/boost/beast/core/detail/variant.hpp | 279 +++++++++----------- 2 files changed, 125 insertions(+), 155 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79d501d3..676ff6d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Version 191: * Simplify some type traits * Use lean_tuple in buffers_cat * Use lean_tuple in bind_handler, bind_front_handler +* Use mp11 in detail::variant -------------------------------------------------------------------------------- diff --git a/include/boost/beast/core/detail/variant.hpp b/include/boost/beast/core/detail/variant.hpp index 536cb759..02347ae6 100644 --- a/include/boost/beast/core/detail/variant.hpp +++ b/include/boost/beast/core/detail/variant.hpp @@ -12,14 +12,13 @@ #include #include -#include -#include -#include +#include namespace boost { namespace beast { namespace detail { + // This simple variant gets the job done without // causing too much trouble with template depth: // @@ -34,19 +33,115 @@ class variant detail::aligned_union_t<1, TN...> buf_; unsigned char i_ = 0; - template - using type = typename std::tuple_element< - I, std::tuple>::type; + struct destroy + { + variant& self; - template - using C = std::integral_constant; + void operator()(mp11::mp_size_t<0>) + { + } + + template + void operator()(I) noexcept + { + using T = + mp11::mp_at_c; + reinterpret_cast(self.buf_).~T(); + } + }; + + struct copy + { + variant& self; + variant const& other; + + void operator()(mp11::mp_size_t<0>) + { + } + + template + void operator()(I) + { + using T = + mp11::mp_at_c; + ::new(&self.buf_) T( + reinterpret_cast(other.buf_)); + self.i_ = I::value; + } + }; + + struct move + { + variant& self; + variant& other; + + void operator()(mp11::mp_size_t<0>) + { + } + + template + void operator()(I) + { + using T = + mp11::mp_at_c; + ::new(&self.buf_) T( + reinterpret_cast(other.buf_)); + reinterpret_cast(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 + bool operator()(I) + { + using T = + mp11::mp_at_c; + return + reinterpret_cast(self.buf_) == + reinterpret_cast(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() { - destroy(C<0>{}); + destruct(); } bool @@ -54,7 +149,9 @@ public: { if(i_ != other.i_) return false; - return equal(other, C<0>{}); + return mp11::mp_with_index< + sizeof...(TN) + 1>( + i_, equals{*this, other}); } // 0 = empty @@ -65,15 +162,14 @@ public: } // moved-from object becomes empty - variant(variant&& other) + variant(variant&& other) noexcept { - i_ = other.move(&buf_, C<0>{}); - other.i_ = 0; + move_construct(other); } variant(variant const& other) { - i_ = other.copy(&buf_, C<0>{}); + copy_construct(other); } // moved-from object becomes empty @@ -81,182 +177,55 @@ public: { if(this != &other) { - destroy(C<0>{}); - i_ = other.move(&buf_, C<0>{}); - other.i_ = 0; + destruct(); + move_construct(other); } return *this; } - + variant& operator=(variant const& other) { if(this != &other) { - destroy(C<0>{}); - i_ = other.copy(&buf_, C<0>{}); + destruct(); + copy_construct(other); + } return *this; } template void - emplace(Args&&... args) + emplace(Args&&... args) noexcept { - destroy(C<0>{}); - new(&buf_) type( + destruct(); + ::new(&buf_) mp11::mp_at_c( std::forward(args)...); i_ = I; } template - type& + mp11::mp_at_c& get() { BOOST_ASSERT(i_ == I); return *reinterpret_cast< - type*>(&buf_); + mp11::mp_at_c*>(&buf_); } template - type const& + mp11::mp_at_c const& get() const { BOOST_ASSERT(i_ == I); return *reinterpret_cast< - type const*>(&buf_); + mp11::mp_at_c const*>(&buf_); } void reset() { - destroy(C<0>{}); - } - -private: - void - destroy(C<0>) - { - auto const I = 0; - if(i_ == I) - return; - destroy(C{}); - i_ = 0; - } - - template - void - destroy(C) - { - if(i_ == I) - { - using T = type; - get().~T(); - return; - } - destroy(C{}); - } - - void - destroy(C) - { - auto const I = sizeof...(TN); - BOOST_ASSERT(i_ == I); - using T = type; - get().~T(); - } - - unsigned char - move(void* dest, C<0>) - { - auto const I = 0; - if(i_ == I) - return I; - return move(dest, C{}); - } - - template - unsigned char - move(void* dest, C) - { - if(i_ == I) - { - using T = type; - new(dest) T(std::move(get())); - get().~T(); - return I; - } - return move(dest, C{}); - } - - unsigned char - move(void* dest, C) - { - auto const I = sizeof...(TN); - BOOST_ASSERT(i_ == I); - using T = type; - new(dest) T(std::move(get())); - get().~T(); - return I; - } - - unsigned char - copy(void* dest, C<0>) const - { - auto const I = 0; - if(i_ == I) - return I; - return copy(dest, C{}); - } - - template - unsigned char - copy(void* dest, C) const - { - if(i_ == I) - { - using T = type; - auto const& t = get(); - new(dest) T(t); - return I; - } - return copy(dest, C{}); - } - - unsigned char - copy(void* dest, C) const - { - auto const I = sizeof...(TN); - BOOST_ASSERT(i_ == I); - using T = type; - auto const& t = get(); - new(dest) T(t); - return I; - } - - bool - equal(variant const& other, C<0>) const - { - auto constexpr I = 0; - if(i_ == I) - return true; - return equal(other, C{}); - } - - template - bool - equal(variant const& other, C) const - { - if(i_ == I) - return get() == other.get(); - return equal(other, C{}); - } - - bool - equal(variant const& other, C) const - { - auto constexpr I = sizeof...(TN); - BOOST_ASSERT(i_ == I); - return get() == other.get(); + destruct(); } };