I previously used this to extract a size_t offset to a member of an object based on passing in the member object pointer.
template <typename T, typename U>
constexpr size_t memberOffset(U T::*member)
{
return (char*)&((T*)nullptr->*member) - (char*)nullptr;
}
struct Point{float x,y,z; };
memberOffset(&Point::y) == 4;
I used this as part of a reflection library to hash two types for compatibility. IE
struct Point{ float x,y,z;};
struct Point3d{float x,y,z;};
For serialization purposes the above two are the same and thus with the additional metadata of the type of x,y,z and the names of the members, I can generate a hash for the two types and check compatibility.
With gcc 9 the memberOffset function is now broken due to UB in a constexpr function. I'm looking for constexpr version of this that doesn't invoke UB or a gcc 9 workaround. The __builtin__offsetof doesn't take the same syntax and thus would not be compatible with what I already have developed.
[Edit]
To add clarity, this is used as part of an extension to a meta programming library that I wrote. The majority of the code has to do with generating serialization and binding code for structs using member object pointers, etc. Thus the library is often used as follows:
template<>
struct MetaData<Point3d>{
auto getMember(integral_constant<0>){ return makeMemberObjectPointer("x", &Point3d::x); }
auto getMember(integral_constant<1>){ return makeMemberObjectPointer("y", &Point3d::y); }
auto getMember(integral_constant<2>){ return makeMemberObjectPointer("z", &Point3d::z); }
};
Since the code already uses member object pointers everywhere, I wanted to be able to use what exists to extract the offset, instead of having to update each callsite with an additional call to offsetof.