diff --git a/libraries/libvapours/include/vapours/util/util_parent_of_member.hpp b/libraries/libvapours/include/vapours/util/util_parent_of_member.hpp index 9276b0613..a1600680d 100644 --- a/libraries/libvapours/include/vapours/util/util_parent_of_member.hpp +++ b/libraries/libvapours/include/vapours/util/util_parent_of_member.hpp @@ -23,83 +23,101 @@ namespace ams::util { namespace impl { - template - struct OffsetOfUnionHolder { - template - union UnionImpl { - using PaddingMember = char; - static constexpr size_t GetOffset() { return Offset; } + #define AMS_UTIL_OFFSET_OF_STANDARD_COMPLIANT 0 - #pragma pack(push, 1) - struct { - PaddingMember padding[Offset]; - MemberType members[(sizeof(ParentType) / sizeof(MemberType)) + 1]; - } data; - #pragma pack(pop) - UnionImpl next_union; + #if AMS_UTIL_OFFSET_OF_STANDARD_COMPLIANT + + template + struct OffsetOfUnionHolder { + template + union UnionImpl { + using PaddingMember = char; + static constexpr size_t GetOffset() { return Offset; } + + #pragma pack(push, 1) + struct { + PaddingMember padding[Offset]; + MemberType members[(sizeof(ParentType) / sizeof(MemberType)) + 1]; + } data; + #pragma pack(pop) + UnionImpl next_union; + }; + + template + union UnionImpl { + static constexpr size_t GetOffset() { return 0; } + + struct { + MemberType members[(sizeof(ParentType) / sizeof(MemberType)) + 1]; + } data; + UnionImpl next_union; + }; + + template + union UnionImpl { /* Empty ... */ }; }; template - union UnionImpl { - static constexpr size_t GetOffset() { return 0; } + struct OffsetOfCalculator { + using UnionHolder = typename OffsetOfUnionHolder::template UnionImpl; + union Union { + char c; + UnionHolder first_union; + TYPED_STORAGE(ParentType) parent; - struct { - MemberType members[(sizeof(ParentType) / sizeof(MemberType)) + 1]; - } data; - UnionImpl next_union; - }; + /* This coerces the active member to be c. */ + constexpr Union() : c() { /* ... */ } + }; + static constexpr Union U = {}; - template - union UnionImpl { /* Empty ... */ }; - }; - - template - struct OffsetOfCalculator { - using UnionHolder = typename OffsetOfUnionHolder::template UnionImpl; - union Union { - char c; - UnionHolder first_union; - TYPED_STORAGE(ParentType) parent; - - /* This coerces the active member to be c. */ - constexpr Union() : c() { /* ... */ } - }; - static constexpr Union U = {}; - - static constexpr const MemberType *GetNextAddress(const MemberType *start, const MemberType *target) { - while (start < target) { - start++; - } - return start; - } - - static constexpr std::ptrdiff_t GetDifference(const MemberType *start, const MemberType *target) { - return (target - start) * sizeof(MemberType); - } - - template - 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 start = std::addressof(cur_union.data.members[0]); - const auto next = GetNextAddress(start, target); - - if (next != target) { - if constexpr (Offset < sizeof(MemberType) - 1) { - return OffsetOfImpl(member, cur_union.next_union); - } else { - __builtin_unreachable(); + static constexpr const MemberType *GetNextAddress(const MemberType *start, const MemberType *target) { + while (start < target) { + start++; } + return start; } - return (next - start) * sizeof(MemberType) + Offset; - } + static constexpr std::ptrdiff_t GetDifference(const MemberType *start, const MemberType *target) { + return (target - start) * sizeof(MemberType); + } + + template + 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 start = std::addressof(cur_union.data.members[0]); + const auto next = GetNextAddress(start, target); + + if (next != target) { + if constexpr (Offset < sizeof(MemberType) - 1) { + return OffsetOfImpl(member, cur_union.next_union); + } else { + __builtin_unreachable(); + } + } + + return (next - start) * sizeof(MemberType) + Offset; + } - static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::*member) { - return OffsetOfImpl(member, U.first_union); - } - }; + static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::*member) { + return OffsetOfImpl(member, U.first_union); + } + }; + + #else + + template + struct OffsetOfCalculator { + static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::*member) { + constexpr TYPED_STORAGE(ParentType) Holder = {}; + const auto *parent = GetPointer(Holder); + const auto *target = std::addressof(parent->*member); + return static_cast(static_cast(target)) - static_cast(static_cast(parent)); + } + }; + + #endif template struct GetMemberPointerTraits;