File indexing completed on 2026-04-16 07:35:13
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <functional>
0012 #include <memory>
0013 #include <type_traits>
0014 #include <utility>
0015
0016 namespace Acts {
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 template <typename T>
0027 class CloneablePtr {
0028 public:
0029
0030 using Cloner = std::function<std::unique_ptr<T>(const T&)>;
0031
0032 using element_type = T;
0033
0034
0035 CloneablePtr() = default;
0036
0037
0038
0039
0040 CloneablePtr(std::unique_ptr<T> ptr, Cloner cloner)
0041 : m_ptr(std::move(ptr)), m_cloner(std::move(cloner)) {}
0042
0043
0044
0045
0046 explicit CloneablePtr(std::unique_ptr<T> ptr)
0047 requires std::is_copy_constructible_v<T>
0048 : m_ptr(std::move(ptr)),
0049 m_cloner([](const T& src) { return std::make_unique<T>(src); }) {}
0050
0051
0052
0053
0054 CloneablePtr(T* raw, Cloner cloner)
0055 : m_ptr(raw), m_cloner(std::move(cloner)) {}
0056
0057
0058
0059
0060
0061 explicit CloneablePtr(T* raw)
0062 requires std::is_copy_constructible_v<T>
0063 : m_ptr(raw),
0064 m_cloner([](const T& src) { return std::make_unique<T>(src); }) {}
0065
0066
0067
0068 CloneablePtr(const CloneablePtr& other)
0069 : m_ptr(other.m_ptr ? other.m_cloner(*other.m_ptr) : nullptr),
0070 m_cloner(other.m_cloner) {}
0071
0072
0073
0074
0075 CloneablePtr& operator=(const CloneablePtr& other) noexcept {
0076 if (this != &other) {
0077 m_ptr = other.m_ptr ? other.m_cloner(*other.m_ptr) : nullptr;
0078 m_cloner = other.m_cloner;
0079 }
0080 return *this;
0081 }
0082
0083
0084
0085 template <typename T1>
0086 CloneablePtr& operator=(std::unique_ptr<T1>&& ptr) noexcept
0087 requires(std::is_copy_constructible_v<T1> && std::is_base_of_v<T, T1>)
0088 {
0089 m_ptr = std::move(ptr);
0090 if constexpr (!std::is_same_v<const T, const T1>) {
0091 m_cloner = [](const T& obj) {
0092 return std::make_unique<T1>(static_cast<const T1&>(obj));
0093 };
0094 }
0095 return *this;
0096 }
0097
0098
0099 CloneablePtr(CloneablePtr&&) noexcept = default;
0100
0101
0102
0103 CloneablePtr& operator=(CloneablePtr&&) noexcept = default;
0104
0105
0106 ~CloneablePtr() = default;
0107
0108
0109
0110 T& operator*() const { return *m_ptr; }
0111
0112
0113
0114 T* operator->() const { return m_ptr.get(); }
0115
0116
0117 explicit operator bool() const { return m_ptr != nullptr; }
0118
0119
0120 friend bool operator==(const CloneablePtr& lhs, std::nullptr_t) {
0121 return lhs.m_ptr == nullptr;
0122 }
0123
0124
0125
0126 T* get() const { return m_ptr.get(); }
0127
0128
0129
0130 std::unique_ptr<T> release() {
0131 m_cloner = nullptr;
0132 return std::move(m_ptr);
0133 }
0134
0135
0136
0137 void reset(T* ptr = nullptr) {
0138 m_ptr.reset(ptr);
0139 if (m_ptr == nullptr) {
0140 m_cloner = nullptr;
0141 }
0142 }
0143
0144 private:
0145 std::unique_ptr<T> m_ptr;
0146 Cloner m_cloner;
0147 };
0148
0149 }