diff --git a/src/small_vector.hpp b/src/small_vector.hpp index 07090c7..dd948ba 100644 --- a/src/small_vector.hpp +++ b/src/small_vector.hpp @@ -3,7 +3,6 @@ #ifndef SMALL_VECTOR_SMALL_VECTOR_HPP #define SMALL_VECTOR_SMALL_VECTOR_HPP -#include #include #include #include @@ -13,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -200,7 +198,7 @@ namespace detail { if (!std::is_constant_evaluated()) { - std::memset(first, 0, sizeof(T) * (last - first)); + std::fill((char*)first, (char*)last, 0); return; } } @@ -233,7 +231,8 @@ namespace detail { if (!std::is_constant_evaluated()) { - std::memcpy(first, std::to_address(src_first), sizeof(T) * (last - first)); + char* src = (char*)std::to_address(src_first); + std::copy(src, src + sizeof(T) * (last - first), (char*)first); return; } } @@ -253,7 +252,7 @@ namespace detail { if (!std::is_constant_evaluated()) { - std::memcpy(dest, first, sizeof(T) * (last - first)); + std::copy((char*)first, (char*)last, (char*)dest); return; } } @@ -273,7 +272,7 @@ namespace detail { if (!std::is_constant_evaluated()) { - std::memcpy(dest, first, sizeof(T) * (last - first)); + std::copy((char*)first, (char*)last, (char*)dest); return; } } @@ -337,15 +336,15 @@ namespace detail constexpr small_vector_buffer() noexcept {}; constexpr ~small_vector_buffer() noexcept {}; - constexpr auto begin() noexcept { return data_.data(); } - constexpr auto begin() const noexcept { return data_.data(); } + constexpr auto begin() noexcept { return static_cast(data_); } + constexpr auto begin() const noexcept { return static_cast(data_); } - constexpr auto end() noexcept { return data_.data() + Size; } - constexpr auto end() const noexcept { return data_.data() + Size; } + constexpr auto end() noexcept { return static_cast(data_) + Size; } + constexpr auto end() const noexcept { return static_cast(data_) + Size; } constexpr std::size_t size() const noexcept { return Size; } private: - union { std::array data_; }; + union { mutable T data_[Size]; }; }; @@ -427,8 +426,6 @@ class small_vector constexpr small_vector(Iter src_first, Iter src_last, const A& allocator = A()) : alloc_(allocator) { - if (src_first == src_last) return; - const auto src_len = std::distance(src_first, src_last); allocate_n(src_len); detail::scope_exit guard{ [&] { deallocate(); } }; @@ -472,9 +469,9 @@ class small_vector } else { - std::swap(first_, other.first_); - std::swap(last_, other.last_); - std::swap(last_alloc_, other.last_alloc_); + first_ = std::exchange(other.first_, other.buffer_.begin()); + last_ = std::exchange(other.last_, other.buffer_.begin()); + last_alloc_ = std::exchange(other.last_alloc_, other.buffer_.end()); } } diff --git a/test/small_vector.cpp b/test/small_vector.cpp index e6685b1..e2501ef 100644 --- a/test/small_vector.cpp +++ b/test/small_vector.cpp @@ -212,6 +212,7 @@ TEST_CASE("small_vector(nullptr, nullptr)", "[constructor]") const small_vector vec(static_cast(nullptr), static_cast(nullptr)); REQUIRE(vec.empty()); + REQUIRE(vec.capacity() != 0); } TEMPLATE_TEST_CASE("small_vector(initializer_list)", "[constructor]", TrivialType, NonTrivialType, NonDefaultConstructibleType) @@ -244,6 +245,7 @@ TEMPLATE_TEST_CASE("small_vector(const small_vector&)", "[constructor]", Trivial REQUIRE(vec.size() == source.size()); REQUIRE(vec == source); + REQUIRE(vec.capacity() != 0); } TEMPLATE_TEST_CASE("small_vector(const small_vector&, Alloc)", "[constructor]", TrivialType, NonTrivialType, NonDefaultConstructibleType) @@ -256,6 +258,7 @@ TEMPLATE_TEST_CASE("small_vector(const small_vector&, Alloc)", "[constructor]", REQUIRE(vec.size() == source.size()); REQUIRE(vec == source); + REQUIRE(vec.capacity() != 0); } TEMPLATE_TEST_CASE("small_vector(small_vector&&)", "[constructor]", TrivialType, NonTrivialType, NonDefaultConstructibleType) @@ -269,6 +272,12 @@ TEMPLATE_TEST_CASE("small_vector(small_vector&&)", "[constructor]", TrivialType, REQUIRE(vec.size() == source_copy.size()); REQUIRE(vec == source_copy); + + REQUIRE(source.empty()); + REQUIRE(source.capacity() != 0); + + source.push_back(TestType{ 11 }); + REQUIRE(source.size() == 1); } TEMPLATE_TEST_CASE("small_vector(small_vector&&)", "[constructor]", MoveOnlyType) @@ -282,6 +291,12 @@ TEMPLATE_TEST_CASE("small_vector(small_vector&&)", "[constructor]" REQUIRE(vec.size() == source_copy.size()); REQUIRE(vec == source_copy); + + REQUIRE(source.empty()); + REQUIRE(source.capacity() != 0); + + source.push_back(TestType{ 11 }); + REQUIRE(source.size() == 1); } //-----------------------------------// @@ -381,6 +396,11 @@ TEMPLATE_TEST_CASE("operator=(small_vector&&)", "[assignment]", TrivialType, Non REQUIRE(dest.size() == src_copy.size()); REQUIRE(dest == src_copy); + + REQUIRE(source.capacity() != 0); + + source = dest; + REQUIRE(source == dest); } TEMPLATE_TEST_CASE("operator=(initializer_list)", "[assignment]", TrivialType, NonTrivialType, NonDefaultConstructibleType) @@ -516,6 +536,11 @@ TEMPLATE_TEST_CASE("swap", "[modifiers]", TrivialType, NonTrivialType) REQUIRE(right == old_left); REQUIRE(left == old_right); + + swap(left, right); + + REQUIRE(left == old_left); + REQUIRE(right == old_right); } TEMPLATE_TEST_CASE("push_back(const T&)", "[modifiers]", TrivialType, NonTrivialType, NonDefaultConstructibleType) @@ -960,6 +985,11 @@ TEMPLATE_TEST_CASE("propagate_on_move_assignment", "[allocators]", TrivialType, REQUIRE(dest.size() == src_copy.size()); REQUIRE(dest == src_copy); + + REQUIRE(source.capacity() != 0); + + source = dest; + REQUIRE(source == dest); } TEMPLATE_TEST_CASE("propagate_on_swap", "[allocators]", TrivialType, NonTrivialType) @@ -977,4 +1007,9 @@ TEMPLATE_TEST_CASE("propagate_on_swap", "[allocators]", TrivialType, NonTrivialT REQUIRE(right == old_left); REQUIRE(left == old_right); + + swap(left, right); + + REQUIRE(left == old_left); + REQUIRE(right == old_right); }