Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include "compressed_pair.h"
- #include <memory>
- #include <cstddef>
- #include <iostream>
- #include <string>
- // Primary template
- template <typename T, typename Deleter = std::default_delete<T>>
- class UniquePtr {
- public:
- // Constructors
- explicit UniquePtr(T* ptr = nullptr) {
- uptr_ = CompressedPair<T*, Deleter>(ptr, Deleter());
- }
- template<typename Del>
- UniquePtr(T *ptr, Del&& deleter) : uptr_(CompressedPair<T*, Deleter>(ptr, std::forward<Del>(deleter))) {
- }
- UniquePtr(const UniquePtr& other) = delete;
- UniquePtr(UniquePtr&& other) noexcept : uptr_(other.uptr_.GetFirst(), std::forward<Deleter>(other.uptr_.GetSecond())) {
- if (uptr_.GetFirst() != other.uptr_.GetFirst()) {
- other.uptr_.GetFirst() = nullptr;
- }
- }
- template <typename Tp, typename Dp>
- UniquePtr(UniquePtr<Tp, Dp>&& other) noexcept : uptr_(other.uptr_.GetFirst(), std::forward<Dp>(other.uptr_.GetSecond())) {
- other.uptr_.GetFirst() = nullptr;
- }
- // `operator=`-s
- UniquePtr& operator=(const UniquePtr& other) = delete;
- UniquePtr& operator=(UniquePtr&& other) noexcept {
- if (uptr_.GetFirst() != other.uptr_.GetFirst()) {
- Reset(other.Release());
- uptr_.GetSecond() = std::forward<Deleter>(other.uptr_.GetSecond());
- }
- return *this;
- }
- template <typename Tp, typename Dp>
- UniquePtr& operator=(UniquePtr<Tp, Dp>&& other) noexcept {
- Reset(other.Release());
- uptr_.GetSecond() = std::forward<Dp>(other.uptr_.GetSecond());
- return *this;
- }
- UniquePtr& operator=(std::nullptr_t) {
- uptr_.GetSecond()(uptr_.GetFirst());
- uptr_ = CompressedPair<T*, Deleter>(nullptr, Deleter());
- return *this;
- }
- // Destructor
- ~UniquePtr() {
- if (uptr_.GetFirst() != nullptr) {
- uptr_.GetSecond()(uptr_.GetFirst());
- }
- }
- //Modifiers
- T* Release() noexcept {
- T* tmp = uptr_.GetFirst();
- uptr_.GetFirst() = nullptr;
- return tmp;
- }
- void Reset(T* ptr = nullptr) noexcept {
- T* old_ptr = uptr_.GetFirst();
- uptr_.GetFirst() = ptr;
- if (old_ptr) {
- uptr_.GetSecond()(old_ptr);
- }
- }
- void Swap(UniquePtr& other) noexcept {
- std::swap(uptr_, other.uptr_);
- }
- //Observers
- T* Get() const noexcept {
- return uptr_.GetFirst();
- }
- Deleter& GetDeleter() {
- return uptr_.GetSecond();
- }
- const Deleter& GetDeleter() const {
- return uptr_.GetSecond();
- }
- explicit operator bool() const {
- return uptr_.GetFirst() != nullptr;
- }
- // Single-object dereference operators
- typename std::add_lvalue_reference<T>::type
- operator*() const {
- return *Get();
- }
- T* operator->() const {
- return uptr_.GetFirst();
- }
- private:
- CompressedPair<T*, Deleter> uptr_;
- template<class U, class D>
- friend class UniquePtr;
- };
- // Specialization for arrays
- template <typename T, typename Deleter>
- class UniquePtr<T[], Deleter> {
- public:
- //Constructors
- explicit UniquePtr(T* ptr = nullptr) {
- uptr_ = CompressedPair<T*, Deleter>(ptr, Deleter());
- }
- UniquePtr(T *ptr, Deleter deleter) {
- uptr_ = CompressedPair<T*, Deleter>(ptr, deleter);
- }
- UniquePtr(const UniquePtr& other) = delete;
- UniquePtr(UniquePtr&& other) noexcept {
- if (uptr_.GetFirst() != other.uptr_.GetFirst()) {
- uptr_ = other.uptr_;
- other.uptr_.GetFirst() = nullptr;
- }
- }
- template <typename Tp, typename Dp>
- UniquePtr(UniquePtr<Tp, Dp>&& other) noexcept : uptr_(other.uptr_.GetFirst(), std::forward<Dp>(other.uptr_.GetSecond())) {
- other.uptr_.GetFirst() = nullptr;
- }
- // `operator=`-s
- UniquePtr& operator=(const UniquePtr& other) = delete;
- UniquePtr& operator=(UniquePtr&& other) noexcept {
- if (uptr_.GetFirst() != other.uptr_.GetFirst()) {
- Reset(other.Release());
- uptr_.GetSecond = std::forward<Deleter>(other.uptr_.GetSecond());
- }
- return *this;
- }
- template <typename Tp, typename Dp>
- UniquePtr& operator=(UniquePtr<Tp, Dp>&& other) noexcept {
- Reset(other.Release());
- uptr_.GetSecond = std::forward<Dp>(other.uptr_.GetSecond());
- return *this;
- }
- UniquePtr& operator=(std::nullptr_t) {
- uptr_.GetSecond()(uptr_.GetFirst());
- uptr_ = CompressedPair<T*, Deleter>(nullptr, Deleter());
- return *this;
- }
- // Destructor
- ~UniquePtr() {
- if (uptr_.GetFirst() != nullptr){
- uptr_.GetSecond()(uptr_.GetFirst());
- }
- }
- // Modifiers
- T* Release() noexcept {
- T* tmp = uptr_.GetFirst();
- uptr_.GetFirst() = nullptr;
- return tmp;
- }
- void Reset(T* ptr = nullptr) noexcept {
- T* old_ptr = uptr_.GetFirst();
- uptr_.GetFirst() = ptr;
- if (old_ptr) {
- uptr_.GetSecond()(old_ptr);
- }
- }
- void Swap(UniquePtr& other) noexcept {
- std::swap(uptr_, other.uptr_);
- }
- T& operator[](size_t i) {
- return Get()[i];
- }
- //Observers
- T* Get() const noexcept {
- return uptr_.GetFirst();
- }
- Deleter& GetDeleter() {
- return uptr_.GetSecond();
- }
- const Deleter& GetDeleter() const {
- return uptr_.GetSecond();
- }
- explicit operator bool() const {
- return uptr_.GetFirst() != nullptr;
- }
- const T& operator[](size_t i) const {
- return Get()[i];
- }
- private:
- CompressedPair<T*, Deleter> uptr_;
- template<class U, class D>
- friend class UniquePtr;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement