Проверка неактивных членов профсоюза, общая начальная последовательность - PullRequest
0 голосов
/ 05 февраля 2019

Этот вопрос основан на этом

Рассмотрим следующее:

struct Hdr { int type; };
struct A { Hdr h; };
union Big {
   Hdr h;
   A a;
};

и предположим, что для Big big мы знаем, чтоbig.a является активным членом союза.Является ли доступ к big.h.type неопределенным поведением ?

Я думаю, что это действительно UB, основываясь на:

class.union

... [Примечание. Для упрощения использования объединений делается одна специальная гарантия: если объединение стандартных макетов содержит несколько структур стандартных макетов, которые имеют общую начальную последовательность ([class.mem])и если нестатический член данных объекта этого типа объединения стандартной компоновки активен и является одной из структур стандартной компоновки, то разрешается проверять общую начальную последовательность любого из элементов структуры стандартной компоновки;см. [class.mem].- конец примечания]

У нас есть стандартное объединение макетов, которое имеет стандартные элементы-члены макета, но, как вы понимаете, общая начальная последовательность для Hdr и A пустахотя первый элемент данных A имеет тип Hdr.

Прав ли я в том, что это UB?если нет, то какую точку общей начальной последовательности я неправильно понял, чтобы определить доступ big.h.type?

1 Ответ

0 голосов
/ 05 февраля 2019

Я не вижу ошибок в вашей интерпретации.

Согласно вашей цитате, это хорошо определено, только если 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 ++.

...