У меня есть API C, который определяет перечисление, например:
typedef enum { C_ENUM_VALUE_NONE = 0, C_ENUM_VALUE_APPLE = (1 << 0), C_ENUM_VALUE_BANANA = (1 << 1), C_ENUM_VALUE_COCONUT = (1 << 2), // etc. C_ENUM_VALUE_ANY = ~0 } CEnumType;
Существует метод, который использует перечисление, определяемое как:
void do_something(CEnumType types);
В C вы можете вызвать что-то вроде:
do_something(C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA);
Однако, если вы попытаетесь назвать его таким образом в C ++ (Linux, g ++ компилятор), вы получите сообщение об ошибке, недействительное преобразование из ‘int’ в ‘CEnumType’ .
Каков правильный способ использования этого C API из моего приложения на C ++?
Вам нужно использовать int
s для перечислений на C ++, но вы можете скрыть приведение в пользовательском операторе OR
:
CEnumType operator|(CEnumType lhs, CEnumType rhs) { return (CEnumType) ((int)lhs| (int)rhs); }
С помощью этого оператора вы можете написать свой оригинал
do_something(C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA);
и он будет компилироваться и запускаться без проблем.
C ++ имеет более строгие правила, чем C в отношении перечислений. При вызове необходимо указать значение для типа enums:
do_something((CEnumType)(C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA));
Кроме того, вы можете написать функцию обертки, которая принимает int
чтобы сделать бросок для вас, если вы хотите избежать написания акта каждый раз, когда вы его вызываете:
void do_something_wrapper(int types) { do_something((CEnumType)types); } ... do_something_wrapper(C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA);
Хотя я не знаю, хочу ли я видеть, что вы получаете, когда вы пересекаете яблоко с бананом …
В случае побитовых операций выражение оценивается как примитивный тип, т. int
, long
и т. Д. Однако ваша функция принимает не примитивный тип ( CEnumType
). Единственный способ, которым я знаю обходить это, – это выразить выражение. Например:
do_something((CEnumType) (C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA));
CEnumType A;
A = (CEnumType) (A | C_ENUM_VALUE_APPLE);
Вы можете использовать его так же.
Посредством двух значений enum вы создаете недопустимое значение (0x3 не находится в enum CEnumType). Перечисления не являются битовыми полями. Если вы хотите бит-поле, определите его.
Вы можете указать значение, если хотите его прогнать, но это может удивить некоторый код, который рассчитывает только на то, чтобы получить перечисленные значения.
do_something((CEnumType)(C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA));