File indexing completed on 2026-07-26 08:22:00
0001
0002
0003
0004
0005
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 }