Использование флагов C в C ++

У меня есть 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));