Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-26 08:22:00

0001 /** TRACCC library, part of the ACTS project (R&D line)
0002  *
0003  * (c) 2024-2026 CERN for the benefit of the ACTS project
0004  *
0005  * Mozilla Public License Version 2.0
0006  */
0007 
0008 #pragma once
0009 
0010 #include <any>
0011 
0012 #include "traccc/definitions/primitives.hpp"
0013 
0014 namespace traccc {
0015 
0016 class move_only_any {
0017  public:
0018   move_only_any() = default;
0019   move_only_any(const move_only_any &) = delete;
0020   move_only_any &operator=(const move_only_any &) = delete;
0021 
0022   template <typename obj_t>
0023   explicit move_only_any(obj_t &&obj)
0024     requires(!std::same_as<std::decay_t<obj_t>, move_only_any>)
0025       : m_obj(std::malloc(sizeof(obj_t))),
0026         m_type(&typeid(obj_t)),
0027         m_destructor(get_destructor<obj_t>()) {
0028     new (m_obj) obj_t(std::forward<obj_t>(obj));
0029   }
0030 
0031   move_only_any(move_only_any &&other) noexcept
0032       : m_obj(other.m_obj),
0033         m_type(other.m_type),
0034         m_destructor(other.m_destructor) {
0035     other.m_obj = nullptr;
0036     other.m_type = nullptr;
0037     other.m_destructor = nullptr;
0038   }
0039 
0040   move_only_any &operator=(move_only_any &&other) noexcept {
0041     reset();
0042 
0043     m_obj = other.m_obj;
0044     other.m_obj = nullptr;
0045     m_type = other.m_type;
0046     other.m_type = nullptr;
0047     m_destructor = other.m_destructor;
0048     other.m_destructor = nullptr;
0049 
0050     return *this;
0051   }
0052 
0053   ~move_only_any() { reset(); }
0054 
0055   void reset() {
0056     if (m_obj != nullptr) {
0057       assert(m_destructor != nullptr);
0058       m_destructor(m_obj);
0059       std::free(m_obj);
0060     }
0061   }
0062 
0063   template <typename obj_t>
0064   void set(obj_t &&obj)
0065     requires(!std::same_as<std::decay_t<obj_t>, move_only_any>)
0066   {
0067     if (m_obj != nullptr) {
0068       assert(m_destructor != nullptr);
0069       m_destructor(m_obj);
0070       std::free(m_obj);
0071     }
0072 
0073     m_obj = std::malloc(sizeof(obj_t));
0074     new (m_obj) obj_t(std::forward<obj_t>(obj));
0075 
0076     m_type = &typeid(obj_t);
0077     m_destructor = get_destructor<obj_t>();
0078   }
0079 
0080   template <typename obj_t>
0081   bool is() const {
0082     if (m_type == nullptr) {
0083       return false;
0084     } else {
0085       return (*m_type == typeid(obj_t));
0086     }
0087   }
0088 
0089   bool has_value() const {
0090     if (m_type != nullptr) {
0091       assert(m_obj != nullptr && m_destructor != nullptr);
0092       return true;
0093     } else {
0094       assert(m_obj == nullptr && m_destructor == nullptr);
0095       return false;
0096     }
0097   }
0098 
0099   const std::type_info &type() const {
0100     if (!has_value()) {
0101       throw std::logic_error(
0102           "Type ID for `traccc::move_only_any` requested, but no value "
0103           "exists.");
0104     }
0105 
0106     return *m_type;
0107   }
0108 
0109   template <typename obj_t>
0110   obj_t &as() const {
0111     if (!has_value()) {
0112       throw std::logic_error(
0113           "Value for `traccc::move_only_any` requested, but no value "
0114           "exists.");
0115     }
0116     if (!is<obj_t>()) {
0117       throw std::bad_any_cast();
0118     }
0119 
0120     return *static_cast<obj_t *>(m_obj);
0121   }
0122 
0123  private:
0124   template <typename obj_t>
0125   void (*get_destructor() const)(void *) {
0126     return static_cast<void (*)(void *)>(
0127         [](void *ptr) { static_cast<obj_t *>(ptr)->~obj_t(); });
0128   }
0129 
0130   void *m_obj = nullptr;
0131   const std::type_info *m_type = nullptr;
0132   void (*m_destructor)(void *) = nullptr;
0133 };
0134 
0135 }  // namespace traccc