Skip to content

Commit

Permalink
add tests for [container.reqmts]
Browse files Browse the repository at this point in the history
  • Loading branch information
wusatosi committed Nov 21, 2024
1 parent cfbc617 commit 446426c
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 16 deletions.
29 changes: 13 additions & 16 deletions include/beman/inplace_vector/inplace_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,24 @@ struct inplace_vector_destruct_base {
// [containers.sequences.inplace.vector.cons], construct/copy/destroy
constexpr inplace_vector_destruct_base() = default;

inplace_vector_destruct_base(
constexpr inplace_vector_destruct_base(
const inplace_vector_destruct_base
&other) noexcept(std::is_nothrow_copy_constructible_v<T>)
: elems(), size_(other.size_) {}

inplace_vector_destruct_base(
constexpr inplace_vector_destruct_base(
const inplace_vector_destruct_base
&&other) noexcept(std::is_nothrow_move_constructible_v<T>)
: elems(), size_(other.size()) {}
: elems(), size_(other.size_) {}

inplace_vector_destruct_base &
constexpr inplace_vector_destruct_base &
operator=(const inplace_vector_destruct_base &other) noexcept(
std::is_nothrow_copy_constructible_v<T> &&
std::is_nothrow_copy_assignable_v<T>) {
size_ = other.size_;
}

inplace_vector_destruct_base &
constexpr inplace_vector_destruct_base &
operator=(const inplace_vector_destruct_base &&other) noexcept(
std::is_nothrow_move_constructible_v<T> &&
std::is_nothrow_move_assignable_v<T>) {
Expand All @@ -142,19 +142,18 @@ struct inplace_vector_base : public inplace_vector_destruct_base<T, Capacity> {

// [containers.sequences.inplace.vector.cons], construct/copy/destroy
constexpr inplace_vector_base() = default;
inplace_vector_base(const inplace_vector_base &other) noexcept(
constexpr inplace_vector_base(const inplace_vector_base &other) noexcept(
std::is_nothrow_copy_constructible_v<T>)
: inplace_vector_destruct_base<T, Capacity>(other.size) {
: inplace_vector_destruct_base<T, Capacity>(other.size_) {
std::copy(other.begin(), other.end(), begin());
}
inplace_vector_base(inplace_vector_base &&other) noexcept(
constexpr inplace_vector_base(inplace_vector_base &&other) noexcept(
Capacity == 0 || std::is_nothrow_move_constructible_v<T>)
: inplace_vector_destruct_base<T, Capacity>(other.size_) {
std::copy(other.begin(), other.end(), begin());
std::destroy(other.begin(), other.end());
other.size_ = 0;
}
inplace_vector_base &operator=(const inplace_vector_base &other) noexcept(
constexpr inplace_vector_base &
operator=(const inplace_vector_base &other) noexcept(
std::is_nothrow_copy_constructible_v<T> &&
std::is_nothrow_copy_assignable_v<T>) {
const auto diff = static_cast<std::ptrdiff_t>(other.size() - size());
Expand All @@ -175,7 +174,8 @@ struct inplace_vector_base : public inplace_vector_destruct_base<T, Capacity> {
return *this;
}

inplace_vector_base &operator=(inplace_vector_base &&other) noexcept(
constexpr inplace_vector_base &
operator=(inplace_vector_base &&other) noexcept(
Capacity == 0 || (std::is_nothrow_move_constructible_v<T> &&
std::is_nothrow_move_assignable_v<T>)) {
const auto diff = static_cast<std::ptrdiff_t>(other.size() - size());
Expand All @@ -185,13 +185,10 @@ struct inplace_vector_base : public inplace_vector_destruct_base<T, Capacity> {
std::destroy(new_end, end());
// other size is grater than size
} else {
std::move(other, other.begin(), other.begin() + size(), begin());
std::move(other.begin(), other.begin() + size(), begin());
std::move(other.begin() + size(), other.end(), end());
}
this->size_ = other.size();
std::destroy(other.begin(), other.end());
// reset size to zero
other.change_size(-static_cast<std::ptrdiff_t>(other.size()));
return *this;
}
constexpr inplace_vector_base(const size_type size)
Expand Down
125 changes: 125 additions & 0 deletions tests/beman/inplace_vector/constexpr.test.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <algorithm>
#include <beman/inplace_vector/inplace_vector.hpp>
#include <functional>
#include <type_traits>
Expand Down Expand Up @@ -148,6 +149,130 @@ static_assert(std::invoke([]() {
}),
"Basic mutation");

// [container.reqmts] General container requirements
using X = inplace_vector<int, 5>;

constexpr bool reqmts_default() {
{
X u;
S_ASSERT(u.empty());
}
{
X u = X();
S_ASSERT(u.empty());
}

return true;
}

static_assert(reqmts_default());

constexpr bool reqmts_copy() {
constexpr X exp{1, 2, 3};

X a{1, 2, 3};

{
X u(a);
S_ASSERT(std::ranges::equal(exp, u));
S_ASSERT(std::ranges::equal(exp, a));
}
{
X u = a;
S_ASSERT(std::ranges::equal(exp, u));
S_ASSERT(std::ranges::equal(exp, a));
}

return true;
}

static_assert(reqmts_copy());

constexpr bool reqmts_move() {
/*
* TODO: Need to keep in check with revision
*
* Move semantics
* A moved-from inplace_vector is left in a valid but unspecified state
* (option 3 below) unless T is trivially-copyable, in which case the size of
* the inplace_vector does not change (array semantics, option 2 below). That
* is:
*
* inplace_vector a(10);
* inplace_vector b(std::move(a));
* assert(a.size() == 10); // MAY FAIL
*
* moves a's elements element-wise into b, and afterwards the size of the
* moved-from inplace_vector may have changed.
*
* This prevents code from relying on the size staying the same (and therefore
* being incompatible with changing an inplace_vector type back to vector)
* without incuring the cost of having to clear the inplace_vector.
*
* When T is trivially-copyable, array semantics are used to provide trivial
* move operations.
*/

{
constexpr X exp{1, 2, 3};
X mov_from(exp);
X u(std::move(mov_from));
S_ASSERT(std::ranges::equal(exp, u));

static_assert(std::is_trivially_copyable_v<X::value_type>);
S_ASSERT(mov_from.size() == exp.size());
}
{
// Note(river): for later non-trivial type implementation, verify:
// Effects: All existing elements of a are either move assigned to or
// destroyed.
constexpr X origin{1, 2, 3};
constexpr X exp{1, 2};

X a(origin);
X mov_from(exp);
a = std::move(mov_from);

S_ASSERT(std::ranges::equal(exp, a));
static_assert(std::is_trivially_copyable_v<X::value_type>);
S_ASSERT(mov_from.size() == exp.size());
}

return true;
}

static_assert(reqmts_move());

// destructor implicilty tested

constexpr bool reqmts_itr() {
constexpr X exp{1, 2, 3};

{
X b = exp;
auto beg = b.begin();
auto end = b.end();
end--;

S_ASSERT(*b.begin() == 1);
S_ASSERT(*end == 3);
}

{
X b = exp;
auto beg = b.cbegin();
auto end = b.cend();
end--;

S_ASSERT(*b.begin() == 1);
S_ASSERT(*end == 3);
}

return true;
}

static_assert(reqmts_itr());

int main() {
// compile means pass
}

0 comments on commit 446426c

Please sign in to comment.