C++实现智能指针部分功能(UniquePtr, SmartPtr, WeakPtr), head only(更新中)

33 篇文章 0 订阅

先放代码

只实现了基础功能,基本用法和智能指针相差不大,提供了UniquePtr转std::unique_ptr的方法,提供了删除器

#pragma once

#include <memory> /* For std::move, std::forward, std::unique_ptr */
#include <utility> /* For std::exchange */
#include <type_traits> /* For template check */
#include <atomic> /* For std::atomic */

/* Deleter, details see std::default_delete<T> */
namespace csp {

	template<typename T>
	class DefaultDeleter {
	public:
		constexpr DefaultDeleter() noexcept = default;
		virtual ~DefaultDeleter() noexcept = default;

		template<typename U, std::enable_if_t<std::is_convertible_v<U*, T*>, int> = 0>
		DefaultDeleter(const DefaultDeleter<U>&) noexcept {}

		/* Call for delete */
		void operator()(T* p) const noexcept {
			delete p;
			p = nullptr;
		}

		/* Compatible std deleter */
		operator std::default_delete<T>() const noexcept {
			return std::default_delete<T>();
		}

	};

	/* Used for array */
	template<typename T>
	class DefaultDeleter<T[]> {
	public:
		constexpr DefaultDeleter() noexcept = default;
		virtual ~DefaultDeleter() noexcept = default;

		template<typename U, std::enable_if_t<std::is_convertible_v<U(*)[], T(*)[]>, int> = 0>
		DefaultDeleter(const DefaultDeleter<U[]>&) noexcept {}

		/* Call for delete */
		void operator()(T* p) const noexcept {
			delete[] p;
		}

		/* Compatible std deleter */
		operator std::default_delete<T[]>() const noexcept {
			return std::default_delete<T[]>();
		}

	};

}

/* Unique pointer */
namespace csp {

	template<typename T, typename D = DefaultDeleter<T>>
	class UniquePtr final {

		using ElementType = T;
		using Pointer = ElementType*;
		using DeleterType = D;

	private:
		Pointer ptr;
		DeleterType deleter;
		
	public:
		/* Constructor */
		constexpr UniquePtr(Pointer p) noexcept : ptr(p) {}
		constexpr UniquePtr(Pointer p, DeleterType& deleter) noexcept : ptr(p), deleter(std::forward(deleter)) {}
		constexpr UniquePtr(void) noexcept : ptr(nullptr) {}
		constexpr UniquePtr(std::nullptr_t) noexcept : ptr(nullptr) {}
		constexpr UniquePtr(const UniquePtr<T, D>&) noexcept = delete; // Disable the copy constructor
		constexpr UniquePtr(UniquePtr<T, D>&& up) noexcept : ptr(up.release()), deleter(up.getDeleter()) {}

		/* Deconstructor */
		~UniquePtr() noexcept {
			if (ptr) { deleter(ptr); }
		}

		/* Operators */
		UniquePtr<T, D>& operator=(const UniquePtr<T, D>&) noexcept = delete; // Disable the copy assignment operator

		UniquePtr<T, D>& operator=(UniquePtr<T, D>&& rhs) noexcept {
			if ((&rhs) != this) {
				reset(rhs.release());
				deleter = rhs.getDeleter();
			}
			return *this;
		};

		Pointer operator->() const noexcept { return ptr; } // UniquePtr<T> upt; upt->;
		ElementType& operator*() const noexcept { return *ptr; } // UniquePtr<T> upt; (*upt).;

		/* Functions */
		Pointer get() const noexcept { return ptr; }
		DeleterType getDeleter() noexcept { return static_cast<const UniquePtr<T, D>&>(*this).getDeleter(); }
		const DeleterType& getDeleter() const noexcept { return deleter; }
		Pointer release() noexcept { return std::exchange(ptr, nullptr); }
		void swap(UniquePtr<T, D>& p) noexcept { std::swap(ptr, p.ptr); } // not swap the deleter

		void reset(Pointer p = nullptr) noexcept {
			if (nullptr == p) { return; }
			if (ptr) { deleter(ptr); }
			std::swap(ptr, p);
		}

		/* If you want to call this function, you must make sure that your deleter can transorm to std::default_deleter<T> */
		std::unique_ptr<T, D> toStdUniquePtr() {
			return std::unique_ptr<T, D>(release(), deleter);
		}

	};

	template<typename T, typename D = DefaultDeleter<T>, typename ...Args>
	UniquePtr<T, D> makeUnique(Args&&... args) {
		return UniquePtr<T, D>(new T(std::forward<Args>(args)...));
	}

}

/* Shared pointer */
namespace csp {

	class CounterBase {
	public:
		virtual ~CounterBase() {}
		virtual void incRefCount() noexcept = 0;
		virtual void incWeakRefCount() noexcept = 0;
		virtual void decRefCount() noexcept = 0;
		virtual void decWeakRefCount() noexcept = 0;
		virtual long useCount() const noexcept = 0;
		virtual bool unique() const noexcept = 0;
		virtual long weakUseCount() const noexcept = 0;
		virtual bool expired() const noexcept = 0;
		virtual void* getDeleter() noexcept = 0;
	};

	template<typename T, typename D = DefaultDeleter<T>>
	class Counter : public CounterBase {

		using ElementType = T;
		using Pointer = ElementType*;
		using DeleterType = D;

	private:
		std::atomic_long _useCount;
		std::atomic_long _weakUseCount;
		Pointer ptr;
		DeleterType deleter;

	public:
		constexpr Counter(Pointer p) :
			_useCount(1),
			_weakUseCount(1),
			ptr(p),
			deleter{} {}

		constexpr Counter(Pointer p, DeleterType deleter) :
			_useCount(1),
			_weakUseCount(1),
			ptr(p),
			deleter(std::forward(deleter)) {}

		virtual ~Counter() {}

		/* Overrides */
		virtual void incRefCount() noexcept { ++_useCount; }
		virtual void incWeakRefCount() noexcept { ++_weakUseCount; }

		virtual void decRefCount() noexcept {
			--_useCount;
			if (0 == _useCount) {
				if (ptr) {
					deleter(ptr);
				}
				decWeakRefCount();
			}
		}

		virtual void decWeakRefCount() noexcept {
			--_weakUseCount;
			if (0 == _weakUseCount) {
				delete this;
			}
		}

		virtual long useCount() const noexcept { return _useCount; }
		virtual bool unique() const noexcept { return 1 == _useCount; }
		virtual long weakUseCount() const noexcept { return _weakUseCount - (_useCount ? 1 : 0); }
		virtual bool expired() const noexcept { return 0 == _useCount; }
		virtual void* getDeleter() noexcept { return reinterpret_cast<void*>(std::addressof(deleter)); }

	};

	template<typename T, typename D = DefaultDeleter<T>>
	class SharedPtr;

	template<typename T, typename D = DefaultDeleter<T>>
	class WeakPtr final {

		// using ElementType = std::remove_extent<T>::type;
		using ElementType = T;
		using Pointer = ElementType*;
		using DeleterType = D;

	private:
		Pointer ptr;
		CounterBase* counter;

	public:

		friend class SharedPtr<T, D>;

		/* Constructors */
		constexpr WeakPtr(void) noexcept :
			ptr(nullptr),
			counter(nullptr) {}

		WeakPtr(const SharedPtr<T, D>& sp) noexcept :
			ptr(sp.ptr),
			counter(sp.counter) {
			if (counter) {
				counter->incWeakRefCount();
			}
		}

		WeakPtr(const WeakPtr<T, D>* wp) noexcept :
			ptr(wp.ptr),
			counter(wp.counter) {
			if (counter) {
				counter->incWeakRefCount();
			}
		}

		/* Deconstructor */
		~WeakPtr() {
			if (counter) {
				counter->decWeakRefCount();
			}
		}

		/* Operators */
		WeakPtr<T, D>& operator=(const WeakPtr<T, D>& wp) noexcept {
			const_cast<WeakPtr<T, D>&>(wp).swap(*this);
			return *this;
		}

		WeakPtr<T, D>& operator=(const SharedPtr<T, D>& sp) noexcept {
			/* First, use static_cast to change sp to wp, <const SharedPtr<T, D>&> -> <const WeakPtr<T, D>&> */
			/* Second, use const_cast to remove const, <const WeakPtr<T, D>&> -> <WeakPtr<T, D>&> */
			const_cast<WeakPtr<T, D>&>(static_cast<const WeakPtr<T, D>&>(sp)).swap(*this);
			return *this;
		}

		/* Functions */
		void swap(WeakPtr<T, D>& wp) noexcept {
			std::swap(ptr, wp.ptr);
			std::swap(counter, wp.counter);
		}

		void reset() noexcept { WeakPtr<T, D>().swap(*this); }
		long useCount() const noexcept { return counter ? counter->useCount() : 0; }
		bool expired() const noexcept { return counter ? counter->expired() : false; }
		SharedPtr<T, D> lock() const noexcept { return SharedPtr<T, D>(expired() ? nullptr : *this); }

	};

	template<typename T, typename D = DefaultDeleter<T>>
	class SharedPtr final {

		using ElementType = T;
		using Pointer = ElementType*;
		using DeleterType = D;

	private:
		Pointer ptr;
		CounterBase* counter;

	public:

		friend class WeakPtr<T, D>;

		/* Constructor */
		constexpr SharedPtr(void) noexcept :
			ptr(nullptr),
			counter(nullptr) {}

		constexpr SharedPtr(std::nullptr_t) noexcept :
			ptr(nullptr),
			counter(nullptr) {}

		constexpr SharedPtr(std::nullptr_t p, DeleterType deleter) noexcept :
			ptr(nullptr),
			counter(new Counter<T, D>(p, deleter)) {}

		constexpr SharedPtr(Pointer p) noexcept :
			ptr(p),
			counter(new Counter<T, D>(p)) {}

		constexpr SharedPtr(Pointer p, DeleterType deleter) noexcept :
			ptr(p),
			counter(new Counter<T, D>(p, deleter)) {}

		SharedPtr(const SharedPtr<T, D>& sp) noexcept :
			ptr(sp.ptr),
			counter(sp.counter) {
			if (counter) {
				counter->incRefCount();
			}
		}

		SharedPtr(SharedPtr<T, D>&& sp) noexcept :
			ptr(std::exchange(sp.ptr, nullptr)),
			counter(std::exchange(sp.counter, nullptr)) {}

		SharedPtr(const WeakPtr<T, D>& wp) noexcept(false) :
			ptr(wp.ptr),
			counter(wp.counter) {
			if (wp.expired()) {
				/* Compatible with std error */
				throw std::bad_weak_ptr();
			}
			counter->incRefCount();
		}

		/* Deconstructor */
		~SharedPtr() {
			if (counter) {
				counter->decRefCount();
			}
		}

		/* Operators */
		SharedPtr<T, D>& operator=(const SharedPtr<T, D>& sp) noexcept {
			const_cast<SharedPtr<T, D>&>(sp).swap(*this);
			return *this;
		}

		SharedPtr<T, D>& operator=(SharedPtr<T, D>&& sp) noexcept {
			const_cast<SharedPtr<T, D>&>(std::move(sp)).swap(*this);
			return *this;
		}

		Pointer operator->() const noexcept { return ptr; } // UniquePtr<T> upt; upt->;
		ElementType& operator*() const noexcept { return *ptr; } // UniquePtr<T> upt; (*upt).;

		/* Functions */
		void swap(SharedPtr<T, D>& sp) noexcept {
			std::swap(ptr, sp.ptr);
			std::swap(counter, sp.counter);
		}

		void reset() noexcept { SharedPtr<T, D>().swap(*this); }
		Pointer get() const noexcept { return ptr; }
		long useCount() const noexcept { return counter ? counter->useCount() : 0; }
		bool unique() const noexcept { return counter ? counter->unique() : false; }

	};

	template<typename T, typename D = DefaultDeleter<T>, typename ...Args>
	SharedPtr<T, D> makeShared(Args&&... args) {
		return SharedPtr<T, D>(new T(std::forward<Args>(args)...));
	}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值