File indexing completed on 2026-08-06 08:27:10
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Utilities/HashedString.hpp"
0012
0013 #include <algorithm>
0014 #include <any>
0015 #include <array>
0016 #include <cassert>
0017 #include <cstddef>
0018 #include <type_traits>
0019 #include <typeinfo>
0020 #include <utility>
0021
0022
0023
0024
0025
0026 #if defined(_ACTS_ANY_ENABLE_TRACK_ALLOCATIONS)
0027 #include <iostream>
0028 #include <mutex>
0029 #include <set>
0030 #include <typeindex>
0031 #endif
0032
0033 #if defined(_ACTS_ANY_ENABLE_VERBOSE) || defined(_ACTS_ANY_ENABLE_DEBUG)
0034 #include <iomanip>
0035 #include <iostream>
0036 #endif
0037
0038 #if defined(_ACTS_ANY_ENABLE_DEBUG)
0039 #define _ACTS_ANY_DEBUG(x) std::cout << x << std::endl;
0040 #else
0041 #define _ACTS_ANY_DEBUG(x)
0042 #endif
0043
0044 #if defined(_ACTS_ANY_ENABLE_VERBOSE)
0045 #define _ACTS_ANY_VERBOSE(x) std::cout << x << std::endl;
0046 #define _ACTS_ANY_VERBOSE_BUFFER(s, b) \
0047 do { \
0048 std::cout << "" << s << ": 0x"; \
0049 for (char c : b) { \
0050 std::cout << std::hex << static_cast<int>(c); \
0051 } \
0052 std::cout << std::endl; \
0053 } while (0)
0054 #else
0055 #define _ACTS_ANY_VERBOSE(x)
0056 #define _ACTS_ANY_VERBOSE_BUFFER(s, b)
0057 #endif
0058
0059 namespace Acts {
0060
0061 namespace detail {
0062 #if defined(_ACTS_ANY_ENABLE_TRACK_ALLOCATIONS)
0063 static std::mutex _s_any_mutex;
0064 static std::set<std::pair<std::type_index, void*>> _s_any_allocations;
0065
0066 #define _ACTS_ANY_TRACK_ALLOCATION(T, heap) \
0067 do { \
0068 std::lock_guard guard{detail::_s_any_mutex}; \
0069 detail::_s_any_allocations.emplace(std::type_index(typeid(T)), heap); \
0070 _ACTS_ANY_DEBUG("Allocate type: " << typeid(T).name() << " at " << heap) \
0071 } while (0)
0072
0073 #define _ACTS_ANY_TRACK_DEALLOCATION(T, heap) \
0074 do { \
0075 std::lock_guard guard{detail::_s_any_mutex}; \
0076 auto it = detail::_s_any_allocations.find( \
0077 std::pair{std::type_index(typeid(T)), heap}); \
0078 if (it == detail::_s_any_allocations.end()) { \
0079 throw std::runtime_error{ \
0080 "Trying to deallocate heap address that we didn't allocate"}; \
0081 } \
0082 detail::_s_any_allocations.erase(it); \
0083 } while (0)
0084
0085
0086 static constexpr bool kAnyNoexcept = false;
0087
0088 struct _AnyAllocationReporter {
0089 static void checkAllocations() {
0090 std::lock_guard guard{detail::_s_any_mutex};
0091
0092 if (!detail::_s_any_allocations.empty()) {
0093 std::cout << "Not all allocations have been released" << std::endl;
0094 for (const auto& [idx, addr] : detail::_s_any_allocations) {
0095 std::cout << "- " << idx.name() << ": " << addr << std::endl;
0096 }
0097 throw std::runtime_error{"AnyCheckAllocations failed"};
0098 }
0099 }
0100
0101 ~_AnyAllocationReporter() noexcept { checkAllocations(); }
0102 };
0103 static _AnyAllocationReporter s_reporter;
0104 #else
0105 #define _ACTS_ANY_TRACK_ALLOCATION(T, heap) \
0106 do { \
0107 } while (0)
0108 #define _ACTS_ANY_TRACK_DEALLOCATION(T, heap) \
0109 do { \
0110 } while (0)
0111 static constexpr bool kAnyNoexcept = true;
0112 #endif
0113 }
0114
0115
0116
0117
0118
0119 class AnyBaseAll {};
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 template <std::size_t SbSize, bool Copyable = true, typename Base = void>
0152 class AnyBase : public AnyBaseAll {
0153 static_assert(sizeof(void*) <= SbSize, "Size is too small for a pointer");
0154
0155
0156
0157
0158
0159
0160 template <typename U>
0161 static constexpr bool isStorable() {
0162 if constexpr (std::is_base_of_v<AnyBaseAll, U>) {
0163 return false;
0164 } else if constexpr (!std::is_void_v<Base> &&
0165 !std::is_convertible_v<U*, Base*>) {
0166 return false;
0167 } else if constexpr (Copyable) {
0168 return std::is_copy_assignable_v<U> && std::is_copy_constructible_v<U> &&
0169 (sizeof(U) > SbSize || (std::is_move_assignable_v<U> &&
0170 std::is_move_constructible_v<U>));
0171 } else {
0172 return std::is_move_constructible_v<U> &&
0173 (sizeof(U) > SbSize || std::is_move_assignable_v<U>);
0174 }
0175 }
0176
0177 public:
0178
0179
0180
0181
0182 template <typename T, typename... Args>
0183 requires(isStorable<std::decay_t<T>>())
0184 explicit AnyBase(std::in_place_type_t<T> , Args&&... args) {
0185 using U = std::decay_t<T>;
0186 m_handler = makeHandler<U>();
0187 constructValue<U>(std::forward<Args>(args)...);
0188 }
0189
0190 #if defined(_ACTS_ANY_ENABLE_VERBOSE)
0191 AnyBase() { _ACTS_ANY_VERBOSE("Default construct this=" << this); };
0192 #else
0193
0194
0195
0196 AnyBase() {}
0197 #endif
0198
0199
0200
0201
0202
0203
0204
0205 template <typename T>
0206 explicit AnyBase(T&& value)
0207 requires(!std::is_base_of_v<AnyBaseAll, std::decay_t<T>> &&
0208 isStorable<std::decay_t<T>>())
0209 : AnyBase{std::in_place_type<T>, std::forward<T>(value)} {}
0210
0211
0212
0213
0214
0215
0216 template <typename T, typename... Args>
0217 requires(isStorable<std::decay_t<T>>())
0218 T& emplace(Args&&... args) {
0219 using U = std::decay_t<T>;
0220 destroy();
0221
0222
0223
0224
0225
0226 U* ptr = constructValue<U>(std::forward<Args>(args)...);
0227 m_handler = makeHandler<U>();
0228 return *ptr;
0229 }
0230
0231
0232
0233
0234
0235 template <typename T>
0236 T& as() {
0237 static_assert(std::is_same_v<T, std::decay_t<T>>,
0238 "Please pass the raw type, no const or ref");
0239 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0240 throw std::bad_any_cast{};
0241 }
0242
0243 _ACTS_ANY_VERBOSE("Get as "
0244 << (m_handler->heapAllocated ? "heap" : "local"));
0245
0246 return *std::bit_cast<T*>(dataPtr());
0247 }
0248
0249
0250
0251
0252
0253 template <typename T>
0254 const T& as() const {
0255 static_assert(std::is_same_v<T, std::decay_t<T>>,
0256 "Please pass the raw type, no const or ref");
0257 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0258 throw std::bad_any_cast{};
0259 }
0260
0261 _ACTS_ANY_VERBOSE("Get as "
0262 << (m_handler->heapAllocated ? "heap" : "local"));
0263
0264 return *std::bit_cast<const T*>(dataPtr());
0265 }
0266
0267
0268
0269
0270
0271 template <typename T>
0272 T* asPtr() {
0273 static_assert(std::is_same_v<T, std::decay_t<T>>,
0274 "Please pass the raw type, no const or ref");
0275 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0276 return nullptr;
0277 }
0278 return std::bit_cast<T*>(dataPtr());
0279 }
0280
0281
0282
0283
0284
0285 template <typename T>
0286 const T* asPtr() const {
0287 static_assert(std::is_same_v<T, std::decay_t<T>>,
0288 "Please pass the raw type, no const or ref");
0289 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0290 return nullptr;
0291 }
0292 return std::bit_cast<const T*>(dataPtr());
0293 }
0294
0295
0296
0297
0298
0299 template <typename T>
0300 T take() {
0301 static_assert(std::is_same_v<T, std::decay_t<T>>,
0302 "Please pass the raw type, no const or ref");
0303 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0304 throw std::bad_any_cast{};
0305 }
0306 T* ptr = std::bit_cast<T*>(dataPtr());
0307 T value = std::move(*ptr);
0308 destroy();
0309 return value;
0310 }
0311
0312 ~AnyBase() { destroy(); }
0313
0314
0315
0316
0317
0318 AnyBase(const AnyBase& other)
0319 requires Copyable
0320 {
0321 if (m_handler == nullptr && other.m_handler == nullptr) {
0322
0323 return;
0324 }
0325
0326 _ACTS_ANY_VERBOSE("Copy construct (this="
0327 << this << ") at: " << static_cast<void*>(m_data.data()));
0328
0329 m_handler = other.m_handler;
0330 copyConstruct(other);
0331 }
0332
0333
0334 AnyBase(const AnyBase&)
0335 requires(!Copyable)
0336 = delete;
0337
0338
0339
0340
0341
0342
0343 AnyBase& operator=(const AnyBase& other)
0344 requires Copyable
0345 {
0346 _ACTS_ANY_VERBOSE("Copy assign (this="
0347 << this << ") at: " << static_cast<void*>(m_data.data()));
0348
0349 if (this == &other) {
0350
0351 return *this;
0352 }
0353
0354 if (m_handler == nullptr && other.m_handler == nullptr) {
0355
0356 return *this;
0357 }
0358
0359 if (m_handler == other.m_handler) {
0360
0361 copy(other);
0362 } else {
0363 if (m_handler != nullptr) {
0364
0365 destroy();
0366 }
0367 assert(m_handler == nullptr);
0368 m_handler = other.m_handler;
0369 try {
0370 copyConstruct(other);
0371 } catch (...) {
0372
0373
0374
0375
0376
0377 m_handler = nullptr;
0378 throw;
0379 }
0380 }
0381 return *this;
0382 }
0383
0384
0385 AnyBase& operator=(const AnyBase&)
0386 requires(!Copyable)
0387 = delete;
0388
0389
0390
0391 AnyBase(AnyBase&& other) noexcept(detail::kAnyNoexcept) {
0392 _ACTS_ANY_VERBOSE("Move construct (this="
0393 << this << ") at: " << static_cast<void*>(m_data.data()));
0394 if (m_handler == nullptr && other.m_handler == nullptr) {
0395
0396 return;
0397 }
0398
0399 m_handler = other.m_handler;
0400 moveConstruct(std::move(other));
0401 }
0402
0403
0404
0405
0406 AnyBase& operator=(AnyBase&& other) noexcept(detail::kAnyNoexcept) {
0407 _ACTS_ANY_VERBOSE("Move assign (this="
0408 << this << ") at: " << static_cast<void*>(m_data.data()));
0409 if (this == &other) {
0410
0411 return *this;
0412 }
0413
0414 if (m_handler == nullptr && other.m_handler == nullptr) {
0415
0416 return *this;
0417 }
0418
0419
0420
0421 if (m_handler == other.m_handler &&
0422 m_handler->typeHash == other.m_handler->typeHash) {
0423
0424 move(std::move(other));
0425 } else {
0426 if (m_handler != nullptr) {
0427
0428 destroy();
0429 }
0430 assert(m_handler == nullptr);
0431 m_handler = other.m_handler;
0432 moveConstruct(std::move(other));
0433 }
0434
0435 return *this;
0436 }
0437
0438
0439
0440 explicit operator bool() const { return m_handler != nullptr; }
0441
0442
0443
0444 const std::type_info* typeInfo() const {
0445 return m_handler != nullptr ? m_handler->typeInfo : nullptr;
0446 }
0447
0448
0449
0450
0451 template <typename T>
0452 bool is() const {
0453 static_assert(std::is_same_v<T, std::decay_t<T>>,
0454 "Please pass the raw type, no const or ref");
0455 return m_handler != nullptr && m_handler->typeHash == typeHash<T>();
0456 }
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468 template <typename B = Base>
0469 requires(!std::is_void_v<B>)
0470 B* asBase() {
0471 if (m_handler == nullptr) {
0472 return nullptr;
0473 }
0474 return m_handler->upcast(dataPtr());
0475 }
0476
0477
0478
0479
0480 template <typename B = Base>
0481 requires(!std::is_void_v<B>)
0482 const B* asBase() const {
0483 if (m_handler == nullptr) {
0484 return nullptr;
0485 }
0486 return m_handler->upcastConst(dataPtr());
0487 }
0488
0489
0490
0491
0492 template <typename B = Base>
0493 requires(!std::is_void_v<B>)
0494 B& operator*() {
0495 assert(m_handler != nullptr && "operator* on empty AnyBase");
0496 return *m_handler->upcast(dataPtr());
0497 }
0498
0499
0500
0501
0502 template <typename B = Base>
0503 requires(!std::is_void_v<B>)
0504 const B& operator*() const {
0505 assert(m_handler != nullptr && "operator* on empty AnyBase");
0506 return *m_handler->upcastConst(dataPtr());
0507 }
0508
0509
0510
0511
0512 template <typename B = Base>
0513 requires(!std::is_void_v<B>)
0514 B* operator->() {
0515 assert(m_handler != nullptr && "operator-> on empty AnyBase");
0516 return m_handler->upcast(dataPtr());
0517 }
0518
0519
0520
0521
0522 template <typename B = Base>
0523 requires(!std::is_void_v<B>)
0524 const B* operator->() const {
0525 assert(m_handler != nullptr && "operator-> on empty AnyBase");
0526 return m_handler->upcastConst(dataPtr());
0527 }
0528
0529 private:
0530 void* dataPtr() {
0531 if (m_handler->heapAllocated) {
0532 return *std::bit_cast<void**>(m_data.data());
0533 } else {
0534 return std::bit_cast<void*>(m_data.data());
0535 }
0536 }
0537
0538 void setDataPtr(void* ptr) { *std::bit_cast<void**>(m_data.data()) = ptr; }
0539
0540 const void* dataPtr() const {
0541 if (m_handler->heapAllocated) {
0542 return *std::bit_cast<void* const*>(m_data.data());
0543 } else {
0544 return std::bit_cast<const void*>(m_data.data());
0545 }
0546 }
0547
0548 struct Handler {
0549
0550
0551 Base* (*upcast)(void*) = nullptr;
0552
0553
0554
0555 const Base* (*upcastConst)(const void*) = nullptr;
0556 void (*destroy)(void* ptr) = nullptr;
0557 void (*moveConstruct)(void* from, void* to) = nullptr;
0558 void (*move)(void* from, void* to) = nullptr;
0559 void* (*copyConstruct)(const void* from, void* to) = nullptr;
0560 void (*copy)(const void* from, void* to) = nullptr;
0561 bool heapAllocated{false};
0562 std::uint64_t typeHash{0};
0563 const std::type_info* typeInfo{nullptr};
0564 };
0565
0566 template <typename T>
0567 static const Handler* makeHandler() {
0568 static_assert(!std::is_base_of_v<AnyBaseAll, std::decay_t<T>>,
0569 "Cannot wrap Any in Any");
0570 static const Handler static_handler = []() {
0571 Handler h;
0572 h.heapAllocated = heapAllocated<T>();
0573 if constexpr (!std::is_trivially_destructible_v<T> ||
0574 heapAllocated<T>()) {
0575 h.destroy = &destroyImpl<T>;
0576 }
0577 if constexpr (!heapAllocated<T>() &&
0578 !std::is_trivially_move_constructible_v<T>) {
0579 h.moveConstruct = &moveConstructImpl<T>;
0580 }
0581 if constexpr (!heapAllocated<T>() &&
0582 !std::is_trivially_move_assignable_v<T>) {
0583 h.move = &moveImpl<T>;
0584 }
0585 if constexpr (std::is_copy_constructible_v<T> &&
0586 (!std::is_trivially_copy_constructible_v<T> ||
0587 heapAllocated<T>())) {
0588 h.copyConstruct = ©ConstructImpl<T>;
0589 }
0590
0591 if constexpr (std::is_copy_assignable_v<T> &&
0592 (!std::is_trivially_copy_assignable_v<T> ||
0593 heapAllocated<T>())) {
0594 h.copy = ©Impl<T>;
0595 }
0596
0597 if constexpr (!std::is_void_v<Base>) {
0598 h.upcast = [](void* p) -> Base* {
0599 return static_cast<Base*>(static_cast<T*>(p));
0600 };
0601 h.upcastConst = [](const void* p) -> const Base* {
0602 return static_cast<const Base*>(static_cast<const T*>(p));
0603 };
0604 }
0605
0606 h.typeHash = typeHash<T>();
0607 h.typeInfo = &typeid(T);
0608
0609 _ACTS_ANY_DEBUG("Type: " << typeid(T).name());
0610 _ACTS_ANY_DEBUG(" -> destroy: " << h.destroy);
0611 _ACTS_ANY_DEBUG(" -> moveConstruct: " << h.moveConstruct);
0612 _ACTS_ANY_DEBUG(" -> move: " << h.move);
0613 _ACTS_ANY_DEBUG(" -> copyConstruct: " << h.copyConstruct);
0614 _ACTS_ANY_DEBUG(" -> copy: " << h.copy);
0615 _ACTS_ANY_DEBUG(
0616 " -> heapAllocated: " << (h.heapAllocated ? "yes" : "no"));
0617
0618 return h;
0619 }();
0620 return &static_handler;
0621 }
0622
0623 template <typename T>
0624 static constexpr bool heapAllocated() {
0625 return sizeof(T) > SbSize;
0626 }
0627
0628 template <typename T, typename... Args>
0629 T* constructValue(Args&&... args) {
0630 if constexpr (!heapAllocated<T>()) {
0631
0632 auto* ptr = new (m_data.data()) T(std::forward<Args>(args)...);
0633 _ACTS_ANY_VERBOSE("Construct local (this="
0634 << this
0635 << ") at: " << static_cast<void*>(m_data.data()));
0636 return ptr;
0637 } else {
0638
0639 auto* heap = new T(std::forward<Args>(args)...);
0640 _ACTS_ANY_DEBUG("Allocate type: " << typeid(T).name() << " at " << heap);
0641 _ACTS_ANY_TRACK_ALLOCATION(T, heap);
0642 setDataPtr(heap);
0643 return heap;
0644 }
0645 }
0646
0647 void destroy() {
0648 _ACTS_ANY_VERBOSE("Destructor this=" << this << " handler: " << m_handler);
0649 if (m_handler != nullptr && m_handler->destroy != nullptr) {
0650 _ACTS_ANY_VERBOSE("Non-trivial destruction");
0651 m_handler->destroy(dataPtr());
0652 }
0653 m_handler = nullptr;
0654 }
0655
0656 void moveConstruct(AnyBase&& fromAny) {
0657 if (m_handler == nullptr) {
0658 return;
0659 }
0660
0661 void* to = dataPtr();
0662 void* from = fromAny.dataPtr();
0663 if (m_handler->heapAllocated) {
0664
0665 setDataPtr(fromAny.dataPtr());
0666
0667 fromAny.m_handler = nullptr;
0668 return;
0669 }
0670
0671 if (m_handler->moveConstruct == nullptr) {
0672 _ACTS_ANY_VERBOSE("Trivially move construct");
0673
0674 m_data = std::move(fromAny.m_data);
0675 } else {
0676 m_handler->moveConstruct(from, to);
0677 }
0678 }
0679
0680 void move(AnyBase&& fromAny) {
0681 if (m_handler == nullptr) {
0682 return;
0683 }
0684
0685 void* to = dataPtr();
0686 void* from = fromAny.dataPtr();
0687 if (m_handler->heapAllocated) {
0688
0689
0690 m_handler->destroy(dataPtr());
0691 setDataPtr(fromAny.dataPtr());
0692
0693 fromAny.m_handler = nullptr;
0694 return;
0695 }
0696
0697 if (m_handler->move == nullptr) {
0698 _ACTS_ANY_VERBOSE("Trivially move");
0699
0700 m_data = std::move(fromAny.m_data);
0701 } else {
0702 m_handler->move(from, to);
0703 }
0704 }
0705
0706 void copyConstruct(const AnyBase& fromAny) {
0707 if (m_handler == nullptr) {
0708 return;
0709 }
0710
0711 const void* from = fromAny.dataPtr();
0712
0713 if (m_handler->copyConstruct == nullptr) {
0714 _ACTS_ANY_VERBOSE("Trivially copy construct");
0715
0716 m_data = fromAny.m_data;
0717 } else if (m_handler->heapAllocated) {
0718
0719
0720
0721
0722
0723
0724 void* copyAt = m_handler->copyConstruct(from, nullptr);
0725 assert(copyAt != nullptr);
0726 setDataPtr(copyAt);
0727 } else {
0728
0729 m_handler->copyConstruct(from, dataPtr());
0730 }
0731 }
0732
0733 void copy(const AnyBase& fromAny) {
0734 if (m_handler == nullptr) {
0735 return;
0736 }
0737
0738 void* to = dataPtr();
0739 const void* from = fromAny.dataPtr();
0740
0741 if (m_handler->copy == nullptr) {
0742 _ACTS_ANY_VERBOSE("Trivially copy");
0743
0744 m_data = fromAny.m_data;
0745 } else {
0746 m_handler->copy(from, to);
0747 }
0748 }
0749
0750 template <typename T>
0751 static void destroyImpl(void* ptr) {
0752 assert(ptr != nullptr && "Address to destroy is nullptr");
0753 auto* obj = static_cast<T*>(ptr);
0754 if constexpr (!heapAllocated<T>()) {
0755
0756 _ACTS_ANY_VERBOSE("Destroy local at: " << ptr);
0757 obj->~T();
0758 } else {
0759
0760 _ACTS_ANY_DEBUG("Delete type: " << typeid(T).name()
0761 << " heap at: " << obj);
0762 _ACTS_ANY_TRACK_DEALLOCATION(T, obj);
0763 delete obj;
0764 }
0765 }
0766
0767 template <typename T>
0768 static void moveConstructImpl(void* from, void* to) {
0769 _ACTS_ANY_VERBOSE("move const: " << from << " -> " << to);
0770 assert(from != nullptr && "Source is null");
0771 assert(to != nullptr && "Target is null");
0772 auto* _from = static_cast<T*>(from);
0773 new (to) T(std::move(*_from));
0774 }
0775
0776 template <typename T>
0777 static void moveImpl(void* from, void* to) {
0778 _ACTS_ANY_VERBOSE("move: " << from << " -> " << to);
0779 assert(from != nullptr && "Source is null");
0780 assert(to != nullptr && "Target is null");
0781
0782 auto* _from = static_cast<T*>(from);
0783 auto* _to = static_cast<T*>(to);
0784
0785 (*_to) = std::move(*_from);
0786 }
0787
0788 template <typename T>
0789 static void* copyConstructImpl(const void* from, void* to) {
0790 _ACTS_ANY_VERBOSE("copy const: " << from << " -> " << to);
0791 assert(from != nullptr && "Source is null");
0792 const auto* _from = static_cast<const T*>(from);
0793 if (to == nullptr) {
0794 assert(heapAllocated<T>() && "Received nullptr in local buffer case");
0795 to = new T(*_from);
0796 _ACTS_ANY_TRACK_ALLOCATION(T, to);
0797
0798 } else {
0799 assert(!heapAllocated<T>() && "Received non-nullptr in heap case");
0800 new (to) T(*_from);
0801 }
0802 return to;
0803 }
0804
0805 template <typename T>
0806 static void copyImpl(const void* from, void* to) {
0807 _ACTS_ANY_VERBOSE("copy: " << from << " -> " << to);
0808 assert(from != nullptr && "Source is null");
0809 assert(to != nullptr && "Target is null");
0810
0811 const auto* _from = static_cast<const T*>(from);
0812 auto* _to = static_cast<T*>(to);
0813
0814 (*_to) = *_from;
0815 }
0816
0817 static constexpr std::size_t kMaxAlignment =
0818 std::max(alignof(std::max_align_t),
0819 #if defined(__AVX512F__)
0820 std::size_t{64}
0821 #elif defined(__AVX__)
0822 std::size_t{32}
0823 #elif defined(__SSE__)
0824 std::size_t{16}
0825 #else
0826 std::size_t{0}
0827
0828
0829 #endif
0830 );
0831
0832
0833
0834
0835
0836 alignas(kMaxAlignment) std::array<std::byte, SbSize> m_data;
0837 const Handler* m_handler{nullptr};
0838 };
0839
0840
0841
0842
0843
0844 using Any = AnyBase<sizeof(void*), true>;
0845
0846
0847
0848
0849 using AnyMoveOnly = AnyBase<sizeof(void*), false>;
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861 template <typename Base, std::size_t SbSize = sizeof(void*)>
0862 using AnyOf = AnyBase<SbSize, true, Base>;
0863
0864
0865
0866 #undef _ACTS_ANY_VERBOSE
0867 #undef _ACTS_ANY_VERBOSE_BUFFER
0868 #undef _ACTS_ANY_ENABLE_VERBOSE
0869
0870 }