18 template<
size_t ID,
typename T>
19 void* ptr_tag(T* ptr)
noexcept
20 requires(
alignof(T) > ID)
22 assert((
reinterpret_cast<uintptr_t
>(ptr) & (
alignof(T) - 1)) == 0);
24 return reinterpret_cast<void*
>(
reinterpret_cast<uintptr_t
>(ptr) | ID);
34 template<auto ID,
typename T>
35 void* ptr_tag(T* ptr)
noexcept
36 requires(std::is_enum_v<
decltype(ID)>)
38 return ptr_tag<static_cast<size_t>(ID), T>(ptr);
48 template<
size_t ID,
typename T>
49 const void* ptr_tag(
const T* ptr)
noexcept
50 requires(
alignof(T) > ID)
52 assert((
reinterpret_cast<uintptr_t
>(ptr) & (
alignof(T) - 1)) == 0);
54 return reinterpret_cast<const void*
>(
reinterpret_cast<uintptr_t
>(ptr) | ID);
64 template<auto ID,
typename T>
65 const void* ptr_tag(
const T* ptr)
noexcept
66 requires(std::is_enum_v<
decltype(ID)>)
68 return ptr_tag<static_cast<size_t>(ID), T>(ptr);
78 std::pair<T*, size_t> ptr_untag(
void* ptr)
noexcept {
79 const auto align_mask =
static_cast<uintptr_t
>(
alignof(T) - 1);
80 auto uptr =
reinterpret_cast<uintptr_t
>(ptr);
81 return {
reinterpret_cast<T*
>(uptr & ~align_mask), uptr & align_mask};
91 template<
typename T,
typename TTag>
92 std::pair<T*, TTag> ptr_untag(
void* vptr)
noexcept {
93 auto [ptr, tag] = ptr_untag<T>(vptr);
94 return {ptr,
static_cast<TTag
>(tag)};
104 std::pair<const T*, size_t> ptr_untag(
const void* vptr)
noexcept {
105 const auto align_mask =
static_cast<uintptr_t
>(
alignof(T) - 1);
106 auto uptr =
reinterpret_cast<uintptr_t
>(vptr);
107 return {
reinterpret_cast<const T*
>(uptr & ~align_mask), uptr & align_mask};
117 template<
typename T,
typename TTag>
118 std::pair<const T*, TTag> ptr_untag(
const void* vptr)
noexcept {
119 auto [ptr, tag] = ptr_untag<T>(vptr);
120 return {ptr,
static_cast<TTag
>(tag)};
127 template<
typename T1,
typename... TExtra>
128 constexpr size_t min_alignof() noexcept {
129 if constexpr (
sizeof...(TExtra) > 0)
130 return (std::min)(
alignof(T1), min_alignof<TExtra...>());
141 template<
typename... T>
142 size_t ptr_get_tag(
const void* vptr)
noexcept {
143 constexpr auto align_mask =
static_cast<uintptr_t
>(min_alignof<T...>() - 1);
144 return reinterpret_cast<uintptr_t
>(vptr) & align_mask;