Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using C flag enums in C++

Tags:

c++

c

enums

I have a C API that defines an enum like so:

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;

There is a method that uses the enum, defined as:

void do_something(CEnumType types);

In C, you can call something like:

do_something(C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA);

However, if you try to call it this way in C++ (Linux, g++ compiler), you get an error, invalid conversion from ‘int’ to ‘CEnumType’.

What is the correct way to use this C API from my C++ application?

like image 392
Dave Mateer Avatar asked Apr 26 '12 18:04

Dave Mateer


4 Answers

You need to cast ints to enums in C++, but you can hide the cast in a custom OR operator:

CEnumType operator|(CEnumType lhs, CEnumType rhs) {
    return (CEnumType) ((int)lhs| (int)rhs);
}

With this operator in place, you can write your original

do_something(C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA);

and it will compile and run without a problem.

like image 118
Sergey Kalinichenko Avatar answered Nov 08 '22 05:11

Sergey Kalinichenko


C++ has stricter rules than C regarding enums. You'll need to cast the value to the enumeration type when calling:

do_something((CEnumType)(C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA));

Alternatively, you can writer a wrapper function that takes an int to do the cast for you, if you want to avoid writing the cast every time you call it:

void do_something_wrapper(int types)
{
    do_something((CEnumType)types);
}
...
do_something_wrapper(C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA);

Though I don't know if I want to see what you get when you cross an apple with a banana...

like image 34
Adam Rosenfield Avatar answered Nov 08 '22 04:11

Adam Rosenfield


In the case of bitwise operations, the expression evaluates to a primitive type, i.e. int, long, etc. However, your function takes a non-primitive type (CEnumType). The only way I know of to bypass this is to cast the expression. For example:

do_something((CEnumType) (C_ENUM_VALUE_APPLE | C_ENUM_VALUE_BANANA));
like image 5
inspector-g Avatar answered Nov 08 '22 04:11

inspector-g


CEnumType A;

A = (CEnumType)(A | C_ENUM_VALUE_APPLE);

You can use it this way too.

like image 1
mail2subhajit Avatar answered Nov 08 '22 06:11

mail2subhajit