I would like to get the offset of a standard layout member variable when provided with a poiner to that variable. I cannot use offsetof
since I have a pointer and not a name. The current code I have looks something like this, and I am wondering if there is a standards compliant way to get rid of the dummy
variable.
template<class T>
struct {
ptrdiff_t get_offset( int (T::*mem) )
{
T dummy;
return reinterpret_cast<char*>(&(dummy.*mem))
- reinterpret_cast<char*>(&dummy);
}
};
This function should only be callable with int
member variable points (this is intentional).
I am quite certain that the compiler doesn't actually create the dummy
variable but it'd still be nice if I could get rid of it. I can't use a null pointer since dereferencing null is not defined (though it probably works on all common compilers). A C++03 solution would be good, or a C++11 solution is also of interest (but not usable by me now).
NOTE: I'm already aware this is only standards compliant is T is a standard layout type.
How about:
template<class T>
struct {
ptrdiff_t get_offset( int (T::*mem) )
{
union {
int used;
T unused;
} dummy;
return reinterpret_cast<char*>(&(dummy.unused.*mem))
- reinterpret_cast<char*>(&dummy.unused);
}
};
The address of a union member doesn't depend on the union member being constructed. Works already in C++03, but then only for PODs.
I'm afraid that no standard-compliant solution which satisfies OP requirements exists.
I can give a couple of non-compliant ones.
template<class T>
size_t get_offset( int (T::*mem) )
{
return reinterpret_cast<char*>(&(((T*)nullptr)->*mem))-reinterpret_cast<char*>(nullptr);
}
It's funny, but the following works in VC2010, making use of offsetof
being a macro.
template<class T>
size_t get_offset( int (T::*mem) )
{
return offsetof(T, *mem);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With