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?

Reply via email to