Могу ли я использовать значения класса enum в качестве аргументов для функций varargs?

#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.