Информация об изменениях

Сообщение Re: offsetof() без UB от 25.03.2025 10:38

Изменено 25.03.2025 11:23 rg45

Re: offsetof() без UB
Здравствуйте, LuciferSaratov, Вы писали:

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 ]

Re: offsetof() без UB
Здравствуйте, LuciferSaratov, Вы писали:

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. Но пользоваться этим можно только в том случае, если такая возможность обозначена в документации к компилятору. И с портабельностью можно попрощаться.