#c #c 11 #enums #enum-class
#c #c 11 #перечисления #enum-class
Вопрос:
C 11 добавляет классы enum, которые являются перечислениями с более строгой типизацией — значения классов enum не будут неявно преобразовываться в значения других классов enum или целых чисел, а прямые объявления разрешены в силу явного спецификатора размера.
Возможно ли передавать значения таких перечислений функциям varargs и оставаться в рамках поведения, определенного стандартами? В рамках поведения, определяемого реализацией?
Ответ №1:
Да, вы можете. 5.2.2 / 7 явно разрешает аргументы любого типа перечисления. Значения перечисления, не включенные в список, являются целочисленными, а перечисления с областью действия ( enum class
те) — нет.
Конечно, вы все равно должны быть осторожны при реализации функции.
Комментарии:
1. 1 для ссылки 5.2.2 / 7 — я почти уверен, что если
enum class
бы это было исключено, там было бы примечание.2. Интересно, является ли UB использовать базовый тип с
va_arg
, когда выбранный аргумент был значением перечисления с ограниченной областью? Похоже, это так.3. @Johannes: если это вызывает UB, то разве это не противоречит цели указания базового типа в первую очередь (представление идентичного значения)?
4. @Johannes 18.10 / 3 говорит, что все в порядке, если типы параметров и аргументов совместимы, но, к сожалению, «совместимые типы», похоже, относятся к C, а не к C . Понятие. Я уверен, что это сработает, но я сильно подозреваю, что технически это UB.
Ответ №2:
Я думаю, что ответ заключается в том, что это может быть безопасно:
VA_ARGS
требуется, чтобы аргументы были POD, это не изменилось, насколько я знаю.
Я не вижу никаких причин, почему:
enum class foo { bar=1 };
Однако это не соответствует требованиям к POD-ness.
Ответ №3:
Поскольку вы отбрасываете некоторую информацию о типе при использовании varargs (вот почему это настоятельно не рекомендуется для типов, отличных от POD), вы просто получите базовый тип на другом конце вашего varargs с помощью функции. Значение по умолчанию равно int
, но вы можете изменить это (например enum class MyEnum : char { ... };
)
Исправлено: varargs действительно не удаляет всю информацию о типе, и если вы используете тип данных POD, вы должны быть в полной безопасности.
Комментарии:
1. На самом деле это не то, что говорится в стандарте. Не вся информация о типе отбрасывается.
2.
int
значение по умолчанию верно только для ограниченных перечислений (которые, в конце концов, обсуждаются здесь).3. @AlanStokes: Спасибо. Я попытался изменить свое предыдущее утверждение bold.