From 74bb9cd27242b9320f99ff4d2b50c3051576cc14 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 8 Feb 2022 16:53:51 +0800 Subject: ... --- include/cru/common/ClonablePtr.h | 216 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 include/cru/common/ClonablePtr.h (limited to 'include/cru/common/ClonablePtr.h') diff --git a/include/cru/common/ClonablePtr.h b/include/cru/common/ClonablePtr.h new file mode 100644 index 00000000..39b5b454 --- /dev/null +++ b/include/cru/common/ClonablePtr.h @@ -0,0 +1,216 @@ +#pragma once + +#include +#include +#include +#include + +namespace cru { +template +class ClonablePtr { + template + friend class ClonablePtr; + + public: + using element_type = typename std::unique_ptr::element_type; + using pointer = typename std::unique_ptr::pointer; + + ClonablePtr() = default; + ClonablePtr(std::nullptr_t) noexcept : ptr_(nullptr) {} + explicit ClonablePtr(pointer p) noexcept : ptr_(p) {} + ClonablePtr(std::unique_ptr&& p) noexcept + : ptr_(std::move(p)) {} + template ::pointer, pointer>, + int> = 0> + ClonablePtr(std::unique_ptr&& p) : ptr_(std::move(p)) {} + ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} + ClonablePtr(ClonablePtr&& other) = default; + template ::pointer, pointer>, + int> = 0> + ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} + template ::pointer, pointer>, + int> = 0> + ClonablePtr(ClonablePtr&& other) noexcept : ptr_(std::move(other.ptr_)) {} + ClonablePtr& operator=(std::nullptr_t) noexcept { + ptr_ = nullptr; + return *this; + } + ClonablePtr& operator=(std::unique_ptr&& other) noexcept { + ptr_ = std::move(other); + return *this; + } + template ::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(std::unique_ptr&& p) noexcept { + ptr_ = std::move(p); + return *this; + } + ClonablePtr& operator=(const ClonablePtr& other) { + if (this != &other) { + ptr_ = std::unique_ptr(other.ptr_->Clone()); + } + return *this; + } + ClonablePtr& operator=(ClonablePtr&& other) = default; + template ::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(const ClonablePtr& other) noexcept { + if (this != &other) { + ptr_ = std::unique_ptr(other.ptr_->Clone()); + } + return *this; + } + template ::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(ClonablePtr&& other) noexcept { + ptr_ = std::move(other.ptr_); + } + + ~ClonablePtr() = default; + + public: + pointer release() noexcept { return ptr_.release(); } + void reset(pointer p = pointer()) noexcept { ptr_.reset(p); } + void swap(ClonablePtr& other) noexcept { ptr_.swap(other.ptr_); } + + public: + pointer get() const noexcept { return ptr_.get(); } + + operator bool() const noexcept { return ptr_; } + + element_type& operator*() const noexcept { return *ptr_; } + pointer operator->() const noexcept { return ptr_.get(); } + + int Compare(const ClonablePtr& other) const noexcept { + if (ptr_ == other.ptr_) { + return 0; + } else if (ptr_ < other.ptr_) { + return -1; + } else { + return 1; + } + } + + int Compare(nullptr_t) const noexcept { return ptr_ ? 1 : 0; } + + private: + std::unique_ptr ptr_; +}; + +template +void swap(ClonablePtr& left, ClonablePtr& right) noexcept { + left.swap(right); +} + +template +bool operator==(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) == 0; +} + +template +bool operator!=(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) != 0; +} + +template +bool operator<(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) < 0; +} + +template +bool operator<=(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) <= 0; +} + +template +bool operator>(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) > 0; +} + +template +bool operator>=(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) >= 0; +} + +template +bool operator==(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) == 0; +} + +template +bool operator!=(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) != 0; +} + +template +bool operator<(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) < 0; +} + +template +bool operator<=(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) <= 0; +} + +template +bool operator>(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) > 0; +} + +template +bool operator>=(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) >= 0; +} + +template +bool operator==(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) == 0; +} + +template +bool operator!=(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) != 0; +} + +template +bool operator<(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) > 0; +} + +template +bool operator<=(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) >= 0; +} + +template +bool operator>(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) < 0; +} + +template +bool operator>=(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) <= 0; +} + +} // namespace cru + +namespace std { +template +struct hash> { + std::size_t operator()(const cru::ClonablePtr& p) const { + return std::hash::pointer>(p.get()); + } +}; +} // namespace std -- cgit v1.2.3