A strange thing about enums

Hello.

Yesterday I started to compile a project, a BHO for Windows 7. The BHO requires some user input so I decided to use Task dialogs.

One of the things I did was to port the TDF_* and TDCBF_* constants into a new enum under my namespace. Typical typedef รก la Windows SDK: typedef enum _MyEnum{ ... } MyEnum;.

The TDF_ constants are the flags and therefore are combined using bitwise operations.

My CDialog class has bool properties that represent several of these flags, like Use Hyperlinks, or show the verification check checked, etc.

There is a helper function in CDialog that simply checks the bools for those properties and construct the flags to use in the TASKDIALOGCONFIG struct, and uses operator |= and &= to turn the bits on and off.

The problem: To my surprise, there was no matching overload of operator|= that took a left hand operand of type MyEnum. This is a first for me. Of course, if you ask me if I have done this before in C++, I really can't recall an instance (I have done it in C# many times).

The details of the error pointed me to a possible overload (some overload for some enum in the Windows SDK). I examined that and I found a gorgeous macro:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Define operator overloads to enable bit operations on enum values that are 
// used to define flags. Use DEFINE_ENUM_FLAG_OPERATORS(YOUR_TYPE) to enable these 
// operators on YOUR_TYPE.

// Moved here from objbase.w.

#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) \
extern "C++" { \
inline ENUMTYPE operator | (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((int)a) | ((int)b)); } \
inline ENUMTYPE &operator |= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) |= ((int)b)); } \
inline ENUMTYPE operator & (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((int)a) & ((int)b)); } \
inline ENUMTYPE &operator &= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) &= ((int)b)); } \
inline ENUMTYPE operator ~ (ENUMTYPE a) { return ENUMTYPE(~((int)a)); } \
inline ENUMTYPE operator ^ (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((int)a) ^ ((int)b)); } \
inline ENUMTYPE &operator ^= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) ^= ((int)b)); } \
}
#else
#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) // NOP, C allows these operators.
#endif 


So naturally I went ahead and used it for my enums and the problem went away.

My question then is: Is this how standard C++ works? Or is this just a MS C++ compiler thing?
Last edited on
Unless you override it, enums are assigned increasing integers by default. It makes no sense to bitwise combine them, unless of course you override this and assign them powers of two. If you make this override then it makes sense to override the bitwise operators as well, but not by default.
(Yes, that is how C++ works.)
Thanks for the replies.

@kev82: It is not true that it makes no sense to bitwise increasing integers. See this example:

1
2
3
4
5
6
7
typedef enum _SomeFeatures
{
    NoFeatures,
    FeatureA,
    FeatureB,
    FeaturesAB
} SomeFeatures;


As you can see, the increasing integer values assigned are perfect bits, and this is why I didn't feel I had the need to enable bitwise operations explicitly by overriding, and it is why I would reject the theory too. Of course that it is undeniable the fact that it is NOT like this. :-(

In any case, the answers are of course appreciated and have imprinted in me a new piece of knowledge I did not have before. :-)
That example has 2 features. For 6 features you would either have to list 64. Or override the numeric assignment like I suggested. I think anyone with an ounce of sense would overload the numeric assignment. Also enums are commonly used for mutually exclusive things where the bitwise operators really would make no sense.
Last edited on
Topic archived. No new replies allowed.