Dave Mateer
Dave Mateer

Reputation: 17956

Using C flag enums in C++

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?

Upvotes: 13

Views: 3370

Answers (5)

mail2subhajit
mail2subhajit

Reputation: 1150

CEnumType A;

A = (CEnumType)(A | C_ENUM_VALUE_APPLE);

You can use it this way too.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727047

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.

Upvotes: 23

inspector-g
inspector-g

Reputation: 4176

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));

Upvotes: 5

Adam Rosenfield
Adam Rosenfield

Reputation: 400642

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

Upvotes: 6

Variable Length Coder
Variable Length Coder

Reputation: 8116

By or-ing two enum values, you're creating an invalid value (0x3 is not in enum CEnumType). Enumerations are not bitfields. If you want a bitfield, define one.

You can cast the value if you want to force it through, but that may surprise some code that is counting on only being able to get the enumerated values.

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

Upvotes: 0

Related Questions