summaryrefslogtreecommitdiff
path: root/boost/beast/core/detail/variant.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/core/detail/variant.hpp')
-rw-r--r--boost/beast/core/detail/variant.hpp144
1 files changed, 108 insertions, 36 deletions
diff --git a/boost/beast/core/detail/variant.hpp b/boost/beast/core/detail/variant.hpp
index cba6ba63c0..536cb7593f 100644
--- a/boost/beast/core/detail/variant.hpp
+++ b/boost/beast/core/detail/variant.hpp
@@ -31,15 +31,12 @@ namespace detail {
template<class... TN>
class variant
{
- typename std::aligned_storage<
- max_sizeof<TN...>(),
- max_alignof<TN...>()
- >::type buf_;
+ detail::aligned_union_t<1, TN...> buf_;
unsigned char i_ = 0;
template<std::size_t I>
using type = typename std::tuple_element<
- I , std::tuple<TN...>>::type;
+ I, std::tuple<TN...>>::type;
template<std::size_t I>
using C = std::integral_constant<std::size_t, I>;
@@ -49,8 +46,15 @@ public:
~variant()
{
- if(i_)
- destroy(C<0>{});
+ destroy(C<0>{});
+ }
+
+ bool
+ operator==(variant const& other) const
+ {
+ if(i_ != other.i_)
+ return false;
+ return equal(other, C<0>{});
}
// 0 = empty
@@ -64,6 +68,7 @@ public:
variant(variant&& other)
{
i_ = other.move(&buf_, C<0>{});
+ other.i_ = 0;
}
variant(variant const& other)
@@ -74,17 +79,22 @@ public:
// moved-from object becomes empty
variant& operator=(variant&& other)
{
- if(i_ != 0)
+ if(this != &other)
+ {
destroy(C<0>{});
- i_ = other.move(&buf_, C<0>{});
+ i_ = other.move(&buf_, C<0>{});
+ other.i_ = 0;
+ }
return *this;
}
variant& operator=(variant const& other)
{
- if(i_ != 0)
+ if(this != &other)
+ {
destroy(C<0>{});
- i_ = other.copy(&buf_, C<0>{});
+ i_ = other.copy(&buf_, C<0>{});
+ }
return *this;
}
@@ -92,8 +102,7 @@ public:
void
emplace(Args&&... args)
{
- if(i_ != 0)
- destroy(C<0>{});
+ destroy(C<0>{});
new(&buf_) type<I-1>(
std::forward<Args>(args)...);
i_ = I;
@@ -120,72 +129,135 @@ public:
void
reset()
{
- if(i_ == 0)
- return;
destroy(C<0>{});
}
private:
void
- destroy(C<sizeof...(TN)>)
+ destroy(C<0>)
{
- return;
+ 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+1)
+ if(i_ == I)
{
- using T = type<I>;
- get<I+1>().~T();
- i_ = 0;
+ 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*, C<sizeof...(TN)>)
+ move(void* dest, C<0>)
{
- return 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+1)
+ if(i_ == I)
{
- using T = type<I>;
- new(dest) T{std::move(get<I+1>())};
- get<I+1>().~T();
- i_ = 0;
- return I+1;
+ 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
- copy(void*, C<sizeof...(TN)>) const
+ 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
{
- return 0;
+ 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+1)
+ if(i_ == I)
{
- using T = type<I>;
- auto const& t = get<I+1>();
- new(dest) T{t};
- return I+1;
+ 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>();
+ }
};
} // detail