32#ifndef CPPINTEROP_BOX_H
33#define CPPINTEROP_BOX_H
49#ifndef CPPINTEROP_ALWAYS_INLINE
51#define CPPINTEROP_ALWAYS_INLINE __forceinline
52#elif defined(__GNUC__) || defined(__clang__)
53#define CPPINTEROP_ALWAYS_INLINE __attribute__((always_inline)) inline
55#define CPPINTEROP_ALWAYS_INLINE inline
60#ifndef CPPINTEROP_UNREACHABLE
62#define CPPINTEROP_UNREACHABLE() __assume(0)
63#elif defined(__GNUC__) || defined(__clang__)
64#define CPPINTEROP_UNREACHABLE() __builtin_unreachable()
66#define CPPINTEROP_UNREACHABLE() ((void)0)
79#define CPP_BOX_BUILTIN_TYPES \
82 X(signed char, SChar) \
83 X(unsigned char, UChar) \
85 X(unsigned short, UShort) \
87 X(unsigned int, UInt) \
89 X(unsigned long, ULong) \
90 X(long long, LongLong) \
91 X(unsigned long long, ULongLong) \
94 X(long double, LongDouble)
100#define X(type, name) K_##name,
129#define X(type, name) type m_##name;
139 void* m_Type =
nullptr;
140 Storage m_storage = {};
142 template <
class T>
static constexpr Kind KindOf() noexcept;
143 template <class T> static T& slot(Storage& s) noexcept;
144 template <class T> static const T& slot(const Storage& s) noexcept;
150 : m_kind(o.m_kind), m_Type(o.m_Type), m_storage(o.m_storage) {
153 if (m_kind ==
K_PtrOrObj && m_storage.m_Object.m_Ops)
154 m_storage.m_Object.m_Ops->retain(m_storage.m_Object.m_Ptr);
161 m_storage = o.m_storage;
162 if (m_kind ==
K_PtrOrObj && m_storage.m_Object.m_Ops)
163 m_storage.m_Object.m_Ops->retain(m_storage.m_Object.m_Ptr);
168 : m_kind(o.m_kind), m_Type(o.m_Type), m_storage(o.m_storage) {
177 m_storage = o.m_storage;
185 if (m_kind ==
K_PtrOrObj && m_storage.m_Object.m_Ops)
186 m_storage.m_Object.m_Ops->release(m_storage.m_Object.m_Ptr);
190 void*
getType() const noexcept {
return m_Type; }
198 template <
class T> T
unbox() const noexcept {
200 assert(m_kind == KindOf<T>() &&
201 "Cpp::Box::unbox<T>(): T does not match the runtime Kind");
203 return slot<T>(m_storage);
213 void* type =
nullptr) noexcept {
215 v.m_kind = KindOf<T>();
217 slot<T>(v.m_storage) = x;
229 v.m_storage.m_Object.m_Ptr = obj;
230 v.m_storage.m_Object.m_Ops = ops;
239 return m_kind ==
K_PtrOrObj ? m_storage.m_Object.m_Ptr :
nullptr;
248 return visit([](
auto x) -> T {
return static_cast<T
>(x); });
259#define X(type, name) \
261 return vis(unbox<type>());
276#define X(type, name) \
277 template <> constexpr Box::Kind Box::KindOf<type>() noexcept { \
280 template <> inline type& Box::slot<type>(Storage & s) noexcept { \
283 template <> inline const type& Box::slot<type>(const Storage& s) noexcept { \
#define CPPINTEROP_UNREACHABLE()
#define CPPINTEROP_ALWAYS_INLINE
#define CPP_BOX_BUILTIN_TYPES
void * getObjectPtr() const noexcept
Object payload accessor; only valid for K_PtrOrObj.
auto visit(V &&vis) const -> decltype(vis(int{}))
Runtime-typed dispatch via visitor.
Box & operator=(Box &&o) noexcept
T unbox() const noexcept
AOT-typed extraction.
T convertTo() const noexcept
Runtime convert across Kinds: dispatches on the actual Kind and returns the value reinterpreted (via ...
void * getType() const noexcept
static Box Create(T x, void *type=nullptr) noexcept
AOT-typed construction for fundamentals.
Kind getKind() const noexcept
Box & operator=(const Box &o) noexcept
static Box AdoptObject(void *obj, const ObjectOps *ops, void *type) noexcept
Object-payload construction.
Operations vtable for a K_PtrOrObj payload.
void(* release)(void *) noexcept
Decrement the payload's refcount; on the last drop, run the payload's destructor and free storage.
void(* retain)(void *) noexcept
Increment the payload's refcount.