constexpr: resign ourselves to gcc dropping void -> T support

This commit is contained in:
Michael Scire 2021-10-17 02:39:16 -07:00
parent 96d3187f3e
commit ad4c794aea
16 changed files with 201 additions and 290 deletions

View file

@ -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());
}

View file

@ -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());
}

View file

@ -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());
}

View file

@ -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());
}

View file

@ -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() { /* ... */ }

View file

@ -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());
}

View file

@ -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() { /* ... */ }

View file

@ -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(),

View file

@ -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);
}

View file

@ -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;

View file

@ -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:

View file

@ -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);
}
};

View file

@ -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));
}
};

View file

@ -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));
}
};

View file

@ -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))
}

View file

@ -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)...);
}