Offset of a member from a member object pointer in gcc 9

211 views Asked by At

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.

0

There are 0 answers