Just before this question is being dismissed for being a duplicate, most (if not all) questions have accepted-answers with outdated / undefined behavior solutions.
Is there a way to get at, compile-time, the offset of a pointer to member data that:
nullptr
things)gcc trunk
in compiler explorer)offsetof
(or similarly, like the proposed code do).With the trunk version of GCC, the following trick (hack) does not work:
#include <cstdint>
#include <cstddef>
namespace detail
{
// The union stuff is for CLang to avoid creating warnings
template<typename T, auto MPtr>
struct offsetof_ptr_helper
{
union helper_t { int i = 0; T value; };
static constexpr helper_t v = {};
static constexpr size_t sz = sizeof
(uint8_t[
(uint8_t *)&(v.value.*MPtr) -
(uint8_t *)&v.value
]);
};
}
template<typename T, auto MPtr>
static constexpr size_t offsetof_ptr()
{
return detail::offsetofptr_helper<T, MPtr>::sz;
}
size_t f()
{
struct X { char c[10]; int a; };
return offsetof_ptr<X, &X::a>();
}
To be clear, this is a hack using C++98 features and this is not a real surprise that its support is being removed by latest compilers. It works on clang (using the -std=gnu++17
flag) and gcc (including/up-to g++ 7.3 using the flag -std=c++17
).
If you jump to the definition of offsetof
in VS, it gives you this:
#define offsetof(s,m) ((::size_t)&reinterpret_cast<char const volatile&>((((s*)0)->m)))
Modified a bit to match your problem:
template<typename T, auto MPtr>
static constexpr size_t offsetof_ptr()
{
return ((::size_t) & reinterpret_cast<char const volatile&>((((T*)0)->*MPtr)));
}
size_t f()
{
struct X { char c[10]; int a; };
return offsetof_ptr<X, &X::a>();
}
This compiles on GCC and MSVC. (It requires C++17 because of the template auto parameter.)
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