Сохранение совместимости ABI с C ++ 11 `enum class` - PullRequest
0 голосов
/ 19 ноября 2018

Это почти тот же вопрос, что и Разве добавление перечислителей в enum нарушает ABI? , но с enum class, введенным C ++ 11.

Для того, что я понимаю под эта страница Я могу просто иметь стабильный ABI, определив базовый тип для моего перечисления:

enum class Foo : uint32_t
{
    x, y, z
}

Я бы сказал, что это прекрасно работает, например, что-то вроде

enum class Foo : uint8_t { x = 257 }

Не компилируется.Это означает, что компилятор больше не изменяет размер моего перечисления в режиме без вывода сообщений, поэтому я не в конечном итоге нарушаю двоичную совместимость.

Я прав?

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

OP здесь.

Я узнал, и я думаю, что было бы уместно упомянуть, что C ++ 11 имеет этот хороший std :: under_type .

Я думаю, что это может быть использовано вместе со is_same и статическими утверждениями , чтобы создать некоторую защиту от неожиданных изменений ABI из-за перечислений.

Я думаю (ноЯ не пробовал), что это особенно актуально, если кто-то работает с какой-то библиотекой, а в уже существующем перечислителе не указан базовый тип.

0 голосов
/ 20 ноября 2018

Я полагаю принятый ответ на указанный вопрос отвечает на большинство вопросов, касающихся совместимости ABI.Я мог бы повторить это здесь, но я не вижу большой ценности там.

Чтобы ответить на ваш конкретный вопрос о перечислениях C ++ 11, ваш пример:

enum class Foo : uint8_t { x = 257 }

плохо сформирован, так какэто требует сужающего преобразования, реализация должна обеспечивать диагностику, но она может компилироваться, если реализация только предупреждает, например.Как вы и просили, компилятор не будет молча менять размер базового типа.

Это видно из черновика стандарта C ++ dcl.enump5 :

Каждое перечисление определяет тип, который отличается от всех других типов.Каждое перечисление также имеет базовый тип.Базовый тип может быть явно указан с помощью enum-base.Для перечисляемого типа с ограниченным диапазоном базовым типом является int, если он не указан явно.В обоих этих случаях базовый тип считается фиксированным.После закрывающей скобки спецификатора перечисления каждый перечислитель имеет тип своего перечисления. Если базовый тип является фиксированным, тип каждого перечислителя перед закрывающей скобкой является базовым типом, а константное выражение в определении перечислителя должно быть преобразованным константным выражением базового типа .Если базовый тип не является фиксированным, тип каждого перечислителя перед закрывающей скобкой определяется следующим образом: ...

и преобразованное константное выражение запретить сужающее преобразование из expr.constp5 :

Преобразованное константное выражение типа T является выражением, неявно преобразованным в тип T, где преобразованное выражение является константным выражением, а последовательность неявного преобразования содержиттолько

...

  • интегральные преобразования , кроме сужающих преобразований ,

...

...