mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
constexpr: resign ourselves to gcc dropping void -> T support
This commit is contained in:
parent
96d3187f3e
commit
ad4c794aea
16 changed files with 201 additions and 290 deletions
|
@ -52,9 +52,9 @@ namespace ams::ddsf {
|
|||
util::TypedStorage<DeviceCodeEntry> m_entry_storage;
|
||||
bool m_is_constructed;
|
||||
public:
|
||||
using ListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&DeviceCodeEntryHolder::m_list_node>;
|
||||
using ListTraits = util::IntrusiveListMemberTraits<&DeviceCodeEntryHolder::m_list_node>;
|
||||
using List = typename ListTraits::ListType;
|
||||
friend class util::IntrusiveList<DeviceCodeEntryHolder, util::IntrusiveListMemberTraitsDeferredAssert<&DeviceCodeEntryHolder::m_list_node>>;
|
||||
friend class util::IntrusiveList<DeviceCodeEntryHolder, util::IntrusiveListMemberTraits<&DeviceCodeEntryHolder::m_list_node>>;
|
||||
public:
|
||||
DeviceCodeEntryHolder() : m_list_node(), m_entry_storage(), m_is_constructed(false) {
|
||||
/* ... */
|
||||
|
@ -105,6 +105,5 @@ namespace ams::ddsf {
|
|||
return GetReference(m_entry_storage);
|
||||
}
|
||||
};
|
||||
static_assert(DeviceCodeEntryHolder::ListTraits::IsValid());
|
||||
|
||||
}
|
||||
|
|
|
@ -38,9 +38,9 @@ namespace ams::ddsf {
|
|||
mutable os::SdkMutex m_session_list_lock;
|
||||
bool m_is_exclusive_write;
|
||||
public:
|
||||
using ListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&IDevice::m_list_node>;
|
||||
using ListTraits = util::IntrusiveListMemberTraits<&IDevice::m_list_node>;
|
||||
using List = typename ListTraits::ListType;
|
||||
friend class util::IntrusiveList<IDevice, util::IntrusiveListMemberTraitsDeferredAssert<&IDevice::m_list_node>>;
|
||||
friend class util::IntrusiveList<IDevice, util::IntrusiveListMemberTraits<&IDevice::m_list_node>>;
|
||||
private:
|
||||
Result AttachSession(ISession *session) {
|
||||
AMS_ASSERT(session != nullptr);
|
||||
|
@ -135,6 +135,5 @@ namespace ams::ddsf {
|
|||
return !m_session_list.empty();
|
||||
}
|
||||
};
|
||||
static_assert(IDevice::ListTraits::IsValid());
|
||||
|
||||
}
|
||||
|
|
|
@ -31,9 +31,9 @@ namespace ams::ddsf {
|
|||
IDevice::List m_device_list;
|
||||
mutable os::SdkMutex m_device_list_lock;
|
||||
public:
|
||||
using ListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&IDriver::m_list_node>;
|
||||
using ListTraits = util::IntrusiveListMemberTraits<&IDriver::m_list_node>;
|
||||
using List = typename ListTraits::ListType;
|
||||
friend class util::IntrusiveList<IDriver, util::IntrusiveListMemberTraitsDeferredAssert<&IDriver::m_list_node>>;
|
||||
friend class util::IntrusiveList<IDriver, util::IntrusiveListMemberTraits<&IDriver::m_list_node>>;
|
||||
private:
|
||||
public:
|
||||
IDriver() : m_list_node(), m_device_list(), m_device_list_lock() {
|
||||
|
@ -94,6 +94,5 @@ namespace ams::ddsf {
|
|||
return impl::ForEach(m_device_list_lock, m_device_list, f);
|
||||
}
|
||||
};
|
||||
static_assert(IDriver::ListTraits::IsValid());
|
||||
|
||||
}
|
||||
|
|
|
@ -37,9 +37,9 @@ namespace ams::ddsf {
|
|||
IDevice *m_device;
|
||||
AccessMode m_access_mode;
|
||||
public:
|
||||
using ListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&ISession::m_list_node>;
|
||||
using ListTraits = util::IntrusiveListMemberTraits<&ISession::m_list_node>;
|
||||
using List = typename ListTraits::ListType;
|
||||
friend class util::IntrusiveList<ISession, util::IntrusiveListMemberTraitsDeferredAssert<&ISession::m_list_node>>;
|
||||
friend class util::IntrusiveList<ISession, util::IntrusiveListMemberTraits<&ISession::m_list_node>>;
|
||||
private:
|
||||
void AttachDevice(IDevice *dev, AccessMode mode) {
|
||||
AMS_ASSERT(dev != nullptr);
|
||||
|
@ -95,6 +95,5 @@ namespace ams::ddsf {
|
|||
return this->CheckAccess(AccessMode_Write) && !this->CheckAccess(AccessMode_Shared);
|
||||
}
|
||||
};
|
||||
static_assert(ISession::ListTraits::IsValid());
|
||||
|
||||
}
|
||||
|
|
|
@ -29,9 +29,9 @@ namespace ams::i2c::driver {
|
|||
AddressingMode m_addressing_mode;
|
||||
util::IntrusiveListNode m_device_property_list_node;
|
||||
public:
|
||||
using DevicePropertyListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&I2cDeviceProperty::m_device_property_list_node>;
|
||||
using DevicePropertyListTraits = util::IntrusiveListMemberTraits<&I2cDeviceProperty::m_device_property_list_node>;
|
||||
using DevicePropertyList = typename DevicePropertyListTraits::ListType;
|
||||
friend class util::IntrusiveList<I2cDeviceProperty, util::IntrusiveListMemberTraitsDeferredAssert<&I2cDeviceProperty::m_device_property_list_node>>;
|
||||
friend class util::IntrusiveList<I2cDeviceProperty, util::IntrusiveListMemberTraits<&I2cDeviceProperty::m_device_property_list_node>>;
|
||||
public:
|
||||
I2cDeviceProperty() : IDevice(false), m_address(0), m_addressing_mode(AddressingMode_SevenBit), m_device_property_list_node() { /* ... */ }
|
||||
I2cDeviceProperty(u16 addr, AddressingMode m) : IDevice(false), m_address(addr), m_addressing_mode(m), m_device_property_list_node() { /* ... */ }
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace ams::lmem::impl {
|
|||
u32 magic;
|
||||
util::IntrusiveListNode list_node;
|
||||
|
||||
using ChildListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&HeapHead::list_node>;
|
||||
using ChildListTraits = util::IntrusiveListMemberTraits<&HeapHead::list_node>;
|
||||
using ChildList = ChildListTraits::ListType;
|
||||
ChildList child_list;
|
||||
|
||||
|
@ -90,6 +90,5 @@ namespace ams::lmem::impl {
|
|||
ImplementationHeapHead impl_head;
|
||||
};
|
||||
static_assert(std::is_trivially_destructible<HeapHead>::value);
|
||||
static_assert(HeapHead::ChildListTraits::IsValid());
|
||||
|
||||
}
|
||||
|
|
|
@ -355,9 +355,9 @@ namespace ams::gpio::driver::board::nintendo::nx::impl {
|
|||
PadInfo m_info;
|
||||
PadStatus m_status;
|
||||
public:
|
||||
using InterruptListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&TegraPad::m_interrupt_list_node>;
|
||||
using InterruptListTraits = util::IntrusiveListMemberTraits<&TegraPad::m_interrupt_list_node>;
|
||||
using InterruptList = typename InterruptListTraits::ListType;
|
||||
friend class util::IntrusiveList<TegraPad, util::IntrusiveListMemberTraitsDeferredAssert<&TegraPad::m_interrupt_list_node>>;
|
||||
friend class util::IntrusiveList<TegraPad, util::IntrusiveListMemberTraits<&TegraPad::m_interrupt_list_node>>;
|
||||
public:
|
||||
TegraPad() : Pad(), m_interrupt_list_node(), m_info(), m_status() { /* ... */ }
|
||||
|
||||
|
|
|
@ -54,9 +54,9 @@ namespace ams::i2c::driver::board::nintendo::nx::impl {
|
|||
DeviceCode m_device_code;
|
||||
util::IntrusiveListNode m_bus_accessor_list_node;
|
||||
public:
|
||||
using BusAccessorListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::m_bus_accessor_list_node>;
|
||||
using BusAccessorListTraits = util::IntrusiveListMemberTraits<&I2cBusAccessor::m_bus_accessor_list_node>;
|
||||
using BusAccessorList = typename BusAccessorListTraits::ListType;
|
||||
friend class util::IntrusiveList<I2cBusAccessor, util::IntrusiveListMemberTraitsDeferredAssert<&I2cBusAccessor::m_bus_accessor_list_node>>;
|
||||
friend class util::IntrusiveList<I2cBusAccessor, util::IntrusiveListMemberTraits<&I2cBusAccessor::m_bus_accessor_list_node>>;
|
||||
public:
|
||||
I2cBusAccessor()
|
||||
: m_registers(nullptr), m_speed_mode(SpeedMode_Fast), m_user_count(0), m_user_count_mutex(),
|
||||
|
|
|
@ -38,51 +38,51 @@ namespace ams::lmem::impl {
|
|||
void *end;
|
||||
};
|
||||
|
||||
constexpr inline bool IsValidHeapHandle(HeapHandle handle) {
|
||||
inline bool IsValidHeapHandle(HeapHandle handle) {
|
||||
return handle->magic == ExpHeapMagic;
|
||||
}
|
||||
|
||||
constexpr inline ExpHeapHead *GetExpHeapHead(HeapHead *heap_head) {
|
||||
inline ExpHeapHead *GetExpHeapHead(HeapHead *heap_head) {
|
||||
return std::addressof(heap_head->impl_head.exp_heap_head);
|
||||
}
|
||||
|
||||
constexpr inline const ExpHeapHead *GetExpHeapHead(const HeapHead *heap_head) {
|
||||
inline const ExpHeapHead *GetExpHeapHead(const HeapHead *heap_head) {
|
||||
return std::addressof(heap_head->impl_head.exp_heap_head);
|
||||
}
|
||||
|
||||
constexpr inline HeapHead *GetHeapHead(ExpHeapHead *exp_heap_head) {
|
||||
inline HeapHead *GetHeapHead(ExpHeapHead *exp_heap_head) {
|
||||
return util::GetParentPointer<&HeapHead::impl_head>(util::GetParentPointer<&ImplementationHeapHead::exp_heap_head>(exp_heap_head));
|
||||
}
|
||||
|
||||
constexpr inline const HeapHead *GetHeapHead(const ExpHeapHead *exp_heap_head) {
|
||||
inline const HeapHead *GetHeapHead(const ExpHeapHead *exp_heap_head) {
|
||||
return util::GetParentPointer<&HeapHead::impl_head>(util::GetParentPointer<&ImplementationHeapHead::exp_heap_head>(exp_heap_head));
|
||||
}
|
||||
|
||||
constexpr inline void *GetExpHeapMemoryStart(ExpHeapHead *exp_heap_head) {
|
||||
inline void *GetExpHeapMemoryStart(ExpHeapHead *exp_heap_head) {
|
||||
return reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(exp_heap_head) + sizeof(ImplementationHeapHead));
|
||||
}
|
||||
|
||||
constexpr inline void *GetMemoryBlockStart(ExpHeapMemoryBlockHead *head) {
|
||||
inline void *GetMemoryBlockStart(ExpHeapMemoryBlockHead *head) {
|
||||
return reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(head) + sizeof(*head));
|
||||
}
|
||||
|
||||
constexpr inline const void *GetMemoryBlockStart(const ExpHeapMemoryBlockHead *head) {
|
||||
inline const void *GetMemoryBlockStart(const ExpHeapMemoryBlockHead *head) {
|
||||
return reinterpret_cast<const void *>(reinterpret_cast<uintptr_t>(head) + sizeof(*head));
|
||||
}
|
||||
|
||||
constexpr inline void *GetMemoryBlockEnd(ExpHeapMemoryBlockHead *head) {
|
||||
inline void *GetMemoryBlockEnd(ExpHeapMemoryBlockHead *head) {
|
||||
return reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(GetMemoryBlockStart(head)) + head->block_size);
|
||||
}
|
||||
|
||||
constexpr inline const void *GetMemoryBlockEnd(const ExpHeapMemoryBlockHead *head) {
|
||||
inline const void *GetMemoryBlockEnd(const ExpHeapMemoryBlockHead *head) {
|
||||
return reinterpret_cast<const void *>(reinterpret_cast<uintptr_t>(GetMemoryBlockStart(head)) + head->block_size);
|
||||
}
|
||||
|
||||
constexpr inline ExpHeapMemoryBlockHead *GetHeadForMemoryBlock(const void *block) {
|
||||
inline ExpHeapMemoryBlockHead *GetHeadForMemoryBlock(const void *block) {
|
||||
return reinterpret_cast<ExpHeapMemoryBlockHead *>(reinterpret_cast<uintptr_t>(block) - sizeof(ExpHeapMemoryBlockHead));
|
||||
}
|
||||
|
||||
constexpr inline bool IsValidUsedMemoryBlock(const HeapHead *heap, const void *block) {
|
||||
inline bool IsValidUsedMemoryBlock(const HeapHead *heap, const void *block) {
|
||||
/* Block must fall within the heap range. */
|
||||
if (heap != nullptr) {
|
||||
if (block < heap->heap_start || heap->heap_end <= block) {
|
||||
|
@ -106,7 +106,7 @@ namespace ams::lmem::impl {
|
|||
return true;
|
||||
}
|
||||
|
||||
constexpr inline u16 GetMemoryBlockAlignmentPadding(const ExpHeapMemoryBlockHead *block_head) {
|
||||
inline u16 GetMemoryBlockAlignmentPadding(const ExpHeapMemoryBlockHead *block_head) {
|
||||
return static_cast<u16>((block_head->attributes >> 8) & 0x7F);
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ namespace ams::lmem::impl {
|
|||
block_head->attributes |= static_cast<decltype(block_head->attributes)>(padding & 0x7F) << 8;
|
||||
}
|
||||
|
||||
constexpr inline u16 GetMemoryBlockGroupId(const ExpHeapMemoryBlockHead *block_head) {
|
||||
inline u16 GetMemoryBlockGroupId(const ExpHeapMemoryBlockHead *block_head) {
|
||||
return static_cast<u16>(block_head->attributes & 0xFF);
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ namespace ams::lmem::impl {
|
|||
block_head->attributes |= static_cast<decltype(block_head->attributes)>(group_id & 0xFF);
|
||||
}
|
||||
|
||||
constexpr inline AllocationDirection GetMemoryBlockAllocationDirection(const ExpHeapMemoryBlockHead *block_head) {
|
||||
inline AllocationDirection GetMemoryBlockAllocationDirection(const ExpHeapMemoryBlockHead *block_head) {
|
||||
return static_cast<AllocationDirection>((block_head->attributes >> 15) & 1);
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ namespace ams::lmem::impl {
|
|||
out->end = GetMemoryBlockEnd(head);
|
||||
}
|
||||
|
||||
constexpr inline AllocationMode GetAllocationModeImpl(const ExpHeapHead *head) {
|
||||
inline AllocationMode GetAllocationModeImpl(const ExpHeapHead *head) {
|
||||
return static_cast<AllocationMode>(head->mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace ams::os::impl {
|
|||
static constexpr s32 WaitInvalid = -3;
|
||||
static constexpr s32 WaitCancelled = -2;
|
||||
static constexpr s32 WaitTimedOut = -1;
|
||||
using MultiWaitList = util::IntrusiveListMemberTraits<&MultiWaitHolderBase::m_multi_wait_node>::ListType;
|
||||
using MultiWaitList = util::IntrusiveListMemberTraitsByNonConstexprOffsetOf<&MultiWaitHolderBase::m_multi_wait_node>::ListType;
|
||||
private:
|
||||
MultiWaitList m_multi_wait_list;
|
||||
MultiWaitHolderBase *m_signaled_holder;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace ams::os::impl {
|
|||
|
||||
class MultiWaitObjectList {
|
||||
public:
|
||||
using ListType = util::IntrusiveListMemberTraits<&MultiWaitHolderBase::m_object_list_node>::ListType;
|
||||
using ListType = util::IntrusiveListMemberTraitsByNonConstexprOffsetOf<&MultiWaitHolderBase::m_object_list_node>::ListType;
|
||||
private:
|
||||
ListType m_object_list;
|
||||
public:
|
||||
|
|
|
@ -34,20 +34,22 @@ namespace ams::os::impl {
|
|||
private:
|
||||
friend class util::IntrusiveList<ThreadType, ThreadListTraits>;
|
||||
|
||||
static constexpr util::IntrusiveListNode &GetNode(ThreadType &parent) {
|
||||
static util::IntrusiveListNode &GetNode(ThreadType &parent) {
|
||||
return GetReference(parent.all_threads_node);
|
||||
}
|
||||
|
||||
static constexpr util::IntrusiveListNode const &GetNode(ThreadType const &parent) {
|
||||
static util::IntrusiveListNode const &GetNode(ThreadType const &parent) {
|
||||
return GetReference(parent.all_threads_node);
|
||||
}
|
||||
|
||||
static constexpr size_t Offset = OFFSETOF(ThreadType, all_threads_node);
|
||||
|
||||
static ThreadType &GetParent(util::IntrusiveListNode &node) {
|
||||
return *reinterpret_cast<ThreadType *>(reinterpret_cast<char *>(std::addressof(node)) - OFFSETOF(ThreadType, all_threads_node));
|
||||
return *reinterpret_cast<ThreadType *>(reinterpret_cast<char *>(std::addressof(node)) - Offset);
|
||||
}
|
||||
|
||||
static ThreadType const &GetParent(util::IntrusiveListNode const &node) {
|
||||
return *reinterpret_cast<const ThreadType *>(reinterpret_cast<const char *>(std::addressof(node)) - OFFSETOF(ThreadType, all_threads_node));
|
||||
return *reinterpret_cast<const ThreadType *>(reinterpret_cast<const char *>(std::addressof(node)) - Offset);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -45,13 +45,13 @@ namespace ams::util {
|
|||
return m_next != this;
|
||||
}
|
||||
private:
|
||||
ALWAYS_INLINE void LinkPrev(IntrusiveListNode *node) {
|
||||
constexpr ALWAYS_INLINE void LinkPrev(IntrusiveListNode *node) {
|
||||
/* We can't link an already linked node. */
|
||||
AMS_ASSERT(!node->IsLinked());
|
||||
this->SplicePrev(node, node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SplicePrev(IntrusiveListNode *first, IntrusiveListNode *last) {
|
||||
constexpr ALWAYS_INLINE void SplicePrev(IntrusiveListNode *first, IntrusiveListNode *last) {
|
||||
/* Splice a range into the list. */
|
||||
auto last_prev = last->m_prev;
|
||||
first->m_prev = m_prev;
|
||||
|
@ -60,13 +60,13 @@ namespace ams::util {
|
|||
m_prev = last_prev;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void LinkNext(IntrusiveListNode *node) {
|
||||
constexpr ALWAYS_INLINE void LinkNext(IntrusiveListNode *node) {
|
||||
/* We can't link an already linked node. */
|
||||
AMS_ASSERT(!node->IsLinked());
|
||||
return this->SpliceNext(node, node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SpliceNext(IntrusiveListNode *first, IntrusiveListNode *last) {
|
||||
constexpr ALWAYS_INLINE void SpliceNext(IntrusiveListNode *first, IntrusiveListNode *last) {
|
||||
/* Splice a range into the list. */
|
||||
auto last_prev = last->m_prev;
|
||||
first->m_prev = this;
|
||||
|
@ -75,11 +75,11 @@ namespace ams::util {
|
|||
m_next = first;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Unlink() {
|
||||
constexpr ALWAYS_INLINE void Unlink() {
|
||||
this->Unlink(m_next);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Unlink(IntrusiveListNode *last) {
|
||||
constexpr ALWAYS_INLINE void Unlink(IntrusiveListNode *last) {
|
||||
/* Unlink a node from a next node. */
|
||||
auto last_prev = last->m_prev;
|
||||
m_prev->m_next = last;
|
||||
|
@ -88,19 +88,19 @@ namespace ams::util {
|
|||
m_prev = last_prev;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveListNode *GetPrev() {
|
||||
constexpr ALWAYS_INLINE IntrusiveListNode *GetPrev() {
|
||||
return m_prev;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const IntrusiveListNode *GetPrev() const {
|
||||
constexpr ALWAYS_INLINE const IntrusiveListNode *GetPrev() const {
|
||||
return m_prev;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveListNode *GetNext() {
|
||||
constexpr ALWAYS_INLINE IntrusiveListNode *GetNext() {
|
||||
return m_next;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const IntrusiveListNode *GetNext() const {
|
||||
constexpr ALWAYS_INLINE const IntrusiveListNode *GetNext() const {
|
||||
return m_next;
|
||||
}
|
||||
};
|
||||
|
@ -139,51 +139,51 @@ namespace ams::util {
|
|||
private:
|
||||
pointer m_node;
|
||||
public:
|
||||
ALWAYS_INLINE explicit Iterator(pointer n) : m_node(n) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE explicit Iterator(pointer n) : m_node(n) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
constexpr ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
return m_node == rhs.m_node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
constexpr ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE pointer operator->() const {
|
||||
constexpr ALWAYS_INLINE pointer operator->() const {
|
||||
return m_node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference operator*() const {
|
||||
constexpr ALWAYS_INLINE reference operator*() const {
|
||||
return *m_node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator++() {
|
||||
constexpr ALWAYS_INLINE Iterator &operator++() {
|
||||
m_node = m_node->m_next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator--() {
|
||||
constexpr ALWAYS_INLINE Iterator &operator--() {
|
||||
m_node = m_node->m_prev;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator++(int) {
|
||||
constexpr ALWAYS_INLINE Iterator operator++(int) {
|
||||
const Iterator it{*this};
|
||||
++(*this);
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator--(int) {
|
||||
constexpr ALWAYS_INLINE Iterator operator--(int) {
|
||||
const Iterator it{*this};
|
||||
--(*this);
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE operator Iterator<true>() const {
|
||||
constexpr ALWAYS_INLINE operator Iterator<true>() const {
|
||||
return Iterator<true>(m_node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator<false> GetNonConstIterator() const {
|
||||
constexpr ALWAYS_INLINE Iterator<false> GetNonConstIterator() const {
|
||||
return Iterator<false>(const_cast<IntrusiveListImpl::pointer>(m_node));
|
||||
}
|
||||
};
|
||||
|
@ -191,97 +191,97 @@ namespace ams::util {
|
|||
constexpr ALWAYS_INLINE IntrusiveListImpl() : m_root_node() { /* ... */ }
|
||||
|
||||
/* Iterator accessors. */
|
||||
ALWAYS_INLINE iterator begin() {
|
||||
constexpr ALWAYS_INLINE iterator begin() {
|
||||
return iterator(m_root_node.GetNext());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator begin() const {
|
||||
constexpr ALWAYS_INLINE const_iterator begin() const {
|
||||
return const_iterator(m_root_node.GetNext());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator end() {
|
||||
constexpr ALWAYS_INLINE iterator end() {
|
||||
return iterator(std::addressof(m_root_node));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator end() const {
|
||||
constexpr ALWAYS_INLINE const_iterator end() const {
|
||||
return const_iterator(std::addressof(m_root_node));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator iterator_to(reference v) {
|
||||
constexpr ALWAYS_INLINE iterator iterator_to(reference v) {
|
||||
/* Only allow iterator_to for values in lists. */
|
||||
AMS_ASSERT(v.IsLinked());
|
||||
return iterator(std::addressof(v));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator iterator_to(const_reference v) const {
|
||||
constexpr ALWAYS_INLINE const_iterator iterator_to(const_reference v) const {
|
||||
/* Only allow iterator_to for values in lists. */
|
||||
AMS_ASSERT(v.IsLinked());
|
||||
return const_iterator(std::addressof(v));
|
||||
}
|
||||
|
||||
/* Content management. */
|
||||
ALWAYS_INLINE bool empty() const {
|
||||
constexpr ALWAYS_INLINE bool empty() const {
|
||||
return !m_root_node.IsLinked();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE size_type size() const {
|
||||
constexpr ALWAYS_INLINE size_type size() const {
|
||||
return static_cast<size_type>(std::distance(this->begin(), this->end()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference back() {
|
||||
constexpr ALWAYS_INLINE reference back() {
|
||||
return *m_root_node.GetPrev();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference back() const {
|
||||
constexpr ALWAYS_INLINE const_reference back() const {
|
||||
return *m_root_node.GetPrev();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference front() {
|
||||
constexpr ALWAYS_INLINE reference front() {
|
||||
return *m_root_node.GetNext();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference front() const {
|
||||
constexpr ALWAYS_INLINE const_reference front() const {
|
||||
return *m_root_node.GetNext();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void push_back(reference node) {
|
||||
constexpr ALWAYS_INLINE void push_back(reference node) {
|
||||
m_root_node.LinkPrev(std::addressof(node));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void push_front(reference node) {
|
||||
constexpr ALWAYS_INLINE void push_front(reference node) {
|
||||
m_root_node.LinkNext(std::addressof(node));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void pop_back() {
|
||||
constexpr ALWAYS_INLINE void pop_back() {
|
||||
m_root_node.GetPrev()->Unlink();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void pop_front() {
|
||||
constexpr ALWAYS_INLINE void pop_front() {
|
||||
m_root_node.GetNext()->Unlink();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator insert(const_iterator pos, reference node) {
|
||||
constexpr ALWAYS_INLINE iterator insert(const_iterator pos, reference node) {
|
||||
pos.GetNonConstIterator()->LinkPrev(std::addressof(node));
|
||||
return iterator(std::addressof(node));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveListImpl &o) {
|
||||
constexpr ALWAYS_INLINE void splice(const_iterator pos, IntrusiveListImpl &o) {
|
||||
splice_impl(pos, o.begin(), o.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveListImpl &o, const_iterator first) {
|
||||
constexpr ALWAYS_INLINE void splice(const_iterator pos, IntrusiveListImpl &o, const_iterator first) {
|
||||
AMS_UNUSED(o);
|
||||
const_iterator last(first);
|
||||
std::advance(last, 1);
|
||||
splice_impl(pos, first, last);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveListImpl &o, const_iterator first, const_iterator last) {
|
||||
constexpr ALWAYS_INLINE void splice(const_iterator pos, IntrusiveListImpl &o, const_iterator first, const_iterator last) {
|
||||
AMS_UNUSED(o);
|
||||
splice_impl(pos, first, last);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator erase(const_iterator pos) {
|
||||
constexpr ALWAYS_INLINE iterator erase(const_iterator pos) {
|
||||
if (pos == this->end()) {
|
||||
return this->end();
|
||||
}
|
||||
|
@ -290,13 +290,13 @@ namespace ams::util {
|
|||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void clear() {
|
||||
constexpr ALWAYS_INLINE void clear() {
|
||||
while (!this->empty()) {
|
||||
this->pop_front();
|
||||
}
|
||||
}
|
||||
private:
|
||||
ALWAYS_INLINE void splice_impl(const_iterator _pos, const_iterator _first, const_iterator _last) {
|
||||
constexpr ALWAYS_INLINE void splice_impl(const_iterator _pos, const_iterator _first, const_iterator _last) {
|
||||
if (_first == _last) {
|
||||
return;
|
||||
}
|
||||
|
@ -306,7 +306,6 @@ namespace ams::util {
|
|||
first->Unlink(std::addressof(*last));
|
||||
pos->SplicePrev(std::addressof(*first), std::addressof(*first));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -347,51 +346,51 @@ namespace ams::util {
|
|||
private:
|
||||
ImplIterator m_iterator;
|
||||
private:
|
||||
explicit ALWAYS_INLINE Iterator(ImplIterator it) : m_iterator(it) { /* ... */ }
|
||||
constexpr explicit ALWAYS_INLINE Iterator(ImplIterator it) : m_iterator(it) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE ImplIterator GetImplIterator() const {
|
||||
constexpr ALWAYS_INLINE ImplIterator GetImplIterator() const {
|
||||
return m_iterator;
|
||||
}
|
||||
public:
|
||||
ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
constexpr ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
return m_iterator == rhs.m_iterator;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
constexpr ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE pointer operator->() const {
|
||||
constexpr ALWAYS_INLINE pointer operator->() const {
|
||||
return std::addressof(Traits::GetParent(*m_iterator));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference operator*() const {
|
||||
constexpr ALWAYS_INLINE reference operator*() const {
|
||||
return Traits::GetParent(*m_iterator);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator++() {
|
||||
constexpr ALWAYS_INLINE Iterator &operator++() {
|
||||
++m_iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator--() {
|
||||
constexpr ALWAYS_INLINE Iterator &operator--() {
|
||||
--m_iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator++(int) {
|
||||
constexpr ALWAYS_INLINE Iterator operator++(int) {
|
||||
const Iterator it{*this};
|
||||
++m_iterator;
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator--(int) {
|
||||
constexpr ALWAYS_INLINE Iterator operator--(int) {
|
||||
const Iterator it{*this};
|
||||
--m_iterator;
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE operator Iterator<true>() const {
|
||||
constexpr ALWAYS_INLINE operator Iterator<true>() const {
|
||||
return Iterator<true>(m_iterator);
|
||||
}
|
||||
};
|
||||
|
@ -415,130 +414,130 @@ namespace ams::util {
|
|||
constexpr ALWAYS_INLINE IntrusiveList() : m_impl() { /* ... */ }
|
||||
|
||||
/* Iterator accessors. */
|
||||
ALWAYS_INLINE iterator begin() {
|
||||
constexpr ALWAYS_INLINE iterator begin() {
|
||||
return iterator(m_impl.begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator begin() const {
|
||||
constexpr ALWAYS_INLINE const_iterator begin() const {
|
||||
return const_iterator(m_impl.begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator end() {
|
||||
constexpr ALWAYS_INLINE iterator end() {
|
||||
return iterator(m_impl.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator end() const {
|
||||
constexpr ALWAYS_INLINE const_iterator end() const {
|
||||
return const_iterator(m_impl.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cbegin() const {
|
||||
constexpr ALWAYS_INLINE const_iterator cbegin() const {
|
||||
return this->begin();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cend() const {
|
||||
constexpr ALWAYS_INLINE const_iterator cend() const {
|
||||
return this->end();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reverse_iterator rbegin() {
|
||||
constexpr ALWAYS_INLINE reverse_iterator rbegin() {
|
||||
return reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reverse_iterator rbegin() const {
|
||||
constexpr ALWAYS_INLINE const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reverse_iterator rend() {
|
||||
constexpr ALWAYS_INLINE reverse_iterator rend() {
|
||||
return reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reverse_iterator rend() const {
|
||||
constexpr ALWAYS_INLINE const_reverse_iterator rend() const {
|
||||
return const_reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reverse_iterator crbegin() const {
|
||||
constexpr ALWAYS_INLINE const_reverse_iterator crbegin() const {
|
||||
return this->rbegin();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reverse_iterator crend() const {
|
||||
constexpr ALWAYS_INLINE const_reverse_iterator crend() const {
|
||||
return this->rend();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator iterator_to(reference v) {
|
||||
constexpr ALWAYS_INLINE iterator iterator_to(reference v) {
|
||||
return iterator(m_impl.iterator_to(GetNode(v)));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator iterator_to(const_reference v) const {
|
||||
constexpr ALWAYS_INLINE const_iterator iterator_to(const_reference v) const {
|
||||
return const_iterator(m_impl.iterator_to(GetNode(v)));
|
||||
}
|
||||
|
||||
/* Content management. */
|
||||
ALWAYS_INLINE bool empty() const {
|
||||
constexpr ALWAYS_INLINE bool empty() const {
|
||||
return m_impl.empty();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE size_type size() const {
|
||||
constexpr ALWAYS_INLINE size_type size() const {
|
||||
return m_impl.size();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference back() {
|
||||
constexpr ALWAYS_INLINE reference back() {
|
||||
AMS_ASSERT(!m_impl.empty());
|
||||
return GetParent(m_impl.back());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference back() const {
|
||||
constexpr ALWAYS_INLINE const_reference back() const {
|
||||
AMS_ASSERT(!m_impl.empty());
|
||||
return GetParent(m_impl.back());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference front() {
|
||||
constexpr ALWAYS_INLINE reference front() {
|
||||
AMS_ASSERT(!m_impl.empty());
|
||||
return GetParent(m_impl.front());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference front() const {
|
||||
constexpr ALWAYS_INLINE const_reference front() const {
|
||||
AMS_ASSERT(!m_impl.empty());
|
||||
return GetParent(m_impl.front());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void push_back(reference ref) {
|
||||
constexpr ALWAYS_INLINE void push_back(reference ref) {
|
||||
m_impl.push_back(GetNode(ref));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void push_front(reference ref) {
|
||||
constexpr ALWAYS_INLINE void push_front(reference ref) {
|
||||
m_impl.push_front(GetNode(ref));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void pop_back() {
|
||||
constexpr ALWAYS_INLINE void pop_back() {
|
||||
AMS_ASSERT(!m_impl.empty());
|
||||
m_impl.pop_back();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void pop_front() {
|
||||
constexpr ALWAYS_INLINE void pop_front() {
|
||||
AMS_ASSERT(!m_impl.empty());
|
||||
m_impl.pop_front();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator insert(const_iterator pos, reference ref) {
|
||||
constexpr ALWAYS_INLINE iterator insert(const_iterator pos, reference ref) {
|
||||
return iterator(m_impl.insert(pos.GetImplIterator(), GetNode(ref)));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveList &o) {
|
||||
constexpr ALWAYS_INLINE void splice(const_iterator pos, IntrusiveList &o) {
|
||||
m_impl.splice(pos.GetImplIterator(), o.m_impl);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveList &o, const_iterator first) {
|
||||
constexpr ALWAYS_INLINE void splice(const_iterator pos, IntrusiveList &o, const_iterator first) {
|
||||
m_impl.splice(pos.GetImplIterator(), o.m_impl, first.GetImplIterator());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveList &o, const_iterator first, const_iterator last) {
|
||||
constexpr ALWAYS_INLINE void splice(const_iterator pos, IntrusiveList &o, const_iterator first, const_iterator last) {
|
||||
m_impl.splice(pos.GetImplIterator(), o.m_impl, first.GetImplIterator(), last.GetImplIterator());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator erase(const_iterator pos) {
|
||||
constexpr ALWAYS_INLINE iterator erase(const_iterator pos) {
|
||||
return iterator(m_impl.erase(pos.GetImplIterator()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void clear() {
|
||||
constexpr ALWAYS_INLINE void clear() {
|
||||
m_impl.clear();
|
||||
}
|
||||
};
|
||||
|
@ -561,32 +560,24 @@ namespace ams::util {
|
|||
return parent.*Member;
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived &GetParent(IntrusiveListNode &node) {
|
||||
static ALWAYS_INLINE Derived &GetParent(IntrusiveListNode &node) {
|
||||
return util::GetParentReference<Member, Derived>(std::addressof(node));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
static ALWAYS_INLINE Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
return util::GetParentReference<Member, Derived>(std::addressof(node));
|
||||
}
|
||||
private:
|
||||
static constexpr TypedStorage<Derived> DerivedStorage = {};
|
||||
static_assert(std::addressof(GetParent(GetNode(GetReference(DerivedStorage)))) == GetPointer(DerivedStorage));
|
||||
};
|
||||
|
||||
template<auto T, class Derived = util::impl::GetParentType<T>>
|
||||
class IntrusiveListMemberTraitsDeferredAssert;
|
||||
class IntrusiveListMemberTraitsByNonConstexprOffsetOf;
|
||||
|
||||
template<class Parent, IntrusiveListNode Parent::*Member, class Derived>
|
||||
class IntrusiveListMemberTraitsDeferredAssert<Member, Derived> {
|
||||
class IntrusiveListMemberTraitsByNonConstexprOffsetOf<Member, Derived> {
|
||||
public:
|
||||
using ListType = IntrusiveList<Derived, IntrusiveListMemberTraitsDeferredAssert>;
|
||||
|
||||
static constexpr bool IsValid() {
|
||||
TypedStorage<Derived> DerivedStorage = {};
|
||||
return std::addressof(GetParent(GetNode(GetReference(DerivedStorage)))) == GetPointer(DerivedStorage);
|
||||
}
|
||||
using ListType = IntrusiveList<Derived, IntrusiveListMemberTraitsByNonConstexprOffsetOf>;
|
||||
private:
|
||||
friend class IntrusiveList<Derived, IntrusiveListMemberTraitsDeferredAssert>;
|
||||
friend class IntrusiveList<Derived, IntrusiveListMemberTraitsByNonConstexprOffsetOf>;
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode &GetNode(Derived &parent) {
|
||||
return parent.*Member;
|
||||
|
@ -596,12 +587,16 @@ namespace ams::util {
|
|||
return parent.*Member;
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived &GetParent(IntrusiveListNode &node) {
|
||||
return util::GetParentReference<Member, Derived>(std::addressof(node));
|
||||
static ALWAYS_INLINE Derived &GetParent(IntrusiveListNode &node) {
|
||||
return *reinterpret_cast<Derived *>(reinterpret_cast<char *>(std::addressof(node)) - GetOffset());
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
return util::GetParentReference<Member, Derived>(std::addressof(node));
|
||||
static ALWAYS_INLINE Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
return *reinterpret_cast<const Derived *>(reinterpret_cast<const char *>(std::addressof(node)) - GetOffset());
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uintptr_t GetOffset() {
|
||||
return reinterpret_cast<uintptr_t>(std::addressof(reinterpret_cast<Derived *>(0)->*Member));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -616,19 +611,19 @@ namespace ams::util {
|
|||
friend class IntrusiveList<Derived, IntrusiveListBaseTraits>;
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode &GetNode(Derived &parent) {
|
||||
return static_cast<IntrusiveListNode &>(parent);
|
||||
return static_cast<IntrusiveListNode &>(static_cast<IntrusiveListBaseNode<Derived> &>(parent));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode const &GetNode(Derived const &parent) {
|
||||
return static_cast<const IntrusiveListNode &>(parent);
|
||||
return static_cast<const IntrusiveListNode &>(static_cast<const IntrusiveListBaseNode<Derived> &>(parent));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived &GetParent(IntrusiveListNode &node) {
|
||||
return static_cast<Derived &>(node);
|
||||
return static_cast<Derived &>(static_cast<IntrusiveListBaseNode<Derived> &>(node));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
return static_cast<const Derived &>(node);
|
||||
return static_cast<const Derived &>(static_cast<const IntrusiveListBaseNode<Derived> &>(node));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -494,17 +494,15 @@ namespace ams::util {
|
|||
return std::addressof(parent->*Member);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
static ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
return util::GetParentPointer<Member, Derived>(node);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
static ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
return util::GetParentPointer<Member, Derived>(node);
|
||||
}
|
||||
private:
|
||||
static constexpr TypedStorage<Derived> DerivedStorage = {};
|
||||
static_assert(GetParent(GetNode(GetPointer(DerivedStorage))) == GetPointer(DerivedStorage));
|
||||
static_assert(util::IsAligned(util::impl::OffsetOf<Member, Derived>, alignof(void *)));
|
||||
static_assert(util::IsAligned(util::impl::OffsetOf<Member, Derived>::Value, alignof(void *)));
|
||||
};
|
||||
|
||||
template<auto T, class Derived = util::impl::GetParentType<T>>
|
||||
|
@ -518,8 +516,7 @@ namespace ams::util {
|
|||
using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
|
||||
|
||||
static constexpr bool IsValid() {
|
||||
TypedStorage<Derived> DerivedStorage = {};
|
||||
return GetParent(GetNode(GetPointer(DerivedStorage))) == GetPointer(DerivedStorage) && util::IsAligned(util::impl::OffsetOf<Member, Derived>, alignof(void *));
|
||||
return util::IsAligned(util::impl::OffsetOf<Member, Derived>::Value, alignof(void *));
|
||||
}
|
||||
private:
|
||||
template<class, class, class>
|
||||
|
@ -535,11 +532,11 @@ namespace ams::util {
|
|||
return std::addressof(parent->*Member);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
static ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
return util::GetParentPointer<Member, Derived>(node);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
static ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
return util::GetParentPointer<Member, Derived>(node);
|
||||
}
|
||||
};
|
||||
|
@ -547,14 +544,14 @@ namespace ams::util {
|
|||
template<class Derived>
|
||||
class alignas(void *) IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode {
|
||||
public:
|
||||
constexpr ALWAYS_INLINE Derived *GetPrev() { return static_cast< Derived *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this)); }
|
||||
constexpr ALWAYS_INLINE const Derived *GetPrev() const { return static_cast<const Derived *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this)); }
|
||||
constexpr ALWAYS_INLINE Derived *GetPrev() { return static_cast< Derived *>(static_cast< IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this))); }
|
||||
constexpr ALWAYS_INLINE const Derived *GetPrev() const { return static_cast<const Derived *>(static_cast<const IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this))); }
|
||||
|
||||
constexpr ALWAYS_INLINE Derived *GetNext() { return static_cast< Derived *>(impl::IntrusiveRedBlackTreeImpl::GetNext(this)); }
|
||||
constexpr ALWAYS_INLINE const Derived *GetNext() const { return static_cast<const Derived *>(impl::IntrusiveRedBlackTreeImpl::GetNext(this)); }
|
||||
constexpr ALWAYS_INLINE Derived *GetNext() { return static_cast< Derived *>(static_cast< IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetNext(this))); }
|
||||
constexpr ALWAYS_INLINE const Derived *GetNext() const { return static_cast<const Derived *>(static_cast<const IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetNext(this))); }
|
||||
};
|
||||
|
||||
template<class Derived> requires std::derived_from<Derived, IntrusiveRedBlackTreeNode>
|
||||
template<class Derived>
|
||||
class IntrusiveRedBlackTreeBaseTraits {
|
||||
public:
|
||||
template<class Comparator>
|
||||
|
@ -567,19 +564,19 @@ namespace ams::util {
|
|||
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||
return static_cast<IntrusiveRedBlackTreeNode *>(parent);
|
||||
return static_cast<IntrusiveRedBlackTreeNode *>(static_cast<IntrusiveRedBlackTreeBaseNode<Derived> *>(parent));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
|
||||
return static_cast<const IntrusiveRedBlackTreeNode *>(parent);
|
||||
return static_cast<const IntrusiveRedBlackTreeNode *>(static_cast<const IntrusiveRedBlackTreeBaseNode<Derived> *>(parent));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
return static_cast<Derived *>(node);
|
||||
return static_cast<Derived *>(static_cast<IntrusiveRedBlackTreeBaseNode<Derived> *>(node));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
return static_cast<const Derived *>(node);
|
||||
return static_cast<const Derived *>(static_cast<const IntrusiveRedBlackTreeBaseNode<Derived> *>(node));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -43,16 +43,6 @@ namespace ams::util {
|
|||
UnionImpl<ParentType, MemberType, Offset + 1> next_union;
|
||||
};
|
||||
|
||||
template<typename ParentType, typename MemberType>
|
||||
union UnionImpl<ParentType, MemberType, 0> {
|
||||
static constexpr size_t GetOffset() { return 0; }
|
||||
|
||||
struct {
|
||||
MemberType members[(sizeof(ParentType) / sizeof(MemberType)) + 1];
|
||||
} data;
|
||||
UnionImpl<ParentType, MemberType, 1> next_union;
|
||||
};
|
||||
|
||||
template<typename ParentType, typename MemberType>
|
||||
union UnionImpl<ParentType, MemberType, MaxDepth> { /* Empty ... */ };
|
||||
};
|
||||
|
@ -63,10 +53,11 @@ namespace ams::util {
|
|||
union Union {
|
||||
char c;
|
||||
UnionHolder first_union;
|
||||
TypedStorage<ParentType> parent;
|
||||
ParentType parent;
|
||||
|
||||
/* This coerces the active member to be c. */
|
||||
constexpr Union() : c() { /* ... */ }
|
||||
constexpr ~Union() { std::destroy_at(std::addressof(c)); }
|
||||
};
|
||||
static constexpr Union U = {};
|
||||
|
||||
|
@ -84,7 +75,7 @@ namespace ams::util {
|
|||
template<typename CurUnion>
|
||||
static constexpr std::ptrdiff_t OffsetOfImpl(MemberType ParentType::*member, CurUnion &cur_union) {
|
||||
constexpr size_t Offset = CurUnion::GetOffset();
|
||||
const auto target = std::addressof(GetPointer(U.parent)->*member);
|
||||
const auto target = std::addressof(U.parent.*member);
|
||||
const auto start = std::addressof(cur_union.data.members[0]);
|
||||
const auto next = GetNextAddress(start, target);
|
||||
|
||||
|
@ -107,11 +98,20 @@ namespace ams::util {
|
|||
|
||||
#else
|
||||
|
||||
template<typename T>
|
||||
union HelperUnion {
|
||||
T v;
|
||||
char c;
|
||||
|
||||
constexpr HelperUnion() : c() { /* ... */ }
|
||||
constexpr ~HelperUnion() { std::destroy_at(std::addressof(c)); }
|
||||
};
|
||||
|
||||
template<typename ParentType, typename MemberType>
|
||||
struct OffsetOfCalculator {
|
||||
static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::*member) {
|
||||
constexpr TypedStorage<ParentType> Holder = {};
|
||||
const auto *parent = GetPointer(Holder);
|
||||
constexpr HelperUnion<ParentType> Holder = {};
|
||||
const auto *parent = std::addressof(Holder.v);
|
||||
const auto *target = std::addressof(parent->*member);
|
||||
return static_cast<const uint8_t *>(static_cast<const void *>(target)) - static_cast<const uint8_t *>(static_cast<const void *>(parent));
|
||||
}
|
||||
|
@ -134,141 +134,63 @@ namespace ams::util {
|
|||
template<auto MemberPtr>
|
||||
using GetMemberType = typename GetMemberPointerTraits<decltype(MemberPtr)>::Member;
|
||||
|
||||
template<auto MemberPtr, typename RealParentType = GetParentType<MemberPtr>>
|
||||
constexpr inline std::ptrdiff_t OffsetOf = [] {
|
||||
using DeducedParentType = GetParentType<MemberPtr>;
|
||||
using MemberType = GetMemberType<MemberPtr>;
|
||||
static_assert(std::is_base_of<DeducedParentType, RealParentType>::value || std::is_same<RealParentType, DeducedParentType>::value);
|
||||
/* DEPRECATED: static_assert(std::is_literal_type<MemberType>::value); */
|
||||
|
||||
return OffsetOfCalculator<RealParentType, MemberType>::OffsetOf(MemberPtr);
|
||||
}();
|
||||
template<auto MemberPtr, typename RealParentType = GetParentType<MemberPtr>> requires (std::derived_from<RealParentType, GetParentType<MemberPtr>> || std::same_as<RealParentType, GetParentType<MemberPtr>>)
|
||||
struct OffsetOf {
|
||||
using MemberType = GetMemberType<MemberPtr>;
|
||||
|
||||
static constexpr std::ptrdiff_t Value = OffsetOfCalculator<RealParentType, MemberType>::OffsetOf(MemberPtr);
|
||||
};
|
||||
}
|
||||
|
||||
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
|
||||
constexpr ALWAYS_INLINE RealParentType &GetParentReference(impl::GetMemberType<MemberPtr> *member) {
|
||||
constexpr std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>;
|
||||
ALWAYS_INLINE RealParentType &GetParentReference(impl::GetMemberType<MemberPtr> *member) {
|
||||
constexpr std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>::Value;
|
||||
return *static_cast<RealParentType *>(static_cast<void *>(static_cast<uint8_t *>(static_cast<void *>(member)) - Offset));
|
||||
}
|
||||
|
||||
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
|
||||
constexpr ALWAYS_INLINE RealParentType const &GetParentReference(impl::GetMemberType<MemberPtr> const *member) {
|
||||
constexpr std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>;
|
||||
ALWAYS_INLINE RealParentType const &GetParentReference(impl::GetMemberType<MemberPtr> const *member) {
|
||||
constexpr std::ptrdiff_t Offset = impl::OffsetOf<MemberPtr, RealParentType>::Value;
|
||||
return *static_cast<const RealParentType *>(static_cast<const void *>(static_cast<const uint8_t *>(static_cast<const void *>(member)) - Offset));
|
||||
}
|
||||
|
||||
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
|
||||
constexpr ALWAYS_INLINE RealParentType *GetParentPointer(impl::GetMemberType<MemberPtr> *member) {
|
||||
ALWAYS_INLINE RealParentType *GetParentPointer(impl::GetMemberType<MemberPtr> *member) {
|
||||
return std::addressof(GetParentReference<MemberPtr, RealParentType>(member));
|
||||
}
|
||||
|
||||
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
|
||||
constexpr ALWAYS_INLINE RealParentType const *GetParentPointer(impl::GetMemberType<MemberPtr> const *member) {
|
||||
ALWAYS_INLINE RealParentType const *GetParentPointer(impl::GetMemberType<MemberPtr> const *member) {
|
||||
return std::addressof(GetParentReference<MemberPtr, RealParentType>(member));
|
||||
}
|
||||
|
||||
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
|
||||
constexpr ALWAYS_INLINE RealParentType &GetParentReference(impl::GetMemberType<MemberPtr> &member) {
|
||||
ALWAYS_INLINE RealParentType &GetParentReference(impl::GetMemberType<MemberPtr> &member) {
|
||||
return GetParentReference<MemberPtr, RealParentType>(std::addressof(member));
|
||||
}
|
||||
|
||||
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
|
||||
constexpr ALWAYS_INLINE RealParentType const &GetParentReference(impl::GetMemberType<MemberPtr> const &member) {
|
||||
ALWAYS_INLINE RealParentType const &GetParentReference(impl::GetMemberType<MemberPtr> const &member) {
|
||||
return GetParentReference<MemberPtr, RealParentType>(std::addressof(member));
|
||||
}
|
||||
|
||||
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
|
||||
constexpr ALWAYS_INLINE RealParentType *GetParentPointer(impl::GetMemberType<MemberPtr> &member) {
|
||||
ALWAYS_INLINE RealParentType *GetParentPointer(impl::GetMemberType<MemberPtr> &member) {
|
||||
return std::addressof(GetParentReference<MemberPtr, RealParentType>(member));
|
||||
}
|
||||
|
||||
template<auto MemberPtr, typename RealParentType = impl::GetParentType<MemberPtr>>
|
||||
constexpr ALWAYS_INLINE RealParentType const *GetParentPointer(impl::GetMemberType<MemberPtr> const &member) {
|
||||
ALWAYS_INLINE RealParentType const *GetParentPointer(impl::GetMemberType<MemberPtr> const &member) {
|
||||
return std::addressof(GetParentReference<MemberPtr, RealParentType>(member));
|
||||
}
|
||||
|
||||
|
||||
/* Defines, for use by other code. */
|
||||
/* Defines, for use by other code. */
|
||||
|
||||
#define OFFSETOF(parent, member) (::ams::util::impl::OffsetOf<&parent::member, parent>)
|
||||
#define OFFSETOF(parent, member) (::ams::util::impl::OffsetOf<&parent::member, parent>::Value)
|
||||
|
||||
#define GET_PARENT_PTR(parent, member, _arg) (::ams::util::GetParentPointer<&parent::member, parent>(_arg))
|
||||
#define GET_PARENT_PTR(parent, member, _arg) (::ams::util::GetParentPointer<&parent::member, parent>(_arg))
|
||||
|
||||
#define GET_PARENT_REF(parent, member, _arg) (::ams::util::GetParentReference<&parent::member, parent>(_arg))
|
||||
|
||||
namespace test {
|
||||
|
||||
struct Struct1 {
|
||||
uint32_t a;
|
||||
};
|
||||
|
||||
struct Struct2 {
|
||||
uint32_t b;
|
||||
};
|
||||
|
||||
struct Struct3 : public Struct1, Struct2 {
|
||||
uint32_t c;
|
||||
};
|
||||
|
||||
static_assert(impl::OffsetOf<&Struct1::a> == 0);
|
||||
static_assert(impl::OffsetOf<&Struct2::b> == 0);
|
||||
static_assert(impl::OffsetOf<&Struct3::a> == 0);
|
||||
static_assert(impl::OffsetOf<&Struct3::b> == 0);
|
||||
|
||||
|
||||
static_assert(impl::OffsetOf<&Struct3::a, Struct3> == 0 || impl::OffsetOf<&Struct3::b, Struct3> == 0);
|
||||
static_assert(impl::OffsetOf<&Struct3::a, Struct3> == sizeof(Struct2) || impl::OffsetOf<&Struct3::b, Struct3> == sizeof(Struct1));
|
||||
static_assert(impl::OffsetOf<&Struct3::c> == sizeof(Struct1) + sizeof(Struct2));
|
||||
|
||||
constexpr Struct3 TestStruct3 = {};
|
||||
|
||||
static_assert(std::addressof(TestStruct3) == GET_PARENT_PTR(Struct3, a, TestStruct3.a));
|
||||
static_assert(std::addressof(TestStruct3) == GET_PARENT_PTR(Struct3, a, std::addressof(TestStruct3.a)));
|
||||
static_assert(std::addressof(TestStruct3) == GET_PARENT_PTR(Struct3, b, TestStruct3.b));
|
||||
static_assert(std::addressof(TestStruct3) == GET_PARENT_PTR(Struct3, b, std::addressof(TestStruct3.b)));
|
||||
static_assert(std::addressof(TestStruct3) == GET_PARENT_PTR(Struct3, c, TestStruct3.c));
|
||||
static_assert(std::addressof(TestStruct3) == GET_PARENT_PTR(Struct3, c, std::addressof(TestStruct3.c)));
|
||||
|
||||
struct CharArray {
|
||||
char c0;
|
||||
char c1;
|
||||
char c2;
|
||||
char c3;
|
||||
char c4;
|
||||
char c5;
|
||||
char c6;
|
||||
char c7;
|
||||
};
|
||||
|
||||
static_assert(impl::OffsetOf<&CharArray::c0> == 0);
|
||||
static_assert(impl::OffsetOf<&CharArray::c1> == 1);
|
||||
static_assert(impl::OffsetOf<&CharArray::c2> == 2);
|
||||
static_assert(impl::OffsetOf<&CharArray::c3> == 3);
|
||||
static_assert(impl::OffsetOf<&CharArray::c4> == 4);
|
||||
static_assert(impl::OffsetOf<&CharArray::c5> == 5);
|
||||
static_assert(impl::OffsetOf<&CharArray::c6> == 6);
|
||||
static_assert(impl::OffsetOf<&CharArray::c7> == 7);
|
||||
|
||||
constexpr CharArray TestCharArray = {};
|
||||
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c0, TestCharArray.c0));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c0, std::addressof(TestCharArray.c0)));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c1, TestCharArray.c1));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c1, std::addressof(TestCharArray.c1)));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c2, TestCharArray.c2));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c2, std::addressof(TestCharArray.c2)));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c3, TestCharArray.c3));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c3, std::addressof(TestCharArray.c3)));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c4, TestCharArray.c4));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c4, std::addressof(TestCharArray.c4)));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c5, TestCharArray.c5));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c5, std::addressof(TestCharArray.c5)));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c6, TestCharArray.c6));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c6, std::addressof(TestCharArray.c6)));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c7, TestCharArray.c7));
|
||||
static_assert(std::addressof(TestCharArray) == GET_PARENT_PTR(CharArray, c7, std::addressof(TestCharArray.c7)));
|
||||
|
||||
}
|
||||
#define GET_PARENT_REF(parent, member, _arg) (::ams::util::GetParentReference<&parent::member, parent>(_arg))
|
||||
|
||||
}
|
||||
|
|
|
@ -26,32 +26,32 @@ namespace ams::util {
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
static constexpr ALWAYS_INLINE T *GetPointer(TypedStorage<T> &ts) {
|
||||
return static_cast<T *>(static_cast<void *>(std::addressof(ts._storage)));
|
||||
static ALWAYS_INLINE T *GetPointer(TypedStorage<T> &ts) {
|
||||
return std::launder(reinterpret_cast<T *>(std::addressof(ts._storage)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr ALWAYS_INLINE const T *GetPointer(const TypedStorage<T> &ts) {
|
||||
return static_cast<const T *>(static_cast<const void *>(std::addressof(ts._storage)));
|
||||
static ALWAYS_INLINE const T *GetPointer(const TypedStorage<T> &ts) {
|
||||
return std::launder(reinterpret_cast<const T *>(std::addressof(ts._storage)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr ALWAYS_INLINE T &GetReference(TypedStorage<T> &ts) {
|
||||
static ALWAYS_INLINE T &GetReference(TypedStorage<T> &ts) {
|
||||
return *GetPointer(ts);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr ALWAYS_INLINE const T &GetReference(const TypedStorage<T> &ts) {
|
||||
static ALWAYS_INLINE const T &GetReference(const TypedStorage<T> &ts) {
|
||||
return *GetPointer(ts);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static constexpr ALWAYS_INLINE T *ConstructAt(TypedStorage<T> &ts, Args &&... args) {
|
||||
return std::construct_at(GetPointer(ts), std::forward<Args>(args)...);
|
||||
static ALWAYS_INLINE T *ConstructAt(TypedStorage<T> &ts, Args &&... args) {
|
||||
return std::construct_at(reinterpret_cast<T *>(std::addressof(ts._storage)), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr ALWAYS_INLINE void DestroyAt(TypedStorage<T> &ts) {
|
||||
static ALWAYS_INLINE void DestroyAt(TypedStorage<T> &ts) {
|
||||
return std::destroy_at(GetPointer(ts));
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ namespace ams::util {
|
|||
bool m_active;
|
||||
public:
|
||||
template<typename... Args>
|
||||
constexpr ALWAYS_INLINE TypedStorageGuard(TypedStorage<T> &ts, Args &&... args) : m_ts(ts), m_active(true) {
|
||||
ALWAYS_INLINE TypedStorageGuard(TypedStorage<T> &ts, Args &&... args) : m_ts(ts), m_active(true) {
|
||||
ConstructAt(m_ts, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ namespace ams::util {
|
|||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static constexpr ALWAYS_INLINE impl::TypedStorageGuard<T> ConstructAtGuarded(TypedStorage<T> &ts, Args &&... args) {
|
||||
static ALWAYS_INLINE impl::TypedStorageGuard<T> ConstructAtGuarded(TypedStorage<T> &ts, Args &&... args) {
|
||||
return impl::TypedStorageGuard<T>(ts, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue