Я не вижу ошибок в вашей интерпретации.
Согласно вашей цитате, это хорошо определено, только если A
и Hdr
имеют общую начальную последовательность, которая включает Hdr::type
.
Чтобы процитировать правило, определяющее общую начальную последовательность:
[class.mem] Общая начальная последовательность двух типов структуры стандартного макета ([class.prop]) является самой длинной последовательностьюнестатические элементы данных и битовые поля в порядке объявления, начиная с первого такого объекта в каждой из структур, так что соответствующие объекты имеют типы, совместимые с макетом ...
Итак, первыйчлены A
и Hdr
являются общими, если они - то есть int
и Hdr
- являются типами, совместимыми с макетом.Это указано в
[basic.types] Два типа cv1 T1 и cv2 T2 являются типами, совместимыми с макетом, если T1 и T2 имеют одинаковый тип (они не одного типа) , совместимые с макетом перечисления (они не являются перечислениями) , или совместимые с макетом типы классов стандартного макета (только один из них является типом класса) .
Как ни применимо, int
и Hdr
не совместимы с макетом, и поэтому общая начальная последовательность A
и Hdr
пуста, и, следовательно, нет члена, для которого указана специальная гарантияприменяется.
Вы можете использовать оболочку, чтобы обойти тонкость правила:
union Big {
struct {
Hdr h;
} w;
A a;
} big;
Здесь доступ к big.w.h.type
будет хорошо определен, даже если big.a
активный.PS Анонимная структура была бы хороша здесь, чтобы сделать обертку невидимой.К сожалению, они плохо сформированы в стандарте C ++.