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