1

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.

Daniel Moodie
  • 357
  • 1
  • 10
  • 2
    Why not use [`offsetof`](https://en.cppreference.com/w/cpp/types/offsetof)? There is no well-defined way to reproduce its behavior in C++. – Miles Budnek Feb 05 '21 at 14:24
  • I doubt this is possible. As far as I can tell from re-skimming the standard, converting a member pointer to anything other than a null pointer or a derived class member pointer is undefined behavior. There's no information to be extracted here. I'm not sure why this function was used over standard machinery like [`offsetof`](https://en.cppreference.com/w/cpp/types/offsetof). – Brian61354270 Feb 05 '21 at 14:25
  • IIRC `(char*)&((T*)nullptr->*member) - (char*)nullptr;` has been UB for ever - subtracting 2 pointers which don't point into the same object. Which is why `offsetof` exists as it needs compiler help to be legal. – Richard Critten Feb 05 '21 at 14:46

0 Answers0