Сообщение Re: offsetof() без UB от 25.03.2025 10:38
Изменено 25.03.2025 11:23 rg45
LS>Я сейчас портирую большую кучу кода из конца 90-х, в которой очень многое завязано на offsetof() на не-POD типах. Код изначально для MSVC 98.
LS>Согласно стандарту это UB, но ведь есть законы, а есть правоприменительная практика.
LS>Как на практике обстоят дела? Мои целевые компиляторы это современный MSVC и clang под x86_64 и ARM.
Полез в стандарты и обнаружил, что требования к offsetof изменились.
До C++14 включительно использование offsetof с типами, отличными от standard layout квалифицировалось как UB:
The macro offsetof(type, member-designator) accepts a restricted set of type arguments in this International Standard. If type is not a standard-layout class (Clause 9), the results are undefined.
Начиная с C++17, это определяется как "conditionally-supported":
Use of the offsetof macro with a type other than a standard-layout class (Clause 12) is conditionally-supported (187).
---
187) Note that offsetof is required to work as specified even if unary operator& is overloaded for any of the types involved.
3.7
conditionally-supported [defns.cond.supp]
program construct that an implementation is not required to support [ Note: Each implementation documents all conditionally-supported constructs that it does not support. — end note ]
LS>Я сейчас портирую большую кучу кода из конца 90-х, в которой очень многое завязано на offsetof() на не-POD типах. Код изначально для MSVC 98.
LS>Согласно стандарту это UB, но ведь есть законы, а есть правоприменительная практика.
LS>Как на практике обстоят дела? Мои целевые компиляторы это современный MSVC и clang под x86_64 и ARM.
Полез в стандарты и обнаружил, что требования к offsetof изменились.
До C++14 включительно использование offsetof с типами, отличными от standard layout квалифицировалось как UB:
The macro offsetof(type, member-designator) accepts a restricted set of type arguments in this International Standard. If type is not a standard-layout class (Clause 9), the results are undefined.
Начиная с C++17, это определяется как "conditionally-supported":
Use of the offsetof macro with a type other than a standard-layout class (Clause 12) is conditionally-supported (187).
---
187) Note that offsetof is required to work as specified even if unary operator& is overloaded for any of the types involved.
3.7
conditionally-supported [defns.cond.supp]
program construct that an implementation is not required to support [ Note: Each implementation documents all conditionally-supported constructs that it does not support. — end note ]
Получается, что уже не UB. Но пользоваться этим можно только в том случае, если такая возможность обозначена в документации к компилятору. И с портабельностью можно попрощаться.