The following construct in main()
retrieves a class member's offset
at runtime:
struct Base
{
virtual ~Base() = default;
};
struct Cls : public virtual Base
{
int a, b;
};
int main()
{
int Cls::* ptr = &Cls::a;
unsigned long offset = *reinterpret_cast<unsigned long*>(&ptr);
}
The class layout is determined at compile time and doesn't change. So, it would be beneficial to make this a constexpr
.
Unfortunately, the above assignment requires an lvalue.
How can I get the same result using a constexpr
?
CodePudding user response:
Your class is not standard-layout. There is no way to obtain an offset to a member of a non-standard-layout class without undefined behavior (and therefore certainly not in a compile-time context) that is guaranteed by the standard.
Your approach is definitively UB per standard, even in a standard-layout class. It relies on very specific implementation details, assuming it works in the first place. (I haven't tested it.)
Since C 17 use of the offsetof
macro is conditionally-supported (also in a compile-time context) for non-standard-layout classes. If the compiler does not support this, then what you want to do is impossible (except maybe via other compiler extensions).
CodePudding user response:
Found the solution myself:
template<class T> constexpr unsigned long Offset(T ptr)
{
return *reinterpret_cast<unsigned long*>(&ptr);
}