/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef MAPLE_UTIL_PTR_H #define MAPLE_UTIL_PTR_H #include namespace maple { namespace utils { template using PtrCheckerType = void (*)(const T *); template inline constexpr void CheckNothing(const T *) { } template Check = CheckNothing> class Ptr { public: using Pointer = T *; using ElementType = T; constexpr Ptr() noexcept : pointer(nullptr) { Check(nullptr); } constexpr explicit Ptr(std::nullptr_t) noexcept : pointer(nullptr) { Check(nullptr); } explicit Ptr(Pointer ptr) : pointer(ptr) { Check(ptr); } Ptr(Pointer ref, PtrCheckerType checker) : pointer(ref) { checker(pointer); } explicit Ptr(T &ref) : pointer(&ref) { Check(pointer); } Ptr(T &ref, PtrCheckerType checker) : pointer(&ref) { checker(pointer); } explicit Ptr(T &&ref) = delete; template ::value>> explicit Ptr(U *ptr) : pointer(ptr) { Check(pointer); } template ::value>> explicit Ptr(U &ref) : pointer(&ref) { Check(pointer); } template ::value>> Ptr(U &ref, PtrCheckerType checker) : pointer(&ref) { checker(pointer); } template ::value>> explicit Ptr(U &&ref) = delete; explicit Ptr(const Ptr &other) : pointer(other.get()) {} explicit Ptr(Ptr &&other) noexcept : pointer(other.get()) {} template CheckU, typename = std::enable_if_t::value>> explicit Ptr(const Ptr &other) : pointer(other.get()) { Check(pointer); } template CheckU, typename = std::enable_if_t::value>> Ptr(const Ptr &other, PtrCheckerType checker) : pointer(other.get()) { checker(pointer); } template CheckU, typename = std::enable_if_t::value>> explicit Ptr(Ptr &&other) : pointer(other.get()) { Check(pointer); } template CheckU, typename = std::enable_if_t::value>> Ptr(Ptr &&other, PtrCheckerType checker) : pointer(other.get()) { checker(pointer); } ~Ptr() = default; Ptr &operator=(Pointer ptr) noexcept { Check(ptr); pointer = ptr; return *this; } Ptr &operator=(std::nullptr_t) noexcept { Check(nullptr); reset(); return *this; } Ptr &operator=(const Ptr &ptr) noexcept { if (&ptr != this) { pointer = ptr.pointer; } return *this; } Ptr &operator=(Ptr &&ptr) noexcept { if (&ptr != this) { pointer = std::move(ptr.pointer); } return *this; } template CheckU, typename = std::enable_if_t::value>> Ptr &operator=(const Ptr &ptr) noexcept { if (this->get() != ptr.get()) { Check(ptr.get()); pointer = ptr.get(); } return *this; } template CheckU, typename = std::enable_if_t::value>> Ptr &operator=(Ptr &&ptr) noexcept { if (this->get() != ptr.get()) { Check(ptr.get()); pointer = std::move(ptr.get()); } return *this; } Pointer release() noexcept = delete; void reset(Pointer ptr = Pointer()) noexcept { Check(ptr); pointer = ptr; } void swap(Ptr &other) noexcept { std::swap(pointer, other.pointer); } T *get() const noexcept { return pointer; } explicit operator bool() const noexcept { return get() != nullptr; } T &operator*() const { return *get(); } T *operator->() const noexcept { return get(); } T &operator[](size_t i) const = delete; Ptr &operator++() = delete; const Ptr operator++(int) = delete; Ptr &operator--() = delete; const Ptr operator--(int) = delete; Ptr &operator+=(std::ptrdiff_t) = delete; Ptr &operator-=(std::ptrdiff_t) = delete; private: T *pointer; }; template CheckT, typename U, PtrCheckerType CheckU> inline bool operator==(const Ptr &lhs, const Ptr &rhs) { return lhs.get() == rhs.get(); } template CheckT, typename U, PtrCheckerType CheckU> inline bool operator!=(const Ptr &lhs, const Ptr &rhs) { return !(lhs == rhs); } template CheckT, typename U, PtrCheckerType CheckU> inline bool operator<(const Ptr &lhs, const Ptr &rhs) { return lhs.get() < rhs.get(); } template CheckT, typename U, PtrCheckerType CheckU> inline bool operator<=(const Ptr &lhs, const Ptr &rhs) { return lhs.get() <= rhs.get(); } template CheckT, typename U, PtrCheckerType CheckU> inline bool operator>(const Ptr &lhs, const Ptr &rhs) { return !(lhs <= rhs); } template CheckT, typename U, PtrCheckerType CheckU> inline bool operator>=(const Ptr &lhs, const Ptr &rhs) { return !(lhs < rhs); } template CheckT> inline bool operator==(const Ptr &lhs, std::nullptr_t) { return !static_cast(lhs); } template CheckT> inline bool operator==(std::nullptr_t, const Ptr &rhs) { return !static_cast(rhs); } template CheckT> inline bool operator!=(const Ptr &lhs, std::nullptr_t) { return static_cast(lhs); } template CheckT> inline bool operator!=(std::nullptr_t, const Ptr &rhs) { return static_cast(rhs); } template CheckT> inline bool operator<(const Ptr &lhs, std::nullptr_t) { return std::less::Pointer>()(lhs.get(), nullptr); } template CheckT> inline bool operator<(std::nullptr_t, const Ptr &rhs) { return std::less::Pointer>()(nullptr, rhs.get()); } template CheckT> inline bool operator<=(const Ptr &lhs, std::nullptr_t) { return !(lhs > nullptr); } template CheckT> inline bool operator<=(std::nullptr_t, const Ptr &rhs) { return !(rhs < nullptr); } template CheckT> inline bool operator>(const Ptr &lhs, std::nullptr_t) { return !(lhs <= nullptr); } template CheckT> inline bool operator>(std::nullptr_t, const Ptr &rhs) { return !(rhs >= nullptr); } template CheckT> inline bool operator>=(const Ptr &lhs, std::nullptr_t) { return !(lhs < nullptr); } template CheckT> inline bool operator>=(std::nullptr_t, const Ptr &rhs) { return !(rhs > nullptr); } } // namespace utils } // namespace maple #endif // DIY_CPLUSPLUS_SAFE_PTR_H