From 3e0705662dd821ea22cbaea05d13d91e26b3d736 Mon Sep 17 00:00:00 2001 From: KRM7 <70973547+KRM7@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:43:50 +0100 Subject: [PATCH] insert/emplace implementation improvements --- README.md | 115 ++++++++++------------ benchmark/small_vector.cpp | 29 ++++-- src/small_vector.hpp | 194 +++++++++++++++++++++++++------------ test/small_vector.cpp | 43 ++++---- 4 files changed, 227 insertions(+), 154 deletions(-) diff --git a/README.md b/README.md index 20a6d1b..e969977 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,86 @@ +### `small_vector` + ```shell g++ 12.3.0 -std=c++20 -O3 -flto -DNDEBUG ``` ```shell -small_vector_benchmark --benchmark_enable_random_interleaving=true --benchmark_repetitions=10 +small_vector_benchmark --benchmark_min_warmup_time=2 ``` ```text ------------------------------------------------------------------------------------------------------------------ -Benchmark Time CPU Iterations ------------------------------------------------------------------------------------------------------------------ +---------------------------------------------------------------------------------------------------------- +Benchmark Time CPU Iterations +---------------------------------------------------------------------------------------------------------- // construct_from_size -benchmark_construct_from_size>/size:4_median 11.1 ns 11.1 ns 10 -benchmark_construct_from_size>/size:4_median 1.84 ns 1.84 ns 10 - -benchmark_construct_from_size>/size:100_median 11.5 ns 11.5 ns 10 -benchmark_construct_from_size>/size:100_median 11.5 ns 11.5 ns 10 - -// construct_size_value -benchmark_construct_from_size_value>/size:4_median 10.2 ns 10.2 ns 10 -benchmark_construct_from_size_value>/size:4_median 1.61 ns 1.61 ns 10 +benchmark_construct_from_size>/size:4 11.1 ns 11.1 ns 63128125 +benchmark_construct_from_size>/size:100 11.5 ns 11.5 ns 60983419 +benchmark_construct_from_size>/size:4 1.85 ns 1.85 ns 379357325 +benchmark_construct_from_size>/size:100 11.7 ns 11.7 ns 59806415 -benchmark_construct_from_size_value>/size:100_median 16.4 ns 16.4 ns 10 -benchmark_construct_from_size_value>/size:100_median 17.5 ns 17.5 ns 10 +// construct_from_size_value +benchmark_construct_from_size_value>/size:4 10.6 ns 10.6 ns 66230178 +benchmark_construct_from_size_value>/size:100 17.2 ns 17.2 ns 41003124 +benchmark_construct_from_size_value>/size:4 1.84 ns 1.84 ns 379785020 +benchmark_construct_from_size_value>/size:100 17.7 ns 17.7 ns 39628556 // construct_from_range -benchmark_construct_from_range>/size:4_median 11.4 ns 11.4 ns 10 -benchmark_construct_from_range>/size:4_median 2.31 ns 2.31 ns 10 - -benchmark_construct_from_range>/size:100_median 12.7 ns 12.7 ns 10 -benchmark_construct_from_range>/size:100_median 13.4 ns 13.4 ns 10 +benchmark_construct_from_range>/size:4 11.4 ns 11.4 ns 61351468 +benchmark_construct_from_range>/size:100 12.6 ns 12.6 ns 55381324 +benchmark_construct_from_range>/size:4 2.31 ns 2.31 ns 303092496 +benchmark_construct_from_range>/size:100 13.2 ns 13.2 ns 53144806 // assign_reserved -benchmark_assign_reserved>/size:4_median 2.53 ns 2.53 ns 10 -benchmark_assign_reserved>/size:4_median 2.32 ns 2.32 ns 10 - -benchmark_assign_reserved>/size:100_median 4.38 ns 4.38 ns 10 -benchmark_assign_reserved>/size:100_median 4.61 ns 4.61 ns 10 +benchmark_assign_reserved>/size:4 2.30 ns 2.30 ns 300733274 +benchmark_assign_reserved>/size:100 4.93 ns 4.93 ns 141963555 +benchmark_assign_reserved>/size:4 2.30 ns 2.30 ns 303034501 +benchmark_assign_reserved>/size:100 5.28 ns 5.28 ns 132612176 // swap -benchmark_swap>/size:4_median 1.34 ns 1.34 ns 10 -benchmark_swap>/size:4_median 3.92 ns 3.92 ns 10 - -benchmark_swap>/size:100_median 1.34 ns 1.34 ns 10 -benchmark_swap>/size:100_median 1.84 ns 1.84 ns 10 +benchmark_swap>/size:4 1.34 ns 1.34 ns 518765605 +benchmark_swap>/size:100 1.33 ns 1.33 ns 522469939 +benchmark_swap>/size:4 4.15 ns 4.15 ns 168877555 +benchmark_swap>/size:100 1.84 ns 1.84 ns 380621991 // resize -benchmark_resize>/size:4_median 1.61 ns 1.61 ns 10 -benchmark_resize>/size:4_median 2.77 ns 2.77 ns 10 - -benchmark_resize>/size:100_median 1.61 ns 1.61 ns 10 -benchmark_resize>/size:100_median 2.77 ns 2.77 ns 10 +benchmark_resize>/size:4 2.54 ns 2.54 ns 275839458 +benchmark_resize>/size:100 3.67 ns 3.67 ns 197377975 +benchmark_resize>/size:4 1.87 ns 1.87 ns 376250226 +benchmark_resize>/size:100 3.28 ns 3.28 ns 215127588 // push_back_reserved -benchmark_push_back_reserved>/size:4_median 0.923 ns 0.923 ns 10 -benchmark_push_back_reserved>/size:4_median 0.952 ns 0.952 ns 10 - -benchmark_push_back_reserved>/size:100_median 0.923 ns 0.923 ns 10 -benchmark_push_back_reserved>/size:100_median 0.952 ns 0.952 ns 10 +benchmark_push_back_reserved>/size:4 0.613 ns 0.613 ns 1000000000 +benchmark_push_back_reserved>/size:100 0.618 ns 0.618 ns 1000000000 +benchmark_push_back_reserved>/size:4 0.562 ns 0.562 ns 1000000000 +benchmark_push_back_reserved>/size:100 0.617 ns 0.618 ns 1000000000 // push_back_reallocate -benchmark_push_back_reallocate>/size:100_median 143 ns 143 ns 10 -benchmark_push_back_reallocate>/size:100_median 126 ns 126 ns 10 +benchmark_push_back_reallocate>/size:100 144 ns 144 ns 4641722 +benchmark_push_back_reallocate>/size:100 148 ns 148 ns 4781649 // insert_one_reserved -benchmark_insert_one_reserved>/size:4_median 4.63 ns 4.63 ns 10 -benchmark_insert_one_reserved>/size:4_median 4.61 ns 4.61 ns 10 - -benchmark_insert_one_reserved>/size:100_median 8.20 ns 8.20 ns 10 -benchmark_insert_one_reserved>/size:100_median 7.74 ns 7.74 ns 10 +benchmark_insert_one_reserved>/size:4 4.66 ns 4.66 ns 150091813 +benchmark_insert_one_reserved>/size:100 8.01 ns 8.01 ns 85894208 +benchmark_insert_one_reserved>/size:4 4.65 ns 4.65 ns 149969588 +benchmark_insert_one_reserved>/size:100 8.17 ns 8.17 ns 86572377 // insert_one_reallocate -benchmark_insert_one_reallocate>/size:100_median 737 ns 737 ns 10 -benchmark_insert_one_reallocate>/size:100_median 747 ns 747 ns 10 +benchmark_insert_one_reallocate>/size:100 728 ns 728 ns 965758 +benchmark_insert_one_reallocate>/size:100 752 ns 752 ns 939354 // insert_range_reserved -benchmark_insert_range_reserved>/size:4_median 5.30 ns 5.30 ns 10 -benchmark_insert_range_reserved>/size:4_median 6.46 ns 6.46 ns 10 - -benchmark_insert_range_reserved>/size:100_median 8.56 ns 8.56 ns 10 -benchmark_insert_range_reserved>/size:100_median 6.45 ns 6.45 ns 10 +benchmark_insert_range_reserved>/size:4 6.12 ns 6.12 ns 116646059 +benchmark_insert_range_reserved>/size:100 8.62 ns 8.62 ns 82369900 +benchmark_insert_range_reserved>/size:4 6.26 ns 6.26 ns 112617323 +benchmark_insert_range_reserved>/size:100 6.29 ns 6.29 ns 112590153 // insert_range_reallocate -benchmark_insert_range_reallocate>/size:100_median 234 ns 233 ns 10 -benchmark_insert_range_reallocate>/size:100_median 251 ns 251 ns 10 +benchmark_insert_range_reallocate>/size:100 255 ns 255 ns 2707667 +benchmark_insert_range_reallocate>/size:100 229 ns 229 ns 3066817 // erase_front -benchmark_erase>/size:4_median 4.84 ns 4.84 ns 10 -benchmark_erase>/size:4_median 5.54 ns 5.54 ns 10 - -benchmark_erase>/size:100_median 8.43 ns 8.43 ns 10 -benchmark_erase>/size:100_median 8.36 ns 8.36 ns 10 - +benchmark_erase>/size:4 4.88 ns 4.88 ns 143511026 +benchmark_erase>/size:100 8.51 ns 8.51 ns 82108933 +benchmark_erase>/size:4 4.62 ns 4.62 ns 150378007 +benchmark_erase>/size:100 8.53 ns 8.53 ns 82985683 ``` \ No newline at end of file diff --git a/benchmark/small_vector.cpp b/benchmark/small_vector.cpp index 5f1a191..b926a88 100644 --- a/benchmark/small_vector.cpp +++ b/benchmark/small_vector.cpp @@ -11,10 +11,11 @@ inline constexpr size_t LARGE_SIZE = 100; template void benchmark_construct_from_size(benchmark::State& state) { - const size_t size = state.range(0); + size_t size = state.range(0); for (auto _ : state) { + benchmark::DoNotOptimize(size); V vec(size); benchmark::DoNotOptimize(vec); benchmark::ClobberMemory(); @@ -29,11 +30,14 @@ BENCHMARK(benchmark_construct_from_size>)->ArgName("size")->Ar template void benchmark_construct_from_size_value(benchmark::State& state) { - const size_t size = state.range(0); + size_t size = state.range(0); + int value = 2; for (auto _ : state) { - V vec(size, 2); + benchmark::DoNotOptimize(size); + benchmark::DoNotOptimize(value); + V vec(size, value); benchmark::DoNotOptimize(vec); benchmark::ClobberMemory(); } @@ -47,10 +51,11 @@ BENCHMARK(benchmark_construct_from_size_value>)->ArgName("size template void benchmark_construct_from_range(benchmark::State& state) { - const V src(state.range(0), 0); + V src(state.range(0), 0); for (auto _ : state) { + benchmark::DoNotOptimize(src); V vec(src.begin(), src.end()); benchmark::DoNotOptimize(vec); benchmark::ClobberMemory(); @@ -72,6 +77,8 @@ void benchmark_assign_reserved(benchmark::State& state) for (auto _ : state) { + benchmark::DoNotOptimize(src); + dst.clear(); benchmark::DoNotOptimize(dst); @@ -113,12 +120,14 @@ BENCHMARK(benchmark_swap>)->ArgName("size")->Arg(SMALL_SIZE)-> template void benchmark_resize(benchmark::State& state) { - const size_t size = state.range(0); + size_t size = state.range(0); V vec(size); for (auto _ : state) { + benchmark::DoNotOptimize(size); + vec.resize(0); benchmark::DoNotOptimize(vec); @@ -236,13 +245,16 @@ void benchmark_insert_range_reserved(benchmark::State& state) const size_t size = state.range(0); V vec(size + 3, 1); + V rng = { 1, 2, 3 }; for (auto _ : state) { + benchmark::DoNotOptimize(rng); + vec.resize(size); benchmark::DoNotOptimize(vec); - vec.insert(vec.begin(), { 1, 2, 3 }); + vec.insert(vec.begin(), rng.begin(), rng.end()); benchmark::DoNotOptimize(vec); benchmark::ClobberMemory(); @@ -260,14 +272,17 @@ void benchmark_insert_range_reallocate(benchmark::State& state) const size_t final_size = state.range(0); const size_t start_size = small_vector::inline_capacity(); + V rng = { 1, 2, 3 }; + for (auto _ : state) { V vec(start_size); while (vec.size() < final_size) { + benchmark::DoNotOptimize(rng); benchmark::DoNotOptimize(vec); - vec.insert(vec.begin(), { 1, 2, 3 }); + vec.insert(vec.begin(), rng.begin(), rng.end()); benchmark::ClobberMemory(); } } diff --git a/src/small_vector.hpp b/src/small_vector.hpp index f807b7b..07090c7 100644 --- a/src/small_vector.hpp +++ b/src/small_vector.hpp @@ -322,11 +322,7 @@ namespace detail constexpr const T& operator*() const noexcept { return data_; } private: - union - { - unsigned char dummy_ = {}; - T data_; - }; + union { T data_; }; Allocator& alloc_; }; @@ -498,11 +494,11 @@ class small_vector constexpr void assign(size_type count, const T& value) { - const auto src_size = static_cast(count); + const auto src_size = difference_type(count); const auto old_size = std::distance(first_, last_); const auto com_size = std::min(old_size, src_size); - if (capacity() >= count) + if (last_alloc_ - first_ >= difference_type(count)) { detail::assign_range(first_, first_ + com_size, value); detail::construct_range(alloc_, first_ + com_size, first_ + src_size, value); @@ -529,7 +525,7 @@ class small_vector const auto old_size = std::distance(first_, last_); const auto com_size = std::min(old_size, src_size); - if (capacity() >= size_type(src_size)) + if (last_alloc_ - first_ >= src_size) { detail::assign_range(first_, first_ + com_size, src_first); detail::construct_range(alloc_, first_ + com_size, first_ + src_size, src_first + com_size); @@ -713,6 +709,7 @@ class small_vector constexpr bool empty() const noexcept { return first_ == last_; } constexpr size_type size() const noexcept { return size_type(last_ - first_); } + constexpr difference_type ssize() const noexcept { return last_ - first_; } constexpr size_type capacity() const noexcept { return size_type(last_alloc_ - first_); } constexpr size_type max_size() const noexcept { return std::allocator_traits::max_size(alloc_); } @@ -793,9 +790,7 @@ class small_vector constexpr reference emplace_back(Args&&... args) { if (last_ != last_alloc_) return emplace_back_unchecked(std::forward(args)...); - - reallocate_append(next_capacity(), std::forward(args)...); - return back(); + return *reallocate_append(next_capacity(), std::forward(args)...); } template @@ -818,64 +813,73 @@ class small_vector template constexpr iterator emplace(const_iterator pos, Args&&... args) { - if (pos == cend()) return std::addressof(emplace_back(std::forward(args)...)); + if (last_ != last_alloc_) + { + if (pos == cend()) return std::addressof(emplace_back_unchecked(std::forward(args)...)); - detail::allocator_managed new_elem(alloc_, std::forward(args)...); + detail::allocator_managed new_elem(alloc_, std::forward(args)...); - const auto offset = std::distance(cbegin(), pos); + const difference_type offset = std::distance(cbegin(), pos); - if (size() == capacity()) reallocate_n(next_capacity()); - detail::construct(alloc_, last_, std::move(back())); - std::shift_right(first_ + offset, last_++, 1); - *(first_ + offset) = std::move(*new_elem); - return first_ + offset; + detail::construct(alloc_, last_, std::move(back())); + std::shift_right(first_ + offset, last_++, 1); + *(first_ + offset) = std::move(*new_elem); + return first_ + offset; + } + + return reallocate_emplace(next_capacity(), pos, std::forward(args)...); } constexpr iterator insert(const_iterator pos, size_type count, const T& value) { - const auto offset = std::distance(cbegin(), pos); - const auto src_size = static_cast(count); - const auto new_size = size() + count; - - reserve(new_size); - - const auto middle = std::max(last_ - src_size, first_ + offset); - const auto moved_size = last_ - middle; - const auto new_last = last_ + src_size; - const auto new_middle = last_ + src_size - moved_size; - const auto old_last = last_; - - detail::construct_range(alloc_, last_, new_middle, value); - last_ = new_middle; - detail::relocate_range_weak(alloc_, middle, old_last, new_middle); - last_ = new_last; - detail::assign_range(middle, old_last, value); + if (last_alloc_ - last_ >= count) + { + const difference_type offset = std::distance(cbegin(), pos); + const difference_type src_size = difference_type(count); + + const auto middle = first_ + std::max(ssize() - src_size, offset); + const auto moved_size = last_ - middle; + const auto old_last = last_; + const auto new_last = last_ + src_size; + const auto new_middle = middle + src_size; + + detail::construct_range(alloc_, last_, new_middle, value); + last_ = new_middle; + detail::relocate_range_weak(alloc_, middle, old_last, new_middle); + last_ = new_last; + detail::assign_range(middle, old_last, value); + + return first_ + offset; + } - return first_ + offset; + return reallocate_insert(next_capacity(count), pos, count, value); } template constexpr iterator insert(const_iterator pos, Iter src_first, Iter src_last) { - const auto offset = std::distance(cbegin(), pos); - const auto src_size = std::distance(src_first, src_last); - const auto new_size = size() + src_size; + const difference_type src_size = std::distance(src_first, src_last); - reserve(new_size); + if (last_alloc_ - last_ >= src_size) + { + const difference_type offset = std::distance(cbegin(), pos); - const auto middle = std::max(last_ - src_size, first_ + offset); - const auto moved_size = last_ - middle; - const auto new_last = last_ + src_size; - const auto new_middle = last_ + src_size - moved_size; - const auto old_last = last_; + const auto middle = first_ + std::max(ssize() - src_size, offset); + const auto moved_size = last_ - middle; + const auto old_last = last_; + const auto new_last = last_ + src_size; + const auto new_middle = middle + src_size; - detail::construct_range(alloc_, last_, new_middle, src_first + moved_size); - last_ = new_middle; - detail::relocate_range_weak(alloc_, middle, old_last, new_middle); - last_ = new_last; - detail::assign_range(middle, old_last, src_first); + detail::construct_range(alloc_, last_, new_middle, std::next(src_first, moved_size)); + last_ = new_middle; + detail::relocate_range_weak(alloc_, middle, old_last, new_middle); + last_ = new_last; + detail::assign_range(middle, old_last, src_first); - return first_ + offset; + return first_ + offset; + } + + return reallocate_insert(next_capacity(size_type(src_size)), pos, src_first, src_last); } template @@ -885,7 +889,7 @@ class small_vector const auto old_size = std::distance(first_, last_); while (src_first != src_last) emplace_back(*src_first++); - std::rotate(first_ + offset, first_ + difference_type(old_size), last_); + std::rotate(first_ + offset, first_ + old_size, last_); return first_ + offset; } @@ -929,16 +933,12 @@ class small_vector constexpr void allocate_n(size_type count) { - if (count <= buffer_.size()) - { - set_buffer_storage(0); - } - else - { - detail::alloc_result_t alloc_result = detail::allocate(alloc_, count); - first_ = alloc_result.data; - last_alloc_ = alloc_result.data + alloc_result.size; - } + if (count <= inline_capacity()) return set_buffer_storage(0); + + detail::alloc_result_t alloc_result = detail::allocate(alloc_, count); + first_ = alloc_result.data; + last_ = alloc_result.data; + last_alloc_ = alloc_result.data + alloc_result.size; } constexpr void reallocate_n(size_type new_capacity) @@ -955,7 +955,7 @@ class small_vector } template - constexpr void reallocate_append(size_type new_capacity, Args&&... args) + constexpr iterator reallocate_append(size_type new_capacity, Args&&... args) { const size_type old_size = size(); @@ -968,6 +968,72 @@ class small_vector detail::destroy_range(alloc_, first_, last_); deallocate(); set_storage(alloc_result.data, old_size + 1, alloc_result.size); + + return alloc_result.data + old_size; + } + + template + constexpr iterator reallocate_emplace(size_t new_capacity, const_iterator pos, Args&&... args) + { + const size_type old_size = size(); + const difference_type offset = std::distance(cbegin(), pos); + + detail::alloc_result_t alloc_result = detail::allocate(alloc_, new_capacity); + detail::scope_exit guard1{ [&] { detail::deallocate(alloc_, alloc_result.data, alloc_result.size); } }; + detail::construct(alloc_, alloc_result.data + offset, std::forward(args)...); + detail::scope_exit guard2{ [&] { detail::destroy(alloc_, alloc_result.data + offset); } }; + detail::relocate_range_strong(alloc_, first_, first_ + offset, alloc_result.data); + detail::scope_exit guard3{ [&] { detail::destroy_range(alloc_, alloc_result.data, alloc_result.data + offset); } }; + detail::relocate_range_strong(alloc_, first_ + offset, last_, alloc_result.data + offset + 1); + { guard1.release(); guard2.release(); guard3.release(); } + detail::destroy_range(alloc_, first_, last_); + deallocate(); + set_storage(alloc_result.data, old_size + 1, alloc_result.size); + + return alloc_result.data + offset; + } + + constexpr iterator reallocate_insert(size_t new_capacity, const_iterator pos, size_type count, const T& value) + { + const size_type old_size = size(); + const difference_type src_size = difference_type(count); + const difference_type offset = std::distance(cbegin(), pos); + + detail::alloc_result_t alloc_result = detail::allocate(alloc_, new_capacity); + detail::scope_exit guard1{ [&] { detail::deallocate(alloc_, alloc_result.data, alloc_result.size); } }; + detail::relocate_range_weak(alloc_, first_, first_ + offset, alloc_result.data); + detail::scope_exit guard2{ [&] { detail::destroy_range(alloc_, alloc_result.data, alloc_result.data + offset); } }; + detail::construct_range(alloc_, alloc_result.data + offset, alloc_result.data + offset + src_size, value); + detail::scope_exit guard3{ [&] { detail::destroy_range(alloc_, alloc_result.data + offset, alloc_result.data + offset + src_size); } }; + detail::relocate_range_weak(alloc_, first_ + offset, last_, alloc_result.data + offset + src_size); + { guard1.release(); guard2.release(); guard3.release(); } + detail::destroy_range(alloc_, first_, last_); + deallocate(); + set_storage(alloc_result.data, old_size + count, alloc_result.size); + + return alloc_result.data + offset; + } + + template + constexpr iterator reallocate_insert(size_t new_capacity, const_iterator pos, Iter src_first, Iter src_last) + { + const size_type old_size = size(); + const difference_type src_size = std::distance(src_first, src_last); + const difference_type offset = std::distance(cbegin(), pos); + + detail::alloc_result_t alloc_result = detail::allocate(alloc_, new_capacity); + detail::scope_exit guard1{ [&] { detail::deallocate(alloc_, alloc_result.data, alloc_result.size); } }; + detail::relocate_range_weak(alloc_, first_, first_ + offset, alloc_result.data); + detail::scope_exit guard2{ [&] { detail::destroy_range(alloc_, alloc_result.data, alloc_result.data + offset); } }; + detail::construct_range(alloc_, alloc_result.data + offset, alloc_result.data + offset + src_size, src_first); + detail::scope_exit guard3{ [&] { detail::destroy_range(alloc_, alloc_result.data + offset, alloc_result.data + offset + src_size); } }; + detail::relocate_range_weak(alloc_, first_ + offset, last_, alloc_result.data + offset + src_size); + { guard1.release(); guard2.release(); guard3.release(); } + detail::destroy_range(alloc_, first_, last_); + deallocate(); + set_storage(alloc_result.data, old_size + size_type(src_size), alloc_result.size); + + return alloc_result.data + offset; } constexpr void deallocate() noexcept diff --git a/test/small_vector.cpp b/test/small_vector.cpp index afdc607..e6685b1 100644 --- a/test/small_vector.cpp +++ b/test/small_vector.cpp @@ -14,6 +14,7 @@ #include #include +inline constexpr size_t EMPTY = 0; inline constexpr size_t SMALL_SIZE = 4; inline constexpr size_t LARGE_SIZE = 100; @@ -129,7 +130,7 @@ TEMPLATE_TEST_CASE("small_vector(Alloc)", "[constructor]", TrivialType, MoveOnly TEMPLATE_TEST_CASE("small_vector(size_t)", "[constructor]", TrivialType, MoveOnlyType, ImmovableType, NonTrivialType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); small_vector vec(size); @@ -139,7 +140,7 @@ TEMPLATE_TEST_CASE("small_vector(size_t)", "[constructor]", TrivialType, MoveOnl TEMPLATE_TEST_CASE("small_vector(size_t, Alloc)", "[constructor]", TrivialType, MoveOnlyType, ImmovableType, NonTrivialType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); small_vector vec(size, std::allocator{}); @@ -149,7 +150,7 @@ TEMPLATE_TEST_CASE("small_vector(size_t, Alloc)", "[constructor]", TrivialType, TEMPLATE_TEST_CASE("small_vector(size_t, const T&)", "[constructor]", TrivialType, NonTrivialType, NonDefaultConstructibleType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); small_vector vec(size, TestType{ 0 }); @@ -160,7 +161,7 @@ TEMPLATE_TEST_CASE("small_vector(size_t, const T&)", "[constructor]", TrivialTyp TEMPLATE_TEST_CASE("small_vector(size_t, const T&, Alloc)", "[constructor]", TrivialType, NonTrivialType, NonDefaultConstructibleType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); small_vector vec(size, TestType{ 1 }, std::allocator{}); @@ -171,7 +172,7 @@ TEMPLATE_TEST_CASE("small_vector(size_t, const T&, Alloc)", "[constructor]", Tri TEMPLATE_TEST_CASE("small_vector(Iter, Iter)", "[constructor]", TrivialType, MoveOnlyType, ImmovableType, NonTrivialType, NonDefaultConstructibleType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); const std::vector source(size, 2); @@ -183,7 +184,7 @@ TEMPLATE_TEST_CASE("small_vector(Iter, Iter)", "[constructor]", TrivialType, Mov TEMPLATE_TEST_CASE("small_vector(FwdIter, FwdIter, Alloc)", "[constructor]", TrivialType, MoveOnlyType, ImmovableType, NonTrivialType, NonDefaultConstructibleType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); const std::vector source(size, 3); @@ -195,7 +196,7 @@ TEMPLATE_TEST_CASE("small_vector(FwdIter, FwdIter, Alloc)", "[constructor]", Tri TEST_CASE("small_vector(InputIter, InputIter)", "[constructor]") { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); std::istringstream source(std::string(size, 'c')); @@ -235,7 +236,7 @@ TEMPLATE_TEST_CASE("small_vector(initializer_list, Alloc)", "[constructor]", Tri TEMPLATE_TEST_CASE("small_vector(const small_vector&)", "[constructor]", TrivialType, NonTrivialType, NonDefaultConstructibleType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); const small_vector source(size, TestType{ 26 }); @@ -247,7 +248,7 @@ TEMPLATE_TEST_CASE("small_vector(const small_vector&)", "[constructor]", Trivial TEMPLATE_TEST_CASE("small_vector(const small_vector&, Alloc)", "[constructor]", TrivialType, NonTrivialType, NonDefaultConstructibleType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); const small_vector source(size, TestType{ 26 }); @@ -259,7 +260,7 @@ TEMPLATE_TEST_CASE("small_vector(const small_vector&, Alloc)", "[constructor]", TEMPLATE_TEST_CASE("small_vector(small_vector&&)", "[constructor]", TrivialType, NonTrivialType, NonDefaultConstructibleType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); small_vector source(size, TestType{ 26 }); small_vector source_copy(source); @@ -272,7 +273,7 @@ TEMPLATE_TEST_CASE("small_vector(small_vector&&)", "[constructor]", TrivialType, TEMPLATE_TEST_CASE("small_vector(small_vector&&)", "[constructor]", MoveOnlyType) { - const size_t size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); small_vector source(size); small_vector source_copy(size); @@ -289,8 +290,8 @@ TEMPLATE_TEST_CASE("small_vector(small_vector&&)", "[constructor]" TEMPLATE_TEST_CASE("assign(size_t count, const T& val)", "[assignment]", TrivialType, NonTrivialType, NonDefaultConstructibleType) { - const size_t count = GENERATE(0, SMALL_SIZE - 1, LARGE_SIZE + 1); - const size_t dest_size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t count = GENERATE(EMPTY, SMALL_SIZE - 1, LARGE_SIZE + 1); + const size_t dest_size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); small_vector dest(dest_size, TestType{ 2 }); @@ -302,8 +303,8 @@ TEMPLATE_TEST_CASE("assign(size_t count, const T& val)", "[assignment]", Trivial TEMPLATE_TEST_CASE("assign(FwdIter, FwdIter)", "[assignment]", TrivialType, NonTrivialType, NonDefaultConstructibleType) { - const size_t src_size = GENERATE(0, SMALL_SIZE - 1, LARGE_SIZE + 1); - const size_t dest_size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t src_size = GENERATE(EMPTY, SMALL_SIZE - 1, LARGE_SIZE + 1); + const size_t dest_size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); const small_vector source(src_size, TestType{ 4 }); small_vector dest(dest_size, TestType{ 3 }); @@ -324,8 +325,8 @@ TEMPLATE_TEST_CASE("assign(FwdIter, FwdIter)", "[assignment]", TrivialType, NonT TEST_CASE("assign(InputIter, InputIter)", "[assignment]") { - const size_t src_size = GENERATE(0, SMALL_SIZE - 1, LARGE_SIZE + 1); - const size_t dst_size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t src_size = GENERATE(EMPTY, SMALL_SIZE - 1, LARGE_SIZE + 1); + const size_t dst_size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); std::istringstream source(std::string(src_size, 'c')); small_vector dest(dst_size); @@ -347,8 +348,8 @@ TEST_CASE("assign(nullptr, nullptr)", "[assignment]") TEMPLATE_TEST_CASE("operator=(const small_vector&)", "[assignment]", TrivialType, NonTrivialType, NonDefaultConstructibleType) { - const size_t src_size = GENERATE(0, SMALL_SIZE - 1, LARGE_SIZE + 1); - const size_t dest_size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t src_size = GENERATE(EMPTY, SMALL_SIZE - 1, LARGE_SIZE + 1); + const size_t dest_size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); const small_vector source(src_size, TestType{ 4 }); small_vector dest(dest_size, TestType{ 3 }); @@ -369,8 +370,8 @@ TEMPLATE_TEST_CASE("operator=(const small_vector&)", "[assignment]", TrivialType TEMPLATE_TEST_CASE("operator=(small_vector&&)", "[assignment]", TrivialType, NonTrivialType, NonDefaultConstructibleType) { - const size_t src_size = GENERATE(0, SMALL_SIZE - 1, LARGE_SIZE + 1); - const size_t dest_size = GENERATE(0, SMALL_SIZE, LARGE_SIZE); + const size_t src_size = GENERATE(EMPTY, SMALL_SIZE - 1, LARGE_SIZE + 1); + const size_t dest_size = GENERATE(EMPTY, SMALL_SIZE, LARGE_SIZE); small_vector source(src_size, TestType{ 4 }); const small_vector src_copy(source);