From 430cf315f8954d004efaa0d7b1abe9d35b8ad081 Mon Sep 17 00:00:00 2001 From: alimoammeri79 Date: Sun, 10 Apr 2022 14:42:00 +0430 Subject: [PATCH 1/5] Initial commit --- .gitignore | 1 + BUILD | 10 ++ README.md | 5 + WORKSPACE | 7 ++ ali_vector.h | 173 +++++++++++++++++++++++++++++++++++ tests/BUILD | 11 +++ tests/ali_vector_ptr_test.cc | 57 ++++++++++++ 7 files changed, 264 insertions(+) create mode 100644 .gitignore create mode 100644 BUILD create mode 100644 WORKSPACE create mode 100644 ali_vector.h create mode 100644 tests/BUILD create mode 100644 tests/ali_vector_ptr_test.cc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d8ad95 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bazel-* \ No newline at end of file diff --git a/BUILD b/BUILD new file mode 100644 index 0000000..b8d56be --- /dev/null +++ b/BUILD @@ -0,0 +1,10 @@ +cc_library( + name = "build_header", + hdrs = [ + "ali_vector.h" + ], + copts = [ + "-std=c++2a", + ], + visibility = ["//visibility:public"] +) diff --git a/README.md b/README.md index 6fcb573..2b6bcb7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # vector + My implementation of std::vector + +## How to test? + +
bazel test tests:ali_unique_ptr_test --repo_env=CC=g++-10
diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..b54973d --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,7 @@ +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") + +git_repository( + name = "googletest", + remote = "https://github.com/google/googletest", + tag = "release-1.10.0", +) diff --git a/ali_vector.h b/ali_vector.h new file mode 100644 index 0000000..678cdbe --- /dev/null +++ b/ali_vector.h @@ -0,0 +1,173 @@ +/* + * Created by ali on 4/10/22. + * + * todo: + * begin() + * cbegin() + * end() + * cend() + * front() + * back() + * empty() + * insert() +*/ + +#ifndef ALI_VECTOR_H +#define ALI_VECTOR_H + +#include +#include +#include + +namespace ali { + template class vector { + public: + vector() + : m_size{0}, m_capacity{0}, ptr{nullptr} {} + + explicit vector(const std::size_t& _size, const T& value = T{}) + : m_size{_size}, m_capacity{_size * 2}, ptr{ new T[m_capacity] } { + for(std::size_t i{0}; i < m_size; ++i) + ptr[i] = value; + } + + vector(const std::initializer_list& ls) + : m_size{ls.size()}, m_capacity{ls.size() * 2}, ptr{ new T[ls.size()] } { + std::copy(ls.begin(), ls.end(), ptr); + } + + vector(const ali::vector& rhs) + :m_size{rhs.size()}, m_capacity{rhs.capacity()}, ptr{new T[rhs.capacity()]} { + std::copy(rhs.ptr, rhs.ptr + size(), ptr); + } + + vector(ali::vector&& rhs) noexcept + :m_size{rhs.size()}, m_capacity{rhs.capacity()}, ptr{new T[rhs.capacity()]} { + std::copy(rhs.ptr, rhs.ptr + size(), ptr); + rhs.clear(); + } + + ~vector() { delete[] ptr; } + + [[nodiscard]] std::size_t size() const noexcept { return m_size; } + [[nodiscard]] std::size_t capacity() const noexcept { return m_capacity; } + void clear() noexcept { + delete[] ptr; + ptr = nullptr; + m_size = 0; + } + + void push_back(const T& value) { + std::size_t new_size{m_size + 1}; + if(new_size > capacity()) + { + m_capacity = new_size * 2; + T* new_ptr {new T[m_capacity] {T()}}; + std::copy(ptr, ptr + size(), new_ptr); + delete[] ptr; + ptr = new_ptr; + } + ptr[m_size++] = value; + } + + + void pop_back() { + m_size = m_size > 0 ? m_size - 1 : m_size; + } + + T& at(std::size_t index) { + if (index < size()) + return ptr[index]; + else + throw std::out_of_range("index out of range"); + } + + const T& at(std::size_t index) const { + if (index < size()) + return ptr[index]; + else + throw std::out_of_range("index out of range"); + } + + void shrink_to_fit() { + if (size() < capacity()) { + T* new_arr = new T[size()]; + std::copy(ptr, ptr + size(), new_arr); + delete[] ptr; + ptr = new_arr; + m_capacity = size(); + } + } + + void reserve(std::size_t capacity) { + if (capacity > m_capacity) { + T* new_arr = new T[capacity]; + std::copy(ptr, ptr + m_size, new_arr); + delete[] ptr; + ptr = new_arr; + m_capacity = capacity; + } + } + + bool empty() const { return size() == 0; } + + void swap(ali::vector& rhs) { + std::swap(m_size, rhs.m_size); + std::swap(m_capacity, rhs.m_capacity); + std::swap(ptr, rhs.ptr); + } + + T& operator[](const std::size_t& index) { + if(index >= size()) + throw std::out_of_range("out of range index"); + else + return ptr[index]; + } + + const T& operator[](const std::size_t& index) const { + if(index >= size()) + throw std::out_of_range("out of range index"); + else + return ptr[index]; + } + + ali::vector& operator=(const ali::vector& rhs) noexcept { + if(*this != rhs) + { + m_size = rhs.size(); + m_capacity = rhs.capacity(); + T* new_ptr{new T[m_capacity]}; + std::copy(rhs.ptr, rhs.ptr + rhs.size(), new_ptr); + delete[] ptr; + ptr = new_ptr; + } + return *this; + } + + ali::vector& operator=(ali::vector&& rhs) noexcept { + m_size = rhs.size(); + m_capacity = rhs.capacity(); + ptr = new T[rhs.capacity()] ; + std::copy(rhs.ptr, rhs.ptr + size(), ptr); + rhs.clear(); + } + + bool operator==(const vector &rhs) const { + if (size() != rhs.size()) + return false; + for (std::size_t i{0}; i < size(); ++i) { + if (ptr[i] != rhs[i]) + return false; + } + return true; + } + + private: + std::size_t m_size{0}; + std::size_t m_capacity{0}; + T* ptr{nullptr}; + }; +} + +#endif //VECTOR_ALI_VECTOR_H + diff --git a/tests/BUILD b/tests/BUILD new file mode 100644 index 0000000..be95c33 --- /dev/null +++ b/tests/BUILD @@ -0,0 +1,11 @@ +cc_test( + name = "ali_vector_test", + srcs = glob(["**/*.cc"]), + copts = [ + "-std=c++2a", + ], + deps = [ + "//:build_header", + "@googletest//:gtest_main", + ], +) diff --git a/tests/ali_vector_ptr_test.cc b/tests/ali_vector_ptr_test.cc new file mode 100644 index 0000000..77cb7e0 --- /dev/null +++ b/tests/ali_vector_ptr_test.cc @@ -0,0 +1,57 @@ +#include "ali_vector.h" +#include +#include + +TEST(VectorTest, DefaultConstructor) { + ali::vector v; + EXPECT_EQ(v.size(), 0); + EXPECT_EQ(v.capacity(), 0); +} + +TEST(VectorTest, Constructor) { + ali::vector v(10); + EXPECT_EQ(v.size(), 10); + EXPECT_EQ(v[5], 0); + + ali::vector v2(10, 6); + EXPECT_EQ(v2.size(), 10); + EXPECT_EQ(v2[5], 6); + + ali::vector v3{1, 2 ,3 ,4}; + EXPECT_EQ(v3.size(), 4); + EXPECT_EQ(v3[1], 2); +} + +TEST(VectorTest, CopyConstructor) { + ali::vector v{1, 2, 3}; + ali::vector v2{v}; + + EXPECT_EQ(v == v2, true); +} + +TEST(VectorTest, Clear) { + ali::vector v{1, 2, 3}; + v.clear(); + EXPECT_EQ(v.size(), 0); +} + +TEST(VectorTest, PushBack) { + ali::vector v{1, 2, 3}; + v.push_back(4); + EXPECT_EQ(v.size(), 4); + EXPECT_EQ(v[3], 4); +} + +TEST(VectorTest, PopBack) { + ali::vector v{1, 2, 3}; + v.pop_back(); + EXPECT_EQ(v.size(), 2); +} + +TEST(VectorTest, Empty) { + ali::vector v{1, 2, 3}; + ali::vector v2; + EXPECT_EQ(v.empty(), false); + EXPECT_EQ(v2.empty(), true); +} + From 488966ef6cdf6ea050c7976f4e4099ce2d282dab Mon Sep 17 00:00:00 2001 From: alimoammeri79 Date: Sun, 10 Apr 2022 14:43:05 +0430 Subject: [PATCH 2/5] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b6bcb7..f2bf746 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,7 @@ My implementation of std::vector ## How to test? -
bazel test tests:ali_unique_ptr_test --repo_env=CC=g++-10
+
+
$ bazel test tests:ali_vector_test --repo_env=CC=g++-10
+
+
From c979a2f54e32bd664443120983624654ee24283d Mon Sep 17 00:00:00 2001 From: alimoammeri79 Date: Tue, 12 Apr 2022 13:03:39 +0430 Subject: [PATCH 3/5] Refactor code to support types with no default constructor --- ali_vector.h | 121 ++++++++++++++++++----------------- tests/ali_vector_ptr_test.cc | 78 ++++++++++++++++------ 2 files changed, 122 insertions(+), 77 deletions(-) diff --git a/ali_vector.h b/ali_vector.h index 678cdbe..21dd0fb 100644 --- a/ali_vector.h +++ b/ali_vector.h @@ -1,16 +1,6 @@ -/* - * Created by ali on 4/10/22. - * - * todo: - * begin() - * cbegin() - * end() - * cend() - * front() - * back() - * empty() - * insert() -*/ +// +// Created by Ali Moameri on 4/10/22. +// #ifndef ALI_VECTOR_H #define ALI_VECTOR_H @@ -25,32 +15,43 @@ namespace ali { vector() : m_size{0}, m_capacity{0}, ptr{nullptr} {} - explicit vector(const std::size_t& _size, const T& value = T{}) - : m_size{_size}, m_capacity{_size * 2}, ptr{ new T[m_capacity] } { - for(std::size_t i{0}; i < m_size; ++i) - ptr[i] = value; - } + explicit vector(const std::size_t& _size) + : m_size{_size}, m_capacity{_size * 2} { + ptr = m_alloc.allocate(m_capacity); + } + + explicit vector(const std::size_t& _size, const T& value) + : m_size{_size}, m_capacity{_size * 2} { + ptr = m_alloc.allocate(m_capacity); + for(std::size_t i{0}; i < m_size; ++i) + ptr[i] = value; + } vector(const std::initializer_list& ls) - : m_size{ls.size()}, m_capacity{ls.size() * 2}, ptr{ new T[ls.size()] } { + : m_size{ls.size()}, m_capacity{ls.size() * 2} { + ptr = m_alloc.allocate(m_capacity); std::copy(ls.begin(), ls.end(), ptr); } vector(const ali::vector& rhs) - :m_size{rhs.size()}, m_capacity{rhs.capacity()}, ptr{new T[rhs.capacity()]} { - std::copy(rhs.ptr, rhs.ptr + size(), ptr); + :m_size{rhs.size()}, m_capacity{rhs.capacity()} { + ptr = m_alloc.allocate(m_capacity); + std::copy(rhs.ptr, rhs.ptr + rhs.size(), ptr); } vector(ali::vector&& rhs) noexcept - :m_size{rhs.size()}, m_capacity{rhs.capacity()}, ptr{new T[rhs.capacity()]} { - std::copy(rhs.ptr, rhs.ptr + size(), ptr); + :m_size{rhs.size()}, m_capacity{rhs.capacity()} { + ptr = m_alloc.allocate(m_capacity); + std::copy(rhs.ptr, rhs.ptr + rhs.size(), ptr); rhs.clear(); + m_capacity = 0; } - ~vector() { delete[] ptr; } + ~vector() { m_alloc.deallocate(ptr, m_capacity); } + + [[nodiscard]] constexpr std::size_t size() const noexcept { return m_size; } + [[nodiscard]] constexpr std::size_t capacity() const noexcept { return m_capacity; } - [[nodiscard]] std::size_t size() const noexcept { return m_size; } - [[nodiscard]] std::size_t capacity() const noexcept { return m_capacity; } void clear() noexcept { delete[] ptr; ptr = nullptr; @@ -59,12 +60,13 @@ namespace ali { void push_back(const T& value) { std::size_t new_size{m_size + 1}; - if(new_size > capacity()) + if(new_size > m_capacity) { - m_capacity = new_size * 2; - T* new_ptr {new T[m_capacity] {T()}}; - std::copy(ptr, ptr + size(), new_ptr); - delete[] ptr; + std::size_t new_capacity {new_size * 2}; + T* new_ptr{m_alloc.allocate(new_capacity)}; + std::copy(ptr, ptr + m_size, new_ptr); + m_alloc.deallocate(ptr, m_capacity); + m_capacity = new_capacity; ptr = new_ptr; } ptr[m_size++] = value; @@ -76,44 +78,45 @@ namespace ali { } T& at(std::size_t index) { - if (index < size()) + if (index < m_size) return ptr[index]; else throw std::out_of_range("index out of range"); } const T& at(std::size_t index) const { - if (index < size()) + if (index < m_size) return ptr[index]; else throw std::out_of_range("index out of range"); } void shrink_to_fit() { - if (size() < capacity()) { - T* new_arr = new T[size()]; - std::copy(ptr, ptr + size(), new_arr); - delete[] ptr; - ptr = new_arr; - m_capacity = size(); + if (m_size < m_capacity) { + T* new_ptr{m_alloc.allocate(m_size)}; + std::copy(ptr, ptr + m_size, new_ptr); + m_alloc.deallocate(ptr, m_capacity); + ptr = new_ptr; + m_capacity = m_size; } } void reserve(std::size_t capacity) { if (capacity > m_capacity) { - T* new_arr = new T[capacity]; - std::copy(ptr, ptr + m_size, new_arr); - delete[] ptr; - ptr = new_arr; + T* new_ptr{m_alloc.allocate(capacity)}; + std::copy(ptr, ptr + m_size, new_ptr); + m_alloc.deallocate(ptr, m_capacity); + ptr = new_ptr; m_capacity = capacity; } } - bool empty() const { return size() == 0; } + [[nodiscard]] bool empty() const { return size() == 0; } void swap(ali::vector& rhs) { std::swap(m_size, rhs.m_size); std::swap(m_capacity, rhs.m_capacity); + std::swap(m_alloc, rhs.m_alloc); std::swap(ptr, rhs.ptr); } @@ -132,30 +135,30 @@ namespace ali { } ali::vector& operator=(const ali::vector& rhs) noexcept { - if(*this != rhs) - { - m_size = rhs.size(); - m_capacity = rhs.capacity(); - T* new_ptr{new T[m_capacity]}; - std::copy(rhs.ptr, rhs.ptr + rhs.size(), new_ptr); - delete[] ptr; - ptr = new_ptr; - } + m_size = rhs.size(); + T* new_ptr{m_alloc.allocate(rhs.capacity())}; + std::copy(rhs.ptr, rhs.ptr + rhs.size(), new_ptr); + m_alloc.deallocate(ptr, m_capacity); + m_capacity = rhs.capacity(); + ptr = new_ptr; return *this; } ali::vector& operator=(ali::vector&& rhs) noexcept { + T* new_ptr{m_alloc.allocate(rhs.capacity())}; + std::copy(rhs.ptr, rhs.ptr + rhs.size(), new_ptr); + m_alloc.deallocate(ptr, m_capacity); m_size = rhs.size(); m_capacity = rhs.capacity(); - ptr = new T[rhs.capacity()] ; - std::copy(rhs.ptr, rhs.ptr + size(), ptr); + ptr = new_ptr; rhs.clear(); + return *this; } bool operator==(const vector &rhs) const { - if (size() != rhs.size()) + if (m_size != rhs.size()) return false; - for (std::size_t i{0}; i < size(); ++i) { + for (std::size_t i{0}; i < m_size; ++i) { if (ptr[i] != rhs[i]) return false; } @@ -165,9 +168,9 @@ namespace ali { private: std::size_t m_size{0}; std::size_t m_capacity{0}; + std::allocator m_alloc; T* ptr{nullptr}; }; } -#endif //VECTOR_ALI_VECTOR_H - +#endif //ALI_VECTOR_H diff --git a/tests/ali_vector_ptr_test.cc b/tests/ali_vector_ptr_test.cc index 77cb7e0..9e8f43c 100644 --- a/tests/ali_vector_ptr_test.cc +++ b/tests/ali_vector_ptr_test.cc @@ -2,56 +2,98 @@ #include #include +struct T { + int x; + + T(const int input) : x(input) + {} +}; + +constexpr std::size_t size {10}; +constexpr std::size_t capacity {size*2}; + TEST(VectorTest, DefaultConstructor) { - ali::vector v; + ali::vector v; EXPECT_EQ(v.size(), 0); EXPECT_EQ(v.capacity(), 0); } -TEST(VectorTest, Constructor) { - ali::vector v(10); - EXPECT_EQ(v.size(), 10); - EXPECT_EQ(v[5], 0); +TEST(VectorTest, Constructors) { + ali::vector v(size); + EXPECT_EQ(v.size(), size); + EXPECT_EQ(v.capacity(), capacity); - ali::vector v2(10, 6); - EXPECT_EQ(v2.size(), 10); - EXPECT_EQ(v2[5], 6); + ali::vector v2(size, 6); + EXPECT_EQ(v2.size(), size); + EXPECT_EQ(v2.capacity(), capacity); + EXPECT_EQ(v2[5].x, 6); - ali::vector v3{1, 2 ,3 ,4}; + ali::vector v3{1, 2 ,3 ,4}; EXPECT_EQ(v3.size(), 4); - EXPECT_EQ(v3[1], 2); + EXPECT_EQ(v3[1].x, 2); } TEST(VectorTest, CopyConstructor) { ali::vector v{1, 2, 3}; ali::vector v2{v}; - EXPECT_EQ(v == v2, true); } +TEST(VectorTest, MoveConstructor) { + ali::vector v{1, 2, 3}; + ali::vector v2{std::move(v)}; + EXPECT_EQ(v.empty(), true); + EXPECT_EQ(v2[1].x, 2); +} + TEST(VectorTest, Clear) { - ali::vector v{1, 2, 3}; + ali::vector v{1, 2, 3}; v.clear(); EXPECT_EQ(v.size(), 0); } TEST(VectorTest, PushBack) { - ali::vector v{1, 2, 3}; - v.push_back(4); + ali::vector v{1, 2, 3}; + v.push_back(T{4}); EXPECT_EQ(v.size(), 4); - EXPECT_EQ(v[3], 4); + EXPECT_EQ(v[3].x, 4); } TEST(VectorTest, PopBack) { - ali::vector v{1, 2, 3}; + ali::vector v{1, 2, 3}; v.pop_back(); EXPECT_EQ(v.size(), 2); } TEST(VectorTest, Empty) { - ali::vector v{1, 2, 3}; - ali::vector v2; + ali::vector v{1, 2, 3}; + ali::vector v2; EXPECT_EQ(v.empty(), false); EXPECT_EQ(v2.empty(), true); } +TEST(VectorTest, Assigment) { + ali::vector v{1, 2, 3}; + ali::vector v2; + v2 = v; + for(std::size_t i{0}; i < v.size(); ++i) + EXPECT_EQ(v[i].x, v2[i].x); +} + +TEST(VectorTest, MoveAssigment) { + ali::vector v{1, 2, 3}; + ali::vector v2{v}; + ali::vector v3; + v3 = std::move(v); + + for(std::size_t i{0}; i < v3.size(); ++i) + EXPECT_EQ(v3[i].x, v2[i].x); + + EXPECT_EQ(v.empty(), true); +} + +TEST(VectorTest, ConstDerefence) { + const ali::vector v{1, 2, 3}; + EXPECT_EQ(v[2].x, 3); +} + From f4487351a0d188d4d900f7102ebd3a3d67f57e23 Mon Sep 17 00:00:00 2001 From: alimoammeri79 Date: Fri, 15 Apr 2022 17:02:19 +0430 Subject: [PATCH 4/5] Optimizing push_back and assigments --- ali_vector.h | 63 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/ali_vector.h b/ali_vector.h index 21dd0fb..c336df0 100644 --- a/ali_vector.h +++ b/ali_vector.h @@ -10,7 +10,7 @@ #include namespace ali { - template class vector { + template class vector { public: vector() : m_size{0}, m_capacity{0}, ptr{nullptr} {} @@ -59,16 +59,10 @@ namespace ali { } void push_back(const T& value) { - std::size_t new_size{m_size + 1}; - if(new_size > m_capacity) - { - std::size_t new_capacity {new_size * 2}; - T* new_ptr{m_alloc.allocate(new_capacity)}; - std::copy(ptr, ptr + m_size, new_ptr); - m_alloc.deallocate(ptr, m_capacity); - m_capacity = new_capacity; - ptr = new_ptr; - } + if(m_capacity == 0) + reserve(8); + else if(m_size == m_capacity) + reserve(m_size * 2); ptr[m_size++] = value; } @@ -101,13 +95,13 @@ namespace ali { } } - void reserve(std::size_t capacity) { - if (capacity > m_capacity) { - T* new_ptr{m_alloc.allocate(capacity)}; + void reserve(std::size_t space) { + if (space > m_capacity) { + T* new_ptr{m_alloc.allocate(space)}; std::copy(ptr, ptr + m_size, new_ptr); m_alloc.deallocate(ptr, m_capacity); ptr = new_ptr; - m_capacity = capacity; + m_capacity = space; } } @@ -135,30 +129,47 @@ namespace ali { } ali::vector& operator=(const ali::vector& rhs) noexcept { - m_size = rhs.size(); - T* new_ptr{m_alloc.allocate(rhs.capacity())}; + if(this == &rhs) + return *this; + + if(rhs.size() <= m_capacity) { + std::copy(rhs.ptr, rhs.ptr + rhs.size(), ptr); + m_size = rhs.size(); + return *this; + } + + T* new_ptr{m_alloc.allocate(rhs.size())}; std::copy(rhs.ptr, rhs.ptr + rhs.size(), new_ptr); m_alloc.deallocate(ptr, m_capacity); - m_capacity = rhs.capacity(); ptr = new_ptr; + m_capacity = m_size = rhs.size(); return *this; } ali::vector& operator=(ali::vector&& rhs) noexcept { - T* new_ptr{m_alloc.allocate(rhs.capacity())}; - std::copy(rhs.ptr, rhs.ptr + rhs.size(), new_ptr); - m_alloc.deallocate(ptr, m_capacity); - m_size = rhs.size(); - m_capacity = rhs.capacity(); - ptr = new_ptr; + if(this == &rhs) + return *this; + + if(rhs.size() <= m_capacity) { + std::copy(rhs.ptr, rhs.ptr + rhs.size(), ptr); + m_size = rhs.size(); + } else { + T* new_ptr{m_alloc.allocate(rhs.size())}; + std::copy(rhs.ptr, rhs.ptr + rhs.size(), new_ptr); + m_alloc.deallocate(ptr, m_capacity); + ptr = new_ptr; + m_capacity = m_size = rhs.size(); + } + rhs.clear(); + rhs.m_capacity = 0; return *this; } bool operator==(const vector &rhs) const { - if (m_size != rhs.size()) + if (size() != rhs.size()) return false; - for (std::size_t i{0}; i < m_size; ++i) { + for (std::size_t i{0}; i < size(); ++i) { if (ptr[i] != rhs[i]) return false; } From 3e64ba7f44de8dae1ec5c37e41bd8af96de8d006 Mon Sep 17 00:00:00 2001 From: alimoammeri79 Date: Sat, 16 Apr 2022 13:28:41 +0430 Subject: [PATCH 5/5] Use std::allocator in a more standard way --- README.md | 2 +- ali_vector.h | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index f2bf746..2524557 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,6 @@ My implementation of std::vector ## How to test?
-
$ bazel test tests:ali_vector_test --repo_env=CC=g++-10
+
$ bazel test tests:ali_vector_test --repo_env=CC=c++
 
diff --git a/ali_vector.h b/ali_vector.h index c336df0..583eba7 100644 --- a/ali_vector.h +++ b/ali_vector.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace ali { template class vector { @@ -24,25 +25,28 @@ namespace ali { : m_size{_size}, m_capacity{_size * 2} { ptr = m_alloc.allocate(m_capacity); for(std::size_t i{0}; i < m_size; ++i) - ptr[i] = value; + m_alloc.construct(ptr + i, value); } vector(const std::initializer_list& ls) : m_size{ls.size()}, m_capacity{ls.size() * 2} { ptr = m_alloc.allocate(m_capacity); - std::copy(ls.begin(), ls.end(), ptr); + for(std::size_t i{0}; i < ls.size(); ++i) + m_alloc.construct(ptr + i, *(ls.begin() + i)); } vector(const ali::vector& rhs) :m_size{rhs.size()}, m_capacity{rhs.capacity()} { ptr = m_alloc.allocate(m_capacity); - std::copy(rhs.ptr, rhs.ptr + rhs.size(), ptr); + for(std::size_t i{0}; i < rhs.size(); ++i) + m_alloc.construct(ptr + i, rhs[i]); } vector(ali::vector&& rhs) noexcept :m_size{rhs.size()}, m_capacity{rhs.capacity()} { ptr = m_alloc.allocate(m_capacity); - std::copy(rhs.ptr, rhs.ptr + rhs.size(), ptr); + for(std::size_t i{0}; i < rhs.size(); ++i) + m_alloc.construct(ptr + i, rhs[i]); rhs.clear(); m_capacity = 0; } @@ -88,7 +92,10 @@ namespace ali { void shrink_to_fit() { if (m_size < m_capacity) { T* new_ptr{m_alloc.allocate(m_size)}; - std::copy(ptr, ptr + m_size, new_ptr); + for(std::size_t i{0}; i < m_size; ++i) + m_alloc.construct(new_ptr + i, ptr[i]); + for(std::size_t i{0}; i < m_size; ++i) + m_alloc.destroy(ptr + i); m_alloc.deallocate(ptr, m_capacity); ptr = new_ptr; m_capacity = m_size; @@ -98,7 +105,12 @@ namespace ali { void reserve(std::size_t space) { if (space > m_capacity) { T* new_ptr{m_alloc.allocate(space)}; - std::copy(ptr, ptr + m_size, new_ptr); + + for(std::size_t i{0}; i < m_size; ++i) + m_alloc.construct(new_ptr + i, ptr[i]); + for(std::size_t i{0}; i < m_size; ++i) + m_alloc.destroy(ptr + i); + m_alloc.deallocate(ptr, m_capacity); ptr = new_ptr; m_capacity = space; @@ -139,7 +151,10 @@ namespace ali { } T* new_ptr{m_alloc.allocate(rhs.size())}; - std::copy(rhs.ptr, rhs.ptr + rhs.size(), new_ptr); + for(std::size_t i{0}; i < rhs.size(); ++i) + m_alloc.construct(new_ptr + i, rhs[i]); + for(std::size_t i{0}; i < m_size; ++i) + m_alloc.destroy(ptr + i); m_alloc.deallocate(ptr, m_capacity); ptr = new_ptr; m_capacity = m_size = rhs.size(); @@ -154,13 +169,16 @@ namespace ali { std::copy(rhs.ptr, rhs.ptr + rhs.size(), ptr); m_size = rhs.size(); } else { - T* new_ptr{m_alloc.allocate(rhs.size())}; - std::copy(rhs.ptr, rhs.ptr + rhs.size(), new_ptr); - m_alloc.deallocate(ptr, m_capacity); - ptr = new_ptr; - m_capacity = m_size = rhs.size(); + T* new_ptr{m_alloc.allocate(rhs.size())}; + for(std::size_t i{0}; i < rhs.size(); ++i) + m_alloc.construct(new_ptr + i, rhs[i]); + for(std::size_t i{0}; i < m_size; ++i) + m_alloc.destroy(ptr + i); + m_alloc.deallocate(ptr, m_capacity); + ptr = new_ptr; + m_capacity = m_size = rhs.size(); } - + rhs.clear(); rhs.m_capacity = 0; return *this;