Well... in C++11, you actually can compute such offsets right with regular C++ facilities (ie, without delegating to a particular compiler intrinsic).
template <typename T, typename U>
constexpr std::size_t func(T const& t, U T::* a) {
return (char const*)&t - (char const*)&(t.*a);
}
However this relies on t
being a reference to a constexpr
instance here, which might not be applicable to all classes. It does not forbid T
from having a virtual
method though, nor even a constructor, as long as it is a constexpr
constructor.
Still, this is quite a hindrance. In unevaluated contexts we could actually use std::declval<T>()
to simulate having an object; while having none. This poses no specific requirements on the constructor of an object, therefore. On the other hand, the values we can extract from such context are few... and they do pose issues with current compilers, too... Well, let's fake it!
template <typename T, typename U>
constexpr std::size_t offsetof_impl(T const* t, U T::* a) {
return (char const*)t - (char const*)&(t->*a) >= 0 ?
(char const*)t - (char const*)&(t->*a) :
(char const*)&(t->*a) - (char const*)t;
}
#define offsetof(Type_, Attr_) \
offsetof_impl((Type_ const*)nullptr, &Type_::Attr_)
The only issue I foresee is with virtual
inheritance, because of its runtime placement of the base object. I would be glad to be presented with other defects, if there are.
reinterpret_cast
'ing it tochar *
) to get to the member? If so, wouldn't simple subtraction tell you? – Ordinateoffsetof(A, i)
if that were defined for such types. Check your compiler documentation to see if it is. – Burressoffsetof
would fail? – Drachm