C++ 11 и выше накладывает шизанутые ограничения на offsetof: http://en.cppreference.com/w/cpp/concept/StandardLayoutType
Вкратце:
- смешал любые из двух private/protected/public => non-standard layout
struct non_std { int x; private: int y; };
- виртуальная функция и/или виртуальный базовый класс => non-standard layout
- используешь ссылки => non-standard layout
struct non_std { int x; int &y; };
- все нестатические поля должны быть standard layout
- еще портянка про C++14 и о том, как было плёхо без него
Внимание, вопрос: зачем все это? Ежу понятно, что компилятор каждую структуру располагает в памяти строго фиксированным образом, который зависит лишь от версии компилятора и параметров компиляции (в т. ч. pragma align). То есть, все поля любого класса вне зависимости от его «наполнения» имеют строго определенные оффсеты, которыми можно свободно манипулировать (да, я люблю интрузивные контейнеры из sys/queue.h
). Зачем это запрещать?
И не только я считаю, что это полное дерьмо (в головах разработчиков стандарта ofc), порождающее чудовищ: https://gist.github.com/graphitemaster/494f21190bb2c63c5516
Как же быть? Мой ответ:
#define coo1_offsetof(type, field) ((uintptr_t)&((type*)(void*)(uintptr_t)1)->field - 1u)
Удалось ли мне утереть нос секте UB-шников, которые в наши дни пишут компиляторы?