/* * Copyright (C) 2025 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once #include template using ExtUniquePtrT = std::unique_ptr; template void cloneExt(ExtUniquePtrT &dst, const T &src); template void allocateExt(ExtUniquePtrT &dst); template void destroyExt(T *dst); namespace Impl { template struct UniquePtrWrapperOps { auto operator*() const noexcept(noexcept(std::declval().operator*())) { return *static_cast(this)->ptr; } auto operator->() const noexcept { return static_cast(this)->ptr.operator->(); } explicit operator bool() const noexcept { return static_cast(static_cast(this)->ptr); } template friend bool operator==(const ParentT &lhs, const Rhs &rhs) { return lhs.ptr == rhs; } template friend bool operator==(const Lhs &lhs, const ParentT &rhs) { return lhs == rhs.ptr; } friend bool operator==(const ParentT &lhs, const ParentT &rhs) { return lhs.ptr == rhs.ptr; } }; } // namespace Impl template struct Ext : Impl::UniquePtrWrapperOps> { Ext(T *ptr) : ptr(ptr, destroyExt) {} Ext() { if constexpr (allocateAtInit) { allocateExt(ptr); } } Ext(const Ext &rhs) { if (rhs.ptr.get()) { cloneExt(this->ptr, *rhs.ptr.get()); } } Ext &operator=(const Ext &rhs) { if (this == &rhs) { return *this; } if (rhs.ptr.get()) { cloneExt(this->ptr, *rhs.ptr.get()); } else { ptr.reset(); } return *this; } ~Ext() = default; Ext(Ext &&rhs) noexcept = default; Ext &operator=(Ext &&rhs) noexcept = default; ExtUniquePtrT ptr{nullptr, destroyExt}; }; template struct Clonable : Impl::UniquePtrWrapperOps> { Clonable(T *ptr) : ptr(ptr) {} Clonable() = default; Clonable(const Clonable &rhs) { if (rhs.ptr != nullptr) { this->ptr = std::make_unique(*rhs.ptr); } } Clonable &operator=(const Clonable &rhs) { if (this == &rhs) { return *this; } if (rhs.ptr == nullptr) { ptr.reset(); return *this; } this->ptr = std::make_unique(*rhs.ptr); return *this; } ~Clonable() = default; Clonable(Clonable &&rhs) noexcept = default; Clonable &operator=(Clonable &&rhs) noexcept = default; std::unique_ptr ptr; };