Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-16 07:35:13

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include <functional>
0012 #include <memory>
0013 #include <type_traits>
0014 #include <utility>
0015 
0016 namespace Acts {
0017 
0018 /// A copyable smart pointer that uses a cloner function to copy the
0019 /// managed object.
0020 ///
0021 /// This enables polymorphic value semantics: you can copy a pointer to a base
0022 /// class by invoking a stored cloner function (typically calling a virtual
0023 /// `clone()` method or a copy constructor).
0024 ///
0025 /// @tparam T The type of the managed object
0026 template <typename T>
0027 class CloneablePtr {
0028  public:
0029   /// The type of the cloner function
0030   using Cloner = std::function<std::unique_ptr<T>(const T&)>;
0031   /// Define the type of the managed object
0032   using element_type = T;
0033 
0034   /// Default constructor, creates a null pointer
0035   CloneablePtr() = default;
0036 
0037   /// Construct from a unique_ptr with a custom cloner
0038   /// @param ptr The unique_ptr to take ownership of
0039   /// @param cloner The cloner function
0040   CloneablePtr(std::unique_ptr<T> ptr, Cloner cloner)
0041       : m_ptr(std::move(ptr)), m_cloner(std::move(cloner)) {}
0042 
0043   /// Construct from a unique_ptr using copy construction as the cloner
0044   /// @param ptr The unique_ptr to take ownership of
0045   /// @note Only available when T is copy-constructible
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   /// Construct by taking ownership of a raw pointer with a custom cloner
0052   /// @param raw The raw pointer to take ownership of
0053   /// @param cloner The cloner function
0054   CloneablePtr(T* raw, Cloner cloner)
0055       : m_ptr(raw), m_cloner(std::move(cloner)) {}
0056 
0057   /// Construct by taking ownership of a raw pointer using copy
0058   /// construction as the cloner
0059   /// @param raw The raw pointer to take ownership of
0060   /// @note Only available when T is copy-constructible
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   /// Copy constructor. Invokes the cloner if the source is non-null.
0067   /// @param other The CloneablePtr to copy from
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   /// Copy assignment. Invokes the cloner if the source is non-null.
0073   /// @param other The CloneablePtr to copy from
0074   /// @return Reference to this
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   /// Move assignment from a unique_ptr
0083   /// @param ptr: The unique_ptr that's assigned to this object
0084   /// @return Reference to this
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   /// Move constructor
0099   CloneablePtr(CloneablePtr&&) noexcept = default;
0100 
0101   /// Move assignment
0102   /// @return Reference to this
0103   CloneablePtr& operator=(CloneablePtr&&) noexcept = default;
0104 
0105   /// Destructor
0106   ~CloneablePtr() = default;
0107 
0108   /// Dereference operator
0109   /// @return Reference to the managed object
0110   T& operator*() const { return *m_ptr; }
0111 
0112   /// Arrow operator
0113   /// @return Pointer to the managed object
0114   T* operator->() const { return m_ptr.get(); }
0115 
0116   /// Boolean conversion, true if non-null
0117   explicit operator bool() const { return m_ptr != nullptr; }
0118 
0119   /// Comparison with nullptr
0120   friend bool operator==(const CloneablePtr& lhs, std::nullptr_t) {
0121     return lhs.m_ptr == nullptr;
0122   }
0123 
0124   /// Get the raw pointer
0125   /// @return Pointer to the managed object, or nullptr
0126   T* get() const { return m_ptr.get(); }
0127 
0128   /// Release ownership of the managed object
0129   /// @return Pointer to the formerly managed object
0130   std::unique_ptr<T> release() {
0131     m_cloner = nullptr;
0132     return std::move(m_ptr);
0133   }
0134 
0135   /// Reset the managed object
0136   /// @param ptr The new raw pointer to manage (default nullptr)
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 }  // namespace Acts