Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 1 .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bazel-*
10 changes: 10 additions & 0 deletions 10 BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cc_library(
name = "build_header",
hdrs = [
"ali_unique_ptr.h"
],
copts = [
"-std=c++2a",
],
visibility = ["//visibility:public"]
)
11 changes: 10 additions & 1 deletion 11 README.md
Original file line number Diff line number Diff line change
@@ -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:
<div>
<pre><code>$ bazel test tests:ali_unique_ptr_test --repo_env=CC=g++-10
</code></pre>
</div>
7 changes: 7 additions & 0 deletions 7 WORKSPACE
Original file line number Diff line number Diff line change
@@ -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",
)
101 changes: 101 additions & 0 deletions 101 ali_unique_ptr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//
// Created by Ali Moammeri on 3/28/22.
//

#ifndef ALI_UNIQUE_PTR_H
#define ALI_UNIQUE_PTR_H

#include <iostream>
#include <cctype>
#include <compare>

namespace ali {
template<class T> class unique_ptr {
friend std::ostream& operator<<(std::ostream&, const unique_ptr<T>&);
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 T> class unique_ptr<T[]> {
friend std::ostream& operator<<(std::ostream&, const unique_ptr<T[]>&);
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<typename T>
std::ostream& operator<<(std::ostream& out, const ali::unique_ptr<T>& u_ptr) {
out << u_ptr.get();
return out;
}

#endif //ALI_UNIQUE_PTR_H
11 changes: 11 additions & 0 deletions 11 tests/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
cc_test(
name = "ali_unique_ptr_test",
srcs = glob(["**/*.cc"]),
copts = [
"-std=c++2a",
],
deps = [
"//:build_header",
"@googletest//:gtest_main",
],
)
159 changes: 159 additions & 0 deletions 159 tests/ali_unique_ptr_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#include "ali_unique_ptr.h"
#include <cctype>
#include <gtest/gtest.h>

TEST(UniquePtrTest, DefaultConstructor) {
ali::unique_ptr<int> u_ptr;
EXPECT_EQ(u_ptr.get(), nullptr);
}

TEST(UniquePtrTest, NullConstructor) {
ali::unique_ptr<int> u_ptr{nullptr};
EXPECT_EQ(u_ptr.get(), nullptr);
}

TEST(UniquePtrTest, PointerConstructor) {
ali::unique_ptr<int> u_ptr{new int};
EXPECT_NE(u_ptr.get(), nullptr);
}

TEST(UniquePtrTest, MoveCostructor) {
ali::unique_ptr<int> u_ptr1{new int};
ali::unique_ptr<int> u_ptr2{std::move(u_ptr1)};
EXPECT_EQ(u_ptr1.get(), nullptr);
EXPECT_NE(u_ptr2.get(), nullptr);
}

TEST(UniquePtrTest, ReleaseTest) {
ali::unique_ptr<int> u_ptr1{new int};
ali::unique_ptr<int> u_ptr2{u_ptr1.release()};
EXPECT_EQ(u_ptr1.get(), nullptr);
EXPECT_NE(u_ptr2.get(), nullptr);
}

TEST(UniquePtrTest, ResetTest) {
ali::unique_ptr<int> 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<int> u_ptr1{new int{a}};
ali::unique_ptr<int> 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<int> u_ptr1{new int{a}};
ali::unique_ptr<int> 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<int> u_ptr1{new int};
ali::unique_ptr<int> u_ptr2{new int};
EXPECT_EQ(u_ptr1 == u_ptr2, 0);
EXPECT_EQ(u_ptr1 == u_ptr1, 1);
}

TEST(UniquePtrTest, NEqualityOperator) {
ali::unique_ptr<int> u_ptr1{new int};
ali::unique_ptr<int> u_ptr2{new int};
EXPECT_EQ(u_ptr1 != u_ptr2, true);
EXPECT_EQ(u_ptr1 != u_ptr1, false);
}

TEST(UniquePtrTest, ComparisionOperatorsTest) {
ali::unique_ptr<int> u_ptr1{new int};
ali::unique_ptr<int> u_ptr2{new int};
EXPECT_EQ(u_ptr1 < u_ptr2, false);
EXPECT_EQ(u_ptr1 > u_ptr2, true);
}

TEST(UniquePtrTest, BoolCastTest) {
ali::unique_ptr<int> u_ptr1;
ali::unique_ptr<int> u_ptr2{new int};
EXPECT_EQ(static_cast<bool>(u_ptr1), false);
EXPECT_EQ(static_cast<bool>(u_ptr2), true);
}

TEST(UniquePtrForArrays, Constructor) {
constexpr std::size_t n {5};
ali::unique_ptr<int[]> u_ptr{new int[n]};
EXPECT_NE(u_ptr.get(), nullptr);
}

TEST(UniquePtrForArrays, MoveCostructor) {
constexpr std::size_t n{5};
ali::unique_ptr<int[]> u_ptr1{new int[n]};
EXPECT_NE(u_ptr1.get(), nullptr);
ali::unique_ptr<int[]> 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<int[]> 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<int[]> 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<int[]> u_ptr1{new int[n]};
ali::unique_ptr<int[]> 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<int[]> u_ptr1{new int[n]};
ali::unique_ptr<int[]> 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<int[]> u_ptr1;
ali::unique_ptr<int[]> u_ptr2{new int[n]};
EXPECT_EQ(static_cast<bool>(u_ptr1), false);
EXPECT_EQ(static_cast<bool>(u_ptr2), true);
}

TEST(UniquePtrForArrays, DereferenceTest) {
constexpr std::size_t n{5};
ali::unique_ptr<int[]> 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<int[]> u_ptr1;
ali::unique_ptr<int[]> u_ptr2{new int[n]};
EXPECT_EQ(u_ptr1 == u_ptr1, true);
EXPECT_EQ(u_ptr1 == u_ptr2, false);
}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.