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..126d27c
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,10 @@
+cc_library(
+ name = "build_header",
+ hdrs = [
+ "ali_unique_ptr.h"
+ ],
+ copts = [
+ "-std=c++2a",
+ ],
+ visibility = ["//visibility:public"]
+)
\ No newline at end of file
diff --git a/README.md b/README.md
index 8b0034a..114db0c 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,11 @@
# uniq_ptr
-A minimal implementation of std::unique_ptr
+
+A minimal implementation of std::uniq_ptr.
+
+## How to test?
+
+You can use bazel:
+
+
$ bazel test tests:ali_unique_ptr_test --repo_env=CC=g++-10
+
+
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 0000000..275a329
--- /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",
+)
\ No newline at end of file
diff --git a/ali_unique_ptr.h b/ali_unique_ptr.h
new file mode 100644
index 0000000..91e4614
--- /dev/null
+++ b/ali_unique_ptr.h
@@ -0,0 +1,101 @@
+//
+// Created by Ali Moammeri on 3/28/22.
+//
+
+#ifndef ALI_UNIQUE_PTR_H
+#define ALI_UNIQUE_PTR_H
+
+#include
+#include
+#include
+
+namespace ali {
+ template class unique_ptr {
+ friend std::ostream& operator<<(std::ostream&, const unique_ptr&);
+ public:
+ unique_ptr() noexcept= default;
+ explicit unique_ptr(std::nullptr_t nptr) noexcept: _pointer{nptr} {}
+ explicit unique_ptr(T* pointer) noexcept : _pointer{pointer} {}
+ unique_ptr(const unique_ptr&) noexcept= delete;
+ unique_ptr(unique_ptr&& other) noexcept : _pointer {other.release()}{};
+ ~unique_ptr() { delete _pointer; }
+
+ T* get() const noexcept { return _pointer; }
+ T* release() noexcept {
+ T* temp_ptr {get()};
+ _pointer = nullptr;
+ return temp_ptr;
+ }
+ void reset(T* pointer = T()) noexcept {
+ delete _pointer;
+ _pointer = pointer;
+ }
+ void reset(std::nullptr_t nptr) noexcept {
+ delete _pointer;
+ _pointer = nptr;
+ }
+ void swap(unique_ptr& other) { std::swap(_pointer, other._pointer); }
+ unique_ptr& operator=(unique_ptr&& other) noexcept {
+ reset(other.release());
+ return *this;
+ }
+ unique_ptr& operator=(const unique_ptr&) noexcept = delete;
+ auto operator<=>(const unique_ptr& rhs) const = default;
+ explicit operator bool() const noexcept { return _pointer != nullptr; }
+ T& operator*() { return *get(); }
+ T* operator->() { return get(); }
+
+ private:
+ T* _pointer{nullptr};
+ };
+
+ // Specialization for arrays:
+ template class unique_ptr {
+ friend std::ostream& operator<<(std::ostream&, const unique_ptr&);
+ public:
+ unique_ptr() noexcept= default;
+ explicit unique_ptr(std::nullptr_t nptr) noexcept: _pointer{nptr} {}
+ explicit unique_ptr(T pointer[]) noexcept : _pointer{pointer} {}
+ unique_ptr(const unique_ptr&) noexcept= delete;
+ unique_ptr(unique_ptr&& other) noexcept : _pointer {other.release()}{};
+ ~unique_ptr() { delete[] _pointer; }
+
+ T* get() const noexcept { return _pointer; }
+ T* release() noexcept {
+ T* temp_ptr {get()};
+ _pointer = nullptr;
+ return temp_ptr;
+ }
+ void reset(T* pointer = T()) noexcept {
+ delete _pointer;
+ _pointer = pointer;
+ }
+ void reset(std::nullptr_t nptr) noexcept {
+ delete _pointer;
+ _pointer = nptr;
+ }
+ void swap(unique_ptr& other) { std::swap(_pointer, other._pointer); }
+ unique_ptr& operator=(unique_ptr&& other) noexcept {
+ reset(other.release());
+ return *this;
+ }
+
+ unique_ptr& operator=(const unique_ptr&) noexcept = delete;
+ auto operator<=>(const unique_ptr& rhs) const = default;
+ explicit operator bool() const noexcept { return _pointer != nullptr; }
+ T& operator*() { return *get(); }
+ T* operator->() { return get(); }
+ T& operator[](const std::size_t& index) { return *(get() + index); }
+
+ private:
+ T* _pointer{nullptr};
+ };
+}
+
+template
+std::ostream& operator<<(std::ostream& out, const ali::unique_ptr& u_ptr) {
+ out << u_ptr.get();
+ return out;
+}
+
+#endif //ALI_UNIQUE_PTR_H
\ No newline at end of file
diff --git a/tests/BUILD b/tests/BUILD
new file mode 100644
index 0000000..f5cc241
--- /dev/null
+++ b/tests/BUILD
@@ -0,0 +1,11 @@
+cc_test(
+ name = "ali_unique_ptr_test",
+ srcs = glob(["**/*.cc"]),
+ copts = [
+ "-std=c++2a",
+ ],
+ deps = [
+ "//:build_header",
+ "@googletest//:gtest_main",
+ ],
+)
\ No newline at end of file
diff --git a/tests/ali_unique_ptr_test.cc b/tests/ali_unique_ptr_test.cc
new file mode 100644
index 0000000..bdabda9
--- /dev/null
+++ b/tests/ali_unique_ptr_test.cc
@@ -0,0 +1,159 @@
+#include "ali_unique_ptr.h"
+#include
+#include
+
+TEST(UniquePtrTest, DefaultConstructor) {
+ ali::unique_ptr u_ptr;
+ EXPECT_EQ(u_ptr.get(), nullptr);
+}
+
+TEST(UniquePtrTest, NullConstructor) {
+ ali::unique_ptr u_ptr{nullptr};
+ EXPECT_EQ(u_ptr.get(), nullptr);
+}
+
+TEST(UniquePtrTest, PointerConstructor) {
+ ali::unique_ptr u_ptr{new int};
+ EXPECT_NE(u_ptr.get(), nullptr);
+}
+
+TEST(UniquePtrTest, MoveCostructor) {
+ ali::unique_ptr u_ptr1{new int};
+ ali::unique_ptr u_ptr2{std::move(u_ptr1)};
+ EXPECT_EQ(u_ptr1.get(), nullptr);
+ EXPECT_NE(u_ptr2.get(), nullptr);
+}
+
+TEST(UniquePtrTest, ReleaseTest) {
+ ali::unique_ptr u_ptr1{new int};
+ ali::unique_ptr u_ptr2{u_ptr1.release()};
+ EXPECT_EQ(u_ptr1.get(), nullptr);
+ EXPECT_NE(u_ptr2.get(), nullptr);
+}
+
+TEST(UniquePtrTest, ResetTest) {
+ ali::unique_ptr u_ptr{new int};
+ u_ptr.reset(nullptr);
+ EXPECT_EQ(u_ptr.get(), nullptr);
+ u_ptr.reset(new int);
+ EXPECT_NE(u_ptr.get(), nullptr);
+}
+
+TEST(UniquePtrTest, DereferenceTest) {
+ constexpr int a {3};
+ constexpr int b {5};
+ ali::unique_ptr u_ptr1{new int{a}};
+ ali::unique_ptr u_ptr2{new int{b}};
+ EXPECT_EQ(*u_ptr1, a);
+ EXPECT_EQ(*u_ptr2, b);
+}
+
+TEST(UniquePtrTest, SwapTest) {
+ constexpr int a {3};
+ constexpr int b {5};
+ ali::unique_ptr u_ptr1{new int{a}};
+ ali::unique_ptr u_ptr2{new int{b}};
+ u_ptr1.swap(u_ptr2);
+ EXPECT_EQ(*u_ptr1, b);
+ EXPECT_EQ(*u_ptr2, a);
+}
+
+TEST(UniquePtrTest, EqualityOperator) {
+ ali::unique_ptr u_ptr1{new int};
+ ali::unique_ptr u_ptr2{new int};
+ EXPECT_EQ(u_ptr1 == u_ptr2, 0);
+ EXPECT_EQ(u_ptr1 == u_ptr1, 1);
+}
+
+TEST(UniquePtrTest, NEqualityOperator) {
+ ali::unique_ptr u_ptr1{new int};
+ ali::unique_ptr u_ptr2{new int};
+ EXPECT_EQ(u_ptr1 != u_ptr2, true);
+ EXPECT_EQ(u_ptr1 != u_ptr1, false);
+}
+
+TEST(UniquePtrTest, ComparisionOperatorsTest) {
+ ali::unique_ptr u_ptr1{new int};
+ ali::unique_ptr u_ptr2{new int};
+ EXPECT_EQ(u_ptr1 < u_ptr2, false);
+ EXPECT_EQ(u_ptr1 > u_ptr2, true);
+}
+
+TEST(UniquePtrTest, BoolCastTest) {
+ ali::unique_ptr u_ptr1;
+ ali::unique_ptr u_ptr2{new int};
+ EXPECT_EQ(static_cast(u_ptr1), false);
+ EXPECT_EQ(static_cast(u_ptr2), true);
+}
+
+TEST(UniquePtrForArrays, Constructor) {
+ constexpr std::size_t n {5};
+ ali::unique_ptr u_ptr{new int[n]};
+ EXPECT_NE(u_ptr.get(), nullptr);
+}
+
+TEST(UniquePtrForArrays, MoveCostructor) {
+ constexpr std::size_t n{5};
+ ali::unique_ptr u_ptr1{new int[n]};
+ EXPECT_NE(u_ptr1.get(), nullptr);
+ ali::unique_ptr u_ptr2(std::move(u_ptr1));
+ EXPECT_EQ(u_ptr1.get(), nullptr);
+ EXPECT_NE(u_ptr2.get(), nullptr);
+}
+
+TEST(UniquePtrForArrays, ReleaseTest) {
+ constexpr std::size_t n{5};
+ ali::unique_ptr u_ptr{new int[n]};
+ u_ptr.release();
+ EXPECT_EQ(u_ptr.get(), nullptr);
+}
+
+TEST(UniquePtrForArrays, ResetTest) {
+ constexpr std::size_t n{10};
+ ali::unique_ptr u_ptr{new int[n]};
+ u_ptr.reset(nullptr);
+ EXPECT_EQ(u_ptr.get(), nullptr);
+ u_ptr.reset(new int[n]);
+ EXPECT_NE(u_ptr.get(), nullptr);
+}
+
+TEST(UniquePtrForArrays, SwapTest) {
+ constexpr std::size_t n{10};
+ ali::unique_ptr u_ptr1{new int[n]};
+ ali::unique_ptr u_ptr2;
+ u_ptr1.swap(u_ptr2);
+ EXPECT_EQ(u_ptr1.get(), nullptr);
+ EXPECT_NE(u_ptr2.get(), nullptr);
+}
+
+TEST(UniquePtrForArrays, MoveAssigment) {
+ constexpr std::size_t n{10};
+ ali::unique_ptr u_ptr1{new int[n]};
+ ali::unique_ptr u_ptr2{new int[n]};
+ u_ptr2 = std::move(u_ptr1);
+ EXPECT_EQ(u_ptr1.get(), nullptr);
+ EXPECT_NE(u_ptr2.get(), nullptr);
+}
+
+TEST(UniquePtrForArrays, BoolCast) {
+ constexpr std::size_t n{10};
+ ali::unique_ptr u_ptr1;
+ ali::unique_ptr u_ptr2{new int[n]};
+ EXPECT_EQ(static_cast(u_ptr1), false);
+ EXPECT_EQ(static_cast(u_ptr2), true);
+}
+
+TEST(UniquePtrForArrays, DereferenceTest) {
+ constexpr std::size_t n{5};
+ ali::unique_ptr u_ptr(new int[n] {1, 2, 3, 4, 5});
+ for (size_t i {0}; i < n; i++)
+ EXPECT_EQ(u_ptr[i], i + 1);
+}
+
+TEST(UniquePtrForArrays, EqualityOperator) {
+ constexpr std::size_t n{5};
+ ali::unique_ptr u_ptr1;
+ ali::unique_ptr u_ptr2{new int[n]};
+ EXPECT_EQ(u_ptr1 == u_ptr1, true);
+ EXPECT_EQ(u_ptr1 == u_ptr2, false);
+}
\ No newline at end of file