https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89331
--- Comment #7 from Stas Sergeev <stsp at users dot sourceforge.net> --- (In reply to Jason Merrill from comment #4) > But when we're in the middle of the class definition we don't know yet > whether it's standard-layout, so we can't answer yet. A compiler is allowed > to reorder fields of a non-standard-layout class. Thanks, that clears some things for me. I definitely am not going to turn this ticket into a forum, but I am still puzzled why the below works (on gcc at least, not on clang): --- #include <cstddef> #include <iostream> class L {}; template <typename T, L (T::*M)[0]> struct offset_of { constexpr operator size_t() const { return (std::uintptr_t)&(((T*)nullptr)->*M); } }; template <typename T, L (T::*M)[0]> struct B { char aa; static const int off = offset_of<T, M>(); }; struct A { char a; L _mark[0]; B<A, &A::_mark> b; }; int main() { A a; std::cout << "size " << sizeof(A) << " off " << a.b.off << std::endl; return 0; } --- Here I do 2 emulation tricks. I use address-of on the zero-sized mark to emulate offsetof() in the not yet fully defined class. And I use reinterpret cast in a constexpr to emulate offsetof() that doesn't want to work with the template arguments for some reason. This works perfectly on gcc (I filled a bug report to clang). So if the emulation works, why doesn't the original? Are there any possibility to somehow extend __builtin_offsetof() to cover either of those 2 cases where I currently have to emulate it? While I understand the problem you described, why does the above example avoids it?