File indexing completed on 2026-06-11 07:49:14
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 AnyBase() = default;
0194 #endif
0195
0196
0197
0198
0199
0200
0201
0202 template <typename T>
0203 explicit AnyBase(T&& value)
0204 requires(!std::is_base_of_v<AnyBaseAll, std::decay_t<T>> &&
0205 isStorable<std::decay_t<T>>())
0206 : AnyBase{std::in_place_type<T>, std::forward<T>(value)} {}
0207
0208
0209
0210
0211
0212
0213 template <typename T, typename... Args>
0214 requires(isStorable<std::decay_t<T>>())
0215 T& emplace(Args&&... args) {
0216 using U = std::decay_t<T>;
0217 destroy();
0218
0219
0220
0221
0222
0223 U* ptr = constructValue<U>(std::forward<Args>(args)...);
0224 m_handler = makeHandler<U>();
0225 return *ptr;
0226 }
0227
0228
0229
0230
0231
0232 template <typename T>
0233 T& as() {
0234 static_assert(std::is_same_v<T, std::decay_t<T>>,
0235 "Please pass the raw type, no const or ref");
0236 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0237 throw std::bad_any_cast{};
0238 }
0239
0240 _ACTS_ANY_VERBOSE("Get as "
0241 << (m_handler->heapAllocated ? "heap" : "local"));
0242
0243 return *std::bit_cast<T*>(dataPtr());
0244 }
0245
0246
0247
0248
0249
0250 template <typename T>
0251 const T& as() const {
0252 static_assert(std::is_same_v<T, std::decay_t<T>>,
0253 "Please pass the raw type, no const or ref");
0254 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0255 throw std::bad_any_cast{};
0256 }
0257
0258 _ACTS_ANY_VERBOSE("Get as "
0259 << (m_handler->heapAllocated ? "heap" : "local"));
0260
0261 return *std::bit_cast<const T*>(dataPtr());
0262 }
0263
0264
0265
0266
0267
0268 template <typename T>
0269 T* asPtr() {
0270 static_assert(std::is_same_v<T, std::decay_t<T>>,
0271 "Please pass the raw type, no const or ref");
0272 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0273 return nullptr;
0274 }
0275 return std::bit_cast<T*>(dataPtr());
0276 }
0277
0278
0279
0280
0281
0282 template <typename T>
0283 const T* asPtr() const {
0284 static_assert(std::is_same_v<T, std::decay_t<T>>,
0285 "Please pass the raw type, no const or ref");
0286 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0287 return nullptr;
0288 }
0289 return std::bit_cast<const T*>(dataPtr());
0290 }
0291
0292
0293
0294
0295
0296 template <typename T>
0297 T take() {
0298 static_assert(std::is_same_v<T, std::decay_t<T>>,
0299 "Please pass the raw type, no const or ref");
0300 if (m_handler == nullptr || m_handler->typeHash != typeHash<T>()) {
0301 throw std::bad_any_cast{};
0302 }
0303 T* ptr = std::bit_cast<T*>(dataPtr());
0304 T value = std::move(*ptr);
0305 destroy();
0306 return value;
0307 }
0308
0309 ~AnyBase() { destroy(); }
0310
0311
0312
0313
0314
0315 AnyBase(const AnyBase& other)
0316 requires Copyable
0317 {
0318 if (m_handler == nullptr && other.m_handler == nullptr) {
0319
0320 return;
0321 }
0322
0323 _ACTS_ANY_VERBOSE("Copy construct (this="
0324 << this << ") at: " << static_cast<void*>(m_data.data()));
0325
0326 m_handler = other.m_handler;
0327 copyConstruct(other);
0328 }
0329
0330
0331 AnyBase(const AnyBase&)
0332 requires(!Copyable)
0333 = delete;
0334
0335
0336
0337
0338
0339
0340 AnyBase& operator=(const AnyBase& other)
0341 requires Copyable
0342 {
0343 _ACTS_ANY_VERBOSE("Copy assign (this="
0344 << this << ") at: " << static_cast<void*>(m_data.data()));
0345
0346 if (this == &other) {
0347
0348 return *this;
0349 }
0350
0351 if (m_handler == nullptr && other.m_handler == nullptr) {
0352
0353 return *this;
0354 }
0355
0356 if (m_handler == other.m_handler) {
0357
0358 copy(other);
0359 } else {
0360 if (m_handler != nullptr) {
0361
0362 destroy();
0363 }
0364 assert(m_handler == nullptr);
0365 m_handler = other.m_handler;
0366 try {
0367 copyConstruct(other);
0368 } catch (...) {
0369
0370
0371
0372
0373
0374 m_handler = nullptr;
0375 throw;
0376 }
0377 }
0378 return *this;
0379 }
0380
0381
0382 AnyBase& operator=(const AnyBase&)
0383 requires(!Copyable)
0384 = delete;
0385
0386
0387
0388 AnyBase(AnyBase&& other) noexcept(detail::kAnyNoexcept) {
0389 _ACTS_ANY_VERBOSE("Move construct (this="
0390 << this << ") at: " << static_cast<void*>(m_data.data()));
0391 if (m_handler == nullptr && other.m_handler == nullptr) {
0392
0393 return;
0394 }
0395
0396 m_handler = other.m_handler;
0397 moveConstruct(std::move(other));
0398 }
0399
0400
0401
0402
0403 AnyBase& operator=(AnyBase&& other) noexcept(detail::kAnyNoexcept) {
0404 _ACTS_ANY_VERBOSE("Move assign (this="
0405 << this << ") at: " << static_cast<void*>(m_data.data()));
0406 if (this == &other) {
0407
0408 return *this;
0409 }
0410
0411 if (m_handler == nullptr && other.m_handler == nullptr) {
0412
0413 return *this;
0414 }
0415
0416
0417
0418 if (m_handler == other.m_handler &&
0419 m_handler->typeHash == other.m_handler->typeHash) {
0420
0421 move(std::move(other));
0422 } else {
0423 if (m_handler != nullptr) {
0424
0425 destroy();
0426 }
0427 assert(m_handler == nullptr);
0428 m_handler = other.m_handler;
0429 moveConstruct(std::move(other));
0430 }
0431
0432 return *this;
0433 }
0434
0435
0436
0437 explicit operator bool() const { return m_handler != nullptr; }
0438
0439
0440
0441 const std::type_info* typeInfo() const {
0442 return m_handler != nullptr ? m_handler->typeInfo : nullptr;
0443 }
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455 template <typename B = Base>
0456 requires(!std::is_void_v<B>)
0457 B* asBase() {
0458 if (m_handler == nullptr) {
0459 return nullptr;
0460 }
0461 return m_handler->upcast(dataPtr());
0462 }
0463
0464
0465
0466
0467 template <typename B = Base>
0468 requires(!std::is_void_v<B>)
0469 const B* asBase() const {
0470 if (m_handler == nullptr) {
0471 return nullptr;
0472 }
0473 return m_handler->upcastConst(dataPtr());
0474 }
0475
0476
0477
0478
0479 template <typename B = Base>
0480 requires(!std::is_void_v<B>)
0481 B& operator*() {
0482 assert(m_handler != nullptr && "operator* on empty AnyBase");
0483 return *m_handler->upcast(dataPtr());
0484 }
0485
0486
0487
0488
0489 template <typename B = Base>
0490 requires(!std::is_void_v<B>)
0491 const B& operator*() const {
0492 assert(m_handler != nullptr && "operator* on empty AnyBase");
0493 return *m_handler->upcastConst(dataPtr());
0494 }
0495
0496
0497
0498
0499 template <typename B = Base>
0500 requires(!std::is_void_v<B>)
0501 B* operator->() {
0502 assert(m_handler != nullptr && "operator-> on empty AnyBase");
0503 return m_handler->upcast(dataPtr());
0504 }
0505
0506
0507
0508
0509 template <typename B = Base>
0510 requires(!std::is_void_v<B>)
0511 const B* operator->() const {
0512 assert(m_handler != nullptr && "operator-> on empty AnyBase");
0513 return m_handler->upcastConst(dataPtr());
0514 }
0515
0516 private:
0517 void* dataPtr() {
0518 if (m_handler->heapAllocated) {
0519 return *std::bit_cast<void**>(m_data.data());
0520 } else {
0521 return std::bit_cast<void*>(m_data.data());
0522 }
0523 }
0524
0525 void setDataPtr(void* ptr) { *std::bit_cast<void**>(m_data.data()) = ptr; }
0526
0527 const void* dataPtr() const {
0528 if (m_handler->heapAllocated) {
0529 return *std::bit_cast<void* const*>(m_data.data());
0530 } else {
0531 return std::bit_cast<const void*>(m_data.data());
0532 }
0533 }
0534
0535 struct Handler {
0536
0537
0538 Base* (*upcast)(void*) = nullptr;
0539
0540
0541
0542 const Base* (*upcastConst)(const void*) = nullptr;
0543 void (*destroy)(void* ptr) = nullptr;
0544 void (*moveConstruct)(void* from, void* to) = nullptr;
0545 void (*move)(void* from, void* to) = nullptr;
0546 void* (*copyConstruct)(const void* from, void* to) = nullptr;
0547 void (*copy)(const void* from, void* to) = nullptr;
0548 bool heapAllocated{false};
0549 std::uint64_t typeHash{0};
0550 const std::type_info* typeInfo{nullptr};
0551 };
0552
0553 template <typename T>
0554 static const Handler* makeHandler() {
0555 static_assert(!std::is_base_of_v<AnyBaseAll, std::decay_t<T>>,
0556 "Cannot wrap Any in Any");
0557 static const Handler static_handler = []() {
0558 Handler h;
0559 h.heapAllocated = heapAllocated<T>();
0560 if constexpr (!std::is_trivially_destructible_v<T> ||
0561 heapAllocated<T>()) {
0562 h.destroy = &destroyImpl<T>;
0563 }
0564 if constexpr (!heapAllocated<T>() &&
0565 !std::is_trivially_move_constructible_v<T>) {
0566 h.moveConstruct = &moveConstructImpl<T>;
0567 }
0568 if constexpr (!heapAllocated<T>() &&
0569 !std::is_trivially_move_assignable_v<T>) {
0570 h.move = &moveImpl<T>;
0571 }
0572 if constexpr (std::is_copy_constructible_v<T> &&
0573 (!std::is_trivially_copy_constructible_v<T> ||
0574 heapAllocated<T>())) {
0575 h.copyConstruct = ©ConstructImpl<T>;
0576 }
0577
0578 if constexpr (std::is_copy_assignable_v<T> &&
0579 (!std::is_trivially_copy_assignable_v<T> ||
0580 heapAllocated<T>())) {
0581 h.copy = ©Impl<T>;
0582 }
0583
0584 if constexpr (!std::is_void_v<Base>) {
0585 h.upcast = [](void* p) -> Base* {
0586 return static_cast<Base*>(static_cast<T*>(p));
0587 };
0588 h.upcastConst = [](const void* p) -> const Base* {
0589 return static_cast<const Base*>(static_cast<const T*>(p));
0590 };
0591 }
0592
0593 h.typeHash = typeHash<T>();
0594 h.typeInfo = &typeid(T);
0595
0596 _ACTS_ANY_DEBUG("Type: " << typeid(T).name());
0597 _ACTS_ANY_DEBUG(" -> destroy: " << h.destroy);
0598 _ACTS_ANY_DEBUG(" -> moveConstruct: " << h.moveConstruct);
0599 _ACTS_ANY_DEBUG(" -> move: " << h.move);
0600 _ACTS_ANY_DEBUG(" -> copyConstruct: " << h.copyConstruct);
0601 _ACTS_ANY_DEBUG(" -> copy: " << h.copy);
0602 _ACTS_ANY_DEBUG(
0603 " -> heapAllocated: " << (h.heapAllocated ? "yes" : "no"));
0604
0605 return h;
0606 }();
0607 return &static_handler;
0608 }
0609
0610 template <typename T>
0611 static constexpr bool heapAllocated() {
0612 return sizeof(T) > SbSize;
0613 }
0614
0615 template <typename T, typename... Args>
0616 T* constructValue(Args&&... args) {
0617 if constexpr (!heapAllocated<T>()) {
0618
0619 auto* ptr = new (m_data.data()) T(std::forward<Args>(args)...);
0620 _ACTS_ANY_VERBOSE("Construct local (this="
0621 << this
0622 << ") at: " << static_cast<void*>(m_data.data()));
0623 return ptr;
0624 } else {
0625
0626 auto* heap = new T(std::forward<Args>(args)...);
0627 _ACTS_ANY_DEBUG("Allocate type: " << typeid(T).name() << " at " << heap);
0628 _ACTS_ANY_TRACK_ALLOCATION(T, heap);
0629 setDataPtr(heap);
0630 return heap;
0631 }
0632 }
0633
0634 void destroy() {
0635 _ACTS_ANY_VERBOSE("Destructor this=" << this << " handler: " << m_handler);
0636 if (m_handler != nullptr && m_handler->destroy != nullptr) {
0637 _ACTS_ANY_VERBOSE("Non-trivial destruction");
0638 m_handler->destroy(dataPtr());
0639 }
0640 m_handler = nullptr;
0641 }
0642
0643 void moveConstruct(AnyBase&& fromAny) {
0644 if (m_handler == nullptr) {
0645 return;
0646 }
0647
0648 void* to = dataPtr();
0649 void* from = fromAny.dataPtr();
0650 if (m_handler->heapAllocated) {
0651
0652 setDataPtr(fromAny.dataPtr());
0653
0654 fromAny.m_handler = nullptr;
0655 return;
0656 }
0657
0658 if (m_handler->moveConstruct == nullptr) {
0659 _ACTS_ANY_VERBOSE("Trivially move construct");
0660
0661 m_data = std::move(fromAny.m_data);
0662 } else {
0663 m_handler->moveConstruct(from, to);
0664 }
0665 }
0666
0667 void move(AnyBase&& fromAny) {
0668 if (m_handler == nullptr) {
0669 return;
0670 }
0671
0672 void* to = dataPtr();
0673 void* from = fromAny.dataPtr();
0674 if (m_handler->heapAllocated) {
0675
0676
0677 m_handler->destroy(dataPtr());
0678 setDataPtr(fromAny.dataPtr());
0679
0680 fromAny.m_handler = nullptr;
0681 return;
0682 }
0683
0684 if (m_handler->move == nullptr) {
0685 _ACTS_ANY_VERBOSE("Trivially move");
0686
0687 m_data = std::move(fromAny.m_data);
0688 } else {
0689 m_handler->move(from, to);
0690 }
0691 }
0692
0693 void copyConstruct(const AnyBase& fromAny) {
0694 if (m_handler == nullptr) {
0695 return;
0696 }
0697
0698 const void* from = fromAny.dataPtr();
0699
0700 if (m_handler->copyConstruct == nullptr) {
0701 _ACTS_ANY_VERBOSE("Trivially copy construct");
0702
0703 m_data = fromAny.m_data;
0704 } else if (m_handler->heapAllocated) {
0705
0706
0707
0708
0709
0710
0711 void* copyAt = m_handler->copyConstruct(from, nullptr);
0712 assert(copyAt != nullptr);
0713 setDataPtr(copyAt);
0714 } else {
0715
0716 m_handler->copyConstruct(from, dataPtr());
0717 }
0718 }
0719
0720 void copy(const AnyBase& fromAny) {
0721 if (m_handler == nullptr) {
0722 return;
0723 }
0724
0725 void* to = dataPtr();
0726 const void* from = fromAny.dataPtr();
0727
0728 if (m_handler->copy == nullptr) {
0729 _ACTS_ANY_VERBOSE("Trivially copy");
0730
0731 m_data = fromAny.m_data;
0732 } else {
0733 m_handler->copy(from, to);
0734 }
0735 }
0736
0737 template <typename T>
0738 static void destroyImpl(void* ptr) {
0739 assert(ptr != nullptr && "Address to destroy is nullptr");
0740 auto* obj = static_cast<T*>(ptr);
0741 if constexpr (!heapAllocated<T>()) {
0742
0743 _ACTS_ANY_VERBOSE("Destroy local at: " << ptr);
0744 obj->~T();
0745 } else {
0746
0747 _ACTS_ANY_DEBUG("Delete type: " << typeid(T).name()
0748 << " heap at: " << obj);
0749 _ACTS_ANY_TRACK_DEALLOCATION(T, obj);
0750 delete obj;
0751 }
0752 }
0753
0754 template <typename T>
0755 static void moveConstructImpl(void* from, void* to) {
0756 _ACTS_ANY_VERBOSE("move const: " << from << " -> " << to);
0757 assert(from != nullptr && "Source is null");
0758 assert(to != nullptr && "Target is null");
0759 auto* _from = static_cast<T*>(from);
0760 new (to) T(std::move(*_from));
0761 }
0762
0763 template <typename T>
0764 static void moveImpl(void* from, void* to) {
0765 _ACTS_ANY_VERBOSE("move: " << from << " -> " << to);
0766 assert(from != nullptr && "Source is null");
0767 assert(to != nullptr && "Target is null");
0768
0769 auto* _from = static_cast<T*>(from);
0770 auto* _to = static_cast<T*>(to);
0771
0772 (*_to) = std::move(*_from);
0773 }
0774
0775 template <typename T>
0776 static void* copyConstructImpl(const void* from, void* to) {
0777 _ACTS_ANY_VERBOSE("copy const: " << from << " -> " << to);
0778 assert(from != nullptr && "Source is null");
0779 const auto* _from = static_cast<const T*>(from);
0780 if (to == nullptr) {
0781 assert(heapAllocated<T>() && "Received nullptr in local buffer case");
0782 to = new T(*_from);
0783 _ACTS_ANY_TRACK_ALLOCATION(T, to);
0784
0785 } else {
0786 assert(!heapAllocated<T>() && "Received non-nullptr in heap case");
0787 new (to) T(*_from);
0788 }
0789 return to;
0790 }
0791
0792 template <typename T>
0793 static void copyImpl(const void* from, void* to) {
0794 _ACTS_ANY_VERBOSE("copy: " << from << " -> " << to);
0795 assert(from != nullptr && "Source is null");
0796 assert(to != nullptr && "Target is null");
0797
0798 const auto* _from = static_cast<const T*>(from);
0799 auto* _to = static_cast<T*>(to);
0800
0801 (*_to) = *_from;
0802 }
0803
0804 static constexpr std::size_t kMaxAlignment =
0805 std::max(alignof(std::max_align_t),
0806 #if defined(__AVX512F__)
0807 std::size_t{64}
0808 #elif defined(__AVX__)
0809 std::size_t{32}
0810 #elif defined(__SSE__)
0811 std::size_t{16}
0812 #else
0813 std::size_t{0}
0814
0815
0816 #endif
0817 );
0818
0819 alignas(kMaxAlignment) std::array<std::byte, SbSize> m_data{};
0820 const Handler* m_handler{nullptr};
0821 };
0822
0823
0824
0825
0826
0827 using Any = AnyBase<sizeof(void*), true>;
0828
0829
0830
0831
0832 using AnyMoveOnly = AnyBase<sizeof(void*), false>;
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844 template <typename Base, std::size_t SbSize = sizeof(void*)>
0845 using AnyOf = AnyBase<SbSize, true, Base>;
0846
0847
0848
0849 #undef _ACTS_ANY_VERBOSE
0850 #undef _ACTS_ANY_VERBOSE_BUFFER
0851 #undef _ACTS_ANY_ENABLE_VERBOSE
0852
0853 }