Use mp11 in detail::variant

Reduce compilation cost for all components dependent on variant.

Signed-off-by: Damian Jarek <damian.jarek93@gmail.com>
This commit is contained in:
Damian Jarek
2018-11-18 18:42:39 +01:00
committed by Vinnie Falco
parent 98ff568371
commit 13322fa4bb
2 changed files with 125 additions and 155 deletions

View File

@ -5,6 +5,7 @@ Version 191:
* Simplify some type traits * Simplify some type traits
* Use lean_tuple in buffers_cat * Use lean_tuple in buffers_cat
* Use lean_tuple in bind_handler, bind_front_handler * Use lean_tuple in bind_handler, bind_front_handler
* Use mp11 in detail::variant
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@ -12,14 +12,13 @@
#include <boost/beast/core/detail/type_traits.hpp> #include <boost/beast/core/detail/type_traits.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <cstddef> #include <boost/mp11/algorithm.hpp>
#include <tuple>
#include <type_traits>
namespace boost { namespace boost {
namespace beast { namespace beast {
namespace detail { namespace detail {
// This simple variant gets the job done without // This simple variant gets the job done without
// causing too much trouble with template depth: // causing too much trouble with template depth:
// //
@ -34,19 +33,115 @@ class variant
detail::aligned_union_t<1, TN...> buf_; detail::aligned_union_t<1, TN...> buf_;
unsigned char i_ = 0; unsigned char i_ = 0;
template<std::size_t I> struct destroy
using type = typename std::tuple_element< {
I, std::tuple<TN...>>::type; variant& self;
template<std::size_t I> void operator()(mp11::mp_size_t<0>)
using C = std::integral_constant<std::size_t, I>; {
}
template<class I>
void operator()(I) noexcept
{
using T =
mp11::mp_at_c<variant, I::value - 1>;
reinterpret_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(
reinterpret_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(
reinterpret_cast<T&&>(other.buf_));
reinterpret_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
reinterpret_cast<T const&>(self.buf_) ==
reinterpret_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: public:
variant() = default; variant() = default;
~variant() ~variant()
{ {
destroy(C<0>{}); destruct();
} }
bool bool
@ -54,7 +149,9 @@ public:
{ {
if(i_ != other.i_) if(i_ != other.i_)
return false; return false;
return equal(other, C<0>{}); return mp11::mp_with_index<
sizeof...(TN) + 1>(
i_, equals{*this, other});
} }
// 0 = empty // 0 = empty
@ -65,15 +162,14 @@ public:
} }
// moved-from object becomes empty // moved-from object becomes empty
variant(variant&& other) variant(variant&& other) noexcept
{ {
i_ = other.move(&buf_, C<0>{}); move_construct(other);
other.i_ = 0;
} }
variant(variant const& other) variant(variant const& other)
{ {
i_ = other.copy(&buf_, C<0>{}); copy_construct(other);
} }
// moved-from object becomes empty // moved-from object becomes empty
@ -81,182 +177,55 @@ public:
{ {
if(this != &other) if(this != &other)
{ {
destroy(C<0>{}); destruct();
i_ = other.move(&buf_, C<0>{}); move_construct(other);
other.i_ = 0;
} }
return *this; return *this;
} }
variant& operator=(variant const& other) variant& operator=(variant const& other)
{ {
if(this != &other) if(this != &other)
{ {
destroy(C<0>{}); destruct();
i_ = other.copy(&buf_, C<0>{}); copy_construct(other);
} }
return *this; return *this;
} }
template<std::size_t I, class... Args> template<std::size_t I, class... Args>
void void
emplace(Args&&... args) emplace(Args&&... args) noexcept
{ {
destroy(C<0>{}); destruct();
new(&buf_) type<I-1>( ::new(&buf_) mp11::mp_at_c<variant, I - 1>(
std::forward<Args>(args)...); std::forward<Args>(args)...);
i_ = I; i_ = I;
} }
template<std::size_t I> template<std::size_t I>
type<I-1>& mp11::mp_at_c<variant, I - 1>&
get() get()
{ {
BOOST_ASSERT(i_ == I); BOOST_ASSERT(i_ == I);
return *reinterpret_cast< return *reinterpret_cast<
type<I-1>*>(&buf_); mp11::mp_at_c<variant, I - 1>*>(&buf_);
} }
template<std::size_t I> template<std::size_t I>
type<I-1> const& mp11::mp_at_c<variant, I - 1> const&
get() const get() const
{ {
BOOST_ASSERT(i_ == I); BOOST_ASSERT(i_ == I);
return *reinterpret_cast< return *reinterpret_cast<
type<I-1> const*>(&buf_); mp11::mp_at_c<variant, I - 1> const*>(&buf_);
} }
void void
reset() reset()
{ {
destroy(C<0>{}); destruct();
}
private:
void
destroy(C<0>)
{
auto const I = 0;
if(i_ == I)
return;
destroy(C<I+1>{});
i_ = 0;
}
template<std::size_t I>
void
destroy(C<I>)
{
if(i_ == I)
{
using T = type<I-1>;
get<I>().~T();
return;
}
destroy(C<I+1>{});
}
void
destroy(C<sizeof...(TN)>)
{
auto const I = sizeof...(TN);
BOOST_ASSERT(i_ == I);
using T = type<I-1>;
get<I>().~T();
}
unsigned char
move(void* dest, C<0>)
{
auto const I = 0;
if(i_ == I)
return I;
return move(dest, C<I+1>{});
}
template<std::size_t I>
unsigned char
move(void* dest, C<I>)
{
if(i_ == I)
{
using T = type<I-1>;
new(dest) T(std::move(get<I>()));
get<I>().~T();
return I;
}
return move(dest, C<I+1>{});
}
unsigned char
move(void* dest, C<sizeof...(TN)>)
{
auto const I = sizeof...(TN);
BOOST_ASSERT(i_ == I);
using T = type<I-1>;
new(dest) T(std::move(get<I>()));
get<I>().~T();
return I;
}
unsigned char
copy(void* dest, C<0>) const
{
auto const I = 0;
if(i_ == I)
return I;
return copy(dest, C<I+1>{});
}
template<std::size_t I>
unsigned char
copy(void* dest, C<I>) const
{
if(i_ == I)
{
using T = type<I-1>;
auto const& t = get<I>();
new(dest) T(t);
return I;
}
return copy(dest, C<I+1>{});
}
unsigned char
copy(void* dest, C<sizeof...(TN)>) const
{
auto const I = sizeof...(TN);
BOOST_ASSERT(i_ == I);
using T = type<I-1>;
auto const& t = get<I>();
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<I+1>{});
}
template<std::size_t I>
bool
equal(variant const& other, C<I>) const
{
if(i_ == I)
return get<I>() == other.get<I>();
return equal(other, C<I+1>{});
}
bool
equal(variant const& other, C<sizeof...(TN)>) const
{
auto constexpr I = sizeof...(TN);
BOOST_ASSERT(i_ == I);
return get<I>() == other.get<I>();
} }
}; };