mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 05:17:26 +02:00
variant fixes and tests
This commit is contained in:
@ -2,6 +2,7 @@ Version 87:
|
||||
|
||||
* Update appveyor for Boost branch
|
||||
* Rename to BEAST_EXPECT
|
||||
* variant fixes and tests
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -82,6 +82,22 @@ max_sizeof()
|
||||
max_sizeof<U0>() : max_sizeof<U1, Us...>();
|
||||
}
|
||||
|
||||
template<class U>
|
||||
std::size_t constexpr
|
||||
max_alignof()
|
||||
{
|
||||
return alignof(U);
|
||||
}
|
||||
|
||||
template<class U0, class U1, class... Us>
|
||||
std::size_t constexpr
|
||||
max_alignof()
|
||||
{
|
||||
return
|
||||
max_alignof<U0>() > max_alignof<U1, Us...>() ?
|
||||
max_alignof<U0>() : max_alignof<U1, Us...>();
|
||||
}
|
||||
|
||||
template<unsigned N, class T, class... Tn>
|
||||
struct repeat_tuple_impl
|
||||
{
|
||||
|
@ -32,7 +32,9 @@ template<class... TN>
|
||||
class variant
|
||||
{
|
||||
typename std::aligned_storage<
|
||||
max_sizeof<TN...>()>::type buf_;
|
||||
max_sizeof<TN...>(),
|
||||
max_alignof<TN...>()
|
||||
>::type buf_;
|
||||
unsigned char i_ = 0;
|
||||
|
||||
template<std::size_t I>
|
||||
@ -51,6 +53,14 @@ public:
|
||||
destroy(C<0>{});
|
||||
}
|
||||
|
||||
// 0 = empty
|
||||
unsigned char
|
||||
index() const
|
||||
{
|
||||
return i_;
|
||||
}
|
||||
|
||||
// moved-from object becomes empty
|
||||
variant(variant&& other)
|
||||
{
|
||||
i_ = other.move(&buf_, C<0>{});
|
||||
@ -61,6 +71,7 @@ public:
|
||||
i_ = other.copy(&buf_, C<0>{});
|
||||
}
|
||||
|
||||
// moved-from object becomes empty
|
||||
variant& operator=(variant&& other)
|
||||
{
|
||||
if(i_ != 0)
|
||||
@ -83,7 +94,6 @@ public:
|
||||
{
|
||||
if(i_ != 0)
|
||||
destroy(C<0>{});
|
||||
i_ = 0;
|
||||
new(&buf_) type<I-1>(
|
||||
std::forward<Args>(args)...);
|
||||
i_ = I;
|
||||
@ -99,7 +109,7 @@ public:
|
||||
}
|
||||
|
||||
template<std::size_t I>
|
||||
type<I-1>&
|
||||
type<I-1> const&
|
||||
get() const
|
||||
{
|
||||
BOOST_ASSERT(i_ == I);
|
||||
@ -130,6 +140,7 @@ private:
|
||||
{
|
||||
using T = type<I>;
|
||||
get<I+1>().~T();
|
||||
i_ = 0;
|
||||
return;
|
||||
}
|
||||
destroy(C<I+1>{});
|
||||
@ -153,7 +164,7 @@ private:
|
||||
i_ = 0;
|
||||
return I+1;
|
||||
}
|
||||
move(C<I+1>{});
|
||||
return move(dest, C<I+1>{});
|
||||
}
|
||||
|
||||
unsigned char
|
||||
@ -173,7 +184,7 @@ private:
|
||||
new(dest) T{t};
|
||||
return I+1;
|
||||
}
|
||||
copy(C<I+1>{});
|
||||
return copy(dest, C<I+1>{});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -52,5 +52,6 @@ add_executable (core-tests
|
||||
base64.cpp
|
||||
empty_base_optimization.cpp
|
||||
sha1.cpp
|
||||
detail/variant.cpp
|
||||
detail/varint.cpp
|
||||
)
|
||||
|
@ -41,5 +41,6 @@ unit-test core-tests :
|
||||
base64.cpp
|
||||
empty_base_optimization.cpp
|
||||
sha1.cpp
|
||||
detail/variant.cpp
|
||||
detail/varint.cpp
|
||||
;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <boost/beast/core/detail/variant.hpp>
|
||||
|
||||
#include <boost/beast/unit_test/suite.hpp>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
@ -29,17 +30,44 @@ public:
|
||||
return n;
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
bool move = false;
|
||||
bool copy = false;
|
||||
bool move_assign = false;
|
||||
bool copy_assign = false;
|
||||
|
||||
Q() { ++count(); }
|
||||
~Q() { --count(); }
|
||||
Q(Q&&) { ++count(); move = true; }
|
||||
Q(Q const&) { ++count(); copy = true; }
|
||||
Q& operator=(Q&&) { move_assign = true; return *this; }
|
||||
Q& operator=(Q const&) { copy_assign = true; return *this; }
|
||||
Q& operator=(Q&& q) = delete;
|
||||
Q& operator=(Q const& q) = delete;
|
||||
|
||||
~Q()
|
||||
{
|
||||
--count();
|
||||
}
|
||||
|
||||
Q()
|
||||
{
|
||||
++count();
|
||||
}
|
||||
|
||||
Q(Q&& q)
|
||||
{
|
||||
if(q.value < 0)
|
||||
throw std::exception{};
|
||||
++count();
|
||||
move = true;
|
||||
}
|
||||
|
||||
Q(Q const& q)
|
||||
{
|
||||
if(q.value < 0)
|
||||
throw std::exception{};
|
||||
++count();
|
||||
copy = true;
|
||||
}
|
||||
|
||||
explicit Q(int value_)
|
||||
: value(value_)
|
||||
{
|
||||
++count();
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
@ -58,6 +86,9 @@ public:
|
||||
v.emplace<1>(10);
|
||||
BEAST_EXPECT(v.index() == 1);
|
||||
BEAST_EXPECT(v.get<1>() == 10);
|
||||
v.emplace<1>(20);
|
||||
BEAST_EXPECT(v.index() == 1);
|
||||
BEAST_EXPECT(v.get<1>() == 20);
|
||||
}
|
||||
{
|
||||
variant<std::string> v;
|
||||
@ -70,6 +101,10 @@ public:
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
v.emplace<1>();
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
BEAST_EXPECT(v.get<1>().value == 0);
|
||||
v.emplace<1>(42);
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
BEAST_EXPECT(v.get<1>().value == 42);
|
||||
v.reset();
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
}
|
||||
@ -200,40 +235,51 @@ public:
|
||||
BEAST_EXPECT(v2.index() == 0);
|
||||
BEAST_EXPECT(v3.get<1>() == "Hello");
|
||||
}
|
||||
{
|
||||
variant<Q<1>, Q<2>> v1;
|
||||
variant<Q<1>, Q<2>> v2;
|
||||
v1.emplace<1>();
|
||||
BEAST_EXPECT(v1.index() == 1);
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
v2.emplace<2>();
|
||||
BEAST_EXPECT(v2.index() == 2);
|
||||
BEAST_EXPECT(Q<2>::count() == 1);
|
||||
v2 = std::move(v1);
|
||||
BEAST_EXPECT(v1.index() == 0);
|
||||
BEAST_EXPECT(v2.index() == 1);
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
BEAST_EXPECT(Q<2>::count() == 0);
|
||||
}
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
BEAST_EXPECT(Q<2>::count() == 0);
|
||||
{
|
||||
variant<Q<1>> v1;
|
||||
v1.emplace<1>();
|
||||
BEAST_EXPECT(! v1.get<1>().move_assign);
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
variant<Q<1>> v2;
|
||||
v2.emplace<1>();
|
||||
BEAST_EXPECT(Q<1>::count() == 2);
|
||||
BEAST_EXPECT(! v2.get<1>().move_assign);
|
||||
v2 = std::move(v1);
|
||||
BEAST_EXPECT(v1.index() == 0);
|
||||
BEAST_EXPECT(v2.index() == 1);
|
||||
BEAST_EXPECT(v2.get<1>().move);
|
||||
BEAST_EXPECT(!v2.get<1>().move_assign);
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
}
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
{
|
||||
variant<Q<1>, Q<2>, Q<3>> v1;
|
||||
v1.emplace<2>();
|
||||
BEAST_EXPECT(! v1.get<2>().move_assign);
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
BEAST_EXPECT(Q<2>::count() == 1);
|
||||
BEAST_EXPECT(Q<3>::count() == 0);
|
||||
variant<Q<1>, Q<2>, Q<3>> v2;
|
||||
v2.emplace<2>();
|
||||
BEAST_EXPECT(! v2.get<2>().move_assign);
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
BEAST_EXPECT(Q<2>::count() == 2);
|
||||
BEAST_EXPECT(Q<3>::count() == 0);
|
||||
v2 = std::move(v1);
|
||||
BEAST_EXPECT(v1.index() == 0);
|
||||
BEAST_EXPECT(v2.index() == 2);
|
||||
BEAST_EXPECT(! v2.get<2>().move_assign);
|
||||
BEAST_EXPECT(v2.get<2>().move);
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
BEAST_EXPECT(Q<2>::count() == 1);
|
||||
@ -257,19 +303,31 @@ public:
|
||||
BEAST_EXPECT(v2.get<1>() == "Hello");
|
||||
BEAST_EXPECT(v3.get<1>() == "Hello");
|
||||
}
|
||||
{
|
||||
variant<Q<1>, Q<2>> v1;
|
||||
variant<Q<1>, Q<2>> v2;
|
||||
v1.emplace<1>();
|
||||
BEAST_EXPECT(v1.index() == 1);
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
v2.emplace<2>();
|
||||
BEAST_EXPECT(v2.index() == 2);
|
||||
BEAST_EXPECT(Q<2>::count() == 1);
|
||||
v2 = v1;
|
||||
BEAST_EXPECT(v1.index() == 1);
|
||||
BEAST_EXPECT(v2.index() == 1);
|
||||
BEAST_EXPECT(Q<1>::count() == 2);
|
||||
BEAST_EXPECT(Q<2>::count() == 0);
|
||||
}
|
||||
{
|
||||
variant<Q<1>> v1;
|
||||
v1.emplace<1>();
|
||||
BEAST_EXPECT(! v1.get<1>().copy_assign);
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
variant<Q<1>> v2;
|
||||
v2.emplace<1>();
|
||||
BEAST_EXPECT(Q<1>::count() == 2);
|
||||
BEAST_EXPECT(! v2.get<1>().copy_assign);
|
||||
v2 = v1;
|
||||
BEAST_EXPECT(v1.index() == 1);
|
||||
BEAST_EXPECT(v2.index() == 1);
|
||||
BEAST_EXPECT(! v2.get<1>().copy_assign);
|
||||
BEAST_EXPECT(v2.get<1>().copy);
|
||||
BEAST_EXPECT(Q<1>::count() == 2);
|
||||
}
|
||||
@ -277,20 +335,17 @@ public:
|
||||
{
|
||||
variant<Q<1>, Q<2>, Q<3>> v1;
|
||||
v1.emplace<2>();
|
||||
BEAST_EXPECT(! v1.get<2>().copy_assign);
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
BEAST_EXPECT(Q<2>::count() == 1);
|
||||
BEAST_EXPECT(Q<3>::count() == 0);
|
||||
variant<Q<1>, Q<2>, Q<3>> v2;
|
||||
v2.emplace<2>();
|
||||
BEAST_EXPECT(! v2.get<2>().copy_assign);
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
BEAST_EXPECT(Q<2>::count() == 2);
|
||||
BEAST_EXPECT(Q<3>::count() == 0);
|
||||
v2 = v1;
|
||||
BEAST_EXPECT(v1.index() == 2);
|
||||
BEAST_EXPECT(v2.index() == 2);
|
||||
BEAST_EXPECT(! v2.get<2>().copy_assign);
|
||||
BEAST_EXPECT(v2.get<2>().copy);
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
BEAST_EXPECT(Q<2>::count() == 2);
|
||||
@ -340,6 +395,48 @@ public:
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
BEAST_EXPECT(Q<2>::count() == 0);
|
||||
BEAST_EXPECT(Q<3>::count() == 0);
|
||||
|
||||
// basic guarantee
|
||||
{
|
||||
// move
|
||||
variant<Q<1>> v1;
|
||||
v1.emplace<1>();
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
variant<Q<1>> v2;
|
||||
v2.emplace<1>(-1);
|
||||
BEAST_EXPECT(Q<1>::count() == 2);
|
||||
try
|
||||
{
|
||||
v1 = std::move(v2);
|
||||
fail();
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
BEAST_EXPECT(v1.index() == 0);
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
}
|
||||
}
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
{
|
||||
// copy
|
||||
variant<Q<1>> v1;
|
||||
v1.emplace<1>();
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
variant<Q<1>> v2;
|
||||
v2.emplace<1>(-1);
|
||||
BEAST_EXPECT(Q<1>::count() == 2);
|
||||
try
|
||||
{
|
||||
v1 = v2;
|
||||
fail();
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
BEAST_EXPECT(v1.index() == 0);
|
||||
BEAST_EXPECT(Q<1>::count() == 1);
|
||||
}
|
||||
}
|
||||
BEAST_EXPECT(Q<1>::count() == 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
Reference in New Issue
Block a user