Problem
The reflection core derives member offsets in two fragile ways:
OffsetFromStart (include/reflection.h:97) memcpys the raw bytes of a pointer-to-member and reinterprets the leading sizeof(size_t) bytes as a byte offset.
DEFINE_MEMBER (include/reflection.h) uses offsetof(struct REFLECTABLE, R), and members are accessed via reinterpret_cast at the computed offset (GetMemberAddress).
Impact
This works for simple standard-layout structs under the common Itanium / MSVC ABIs, but:
- The byte representation of a pointer-to-member is implementation-defined; for multiple or virtual inheritance the leading-bytes-as-offset assumption is wrong.
offsetof on a non-standard-layout type is conditionally-supported / undefined.
So the whole introspection mechanism rests on assumptions the standard doesn't guarantee, and would break (silently, with wrong offsets) for records that aren't simple standard-layout aggregates.
Suggested direction
Document the constraint explicitly (reflectable records must be standard-layout, no inheritance) and enforce it at registration with static_assert(std::is_standard_layout_v<T>), so a violating type fails to compile instead of misbehaving at runtime.
Problem
The reflection core derives member offsets in two fragile ways:
OffsetFromStart(include/reflection.h:97)memcpys the raw bytes of a pointer-to-member and reinterprets the leadingsizeof(size_t)bytes as a byte offset.DEFINE_MEMBER(include/reflection.h) usesoffsetof(struct REFLECTABLE, R), and members are accessed viareinterpret_castat the computed offset (GetMemberAddress).Impact
This works for simple standard-layout structs under the common Itanium / MSVC ABIs, but:
offsetofon a non-standard-layout type is conditionally-supported / undefined.So the whole introspection mechanism rests on assumptions the standard doesn't guarantee, and would break (silently, with wrong offsets) for records that aren't simple standard-layout aggregates.
Suggested direction
Document the constraint explicitly (reflectable records must be standard-layout, no inheritance) and enforce it at registration with
static_assert(std::is_standard_layout_v<T>), so a violating type fails to compile instead of misbehaving at runtime.