Using 'Flags'

This topic is 4375 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Okay. I know it's declared as an int, but I have no idea where to go from there. In many functions I've used, I can pass different flags ( SDL_SRCALPHA | SDL_OPENGL ), or whatever. Now, I want to make my own function which'll take flags. Can someone point me to a tutorial on how to do it, or just post an explanation? Thanks in advance, :) Erondial

Share on other sites
Flags work by using the distinct bits in an integer to represent on/off values.

For instance, you can decide that bit 1 means "GREEN", bit 2 means "BLUE", bit 3 means "RED" and bit 4 means "ALPHA" (for instance, when selecting which channels to read from a file). So you would create the following values:

enum ColorFlags {  GREEN = 0x1,  BLUE = 0x2,  RED = 0x4,  ALPHA = 0x8};

Then, the | operation mixes the bits: it's a bitwise or operation. For instance:

  00010101| 10101001----------  10111101

Finally, to determine if a flag is set, you use the bitwise and operator, &. For instance, to check if the GREEN flag is set, you'd use if( flags & GREEN ). Applied to GREEN | RED | ALPHA, it would work this way:

  00001101& 00000001----------  00000001 // non-zero

Applied to RED | BLUE, it would be:

  00000110& 00000001----------  00000000 // zero

The result is zero if the flag is not set, and is equal to the flag if the flag is set.

Share on other sites
To define your flags I would recommend using a helper enum:
enum Bits {  BIT0 = (1 << 0),  BIT1 = (1 << 1),  BIT2 = (1 << 2),  ...  BIT31 = (1 << 31),};

Then to declare your flags you can simply write:
enum ColorFlags {  GREEN = BIT0,  BLUE = BIT1,  RED = BIT2,  ALPHA = BIT3};

Share on other sites
A clean, type-safe way of doing flags in C++:

namespace MY_FLAG_TYPE_NS {  typedef enum {    NO_FLAG = 0,    FLAG_1 = 1<<0,    FLAG_2 = 1<<1,    FLAG_3 = 1<<2,    FLAG_4 = 1<<3,    FLAG_5 = 1<<4,    // etc...  } MY_FLAG_TYPE;  // some operators that are useful on flags:  MY_FLAG_TYPE operator|(MY_FLAG_TYPE left, MY_FLAG_TYPE right) {return (MY_FLAG_TYPE)(left|right);}    // implement as well:  MY_FLAG_TYPE operator&(...){...}  MY_FLAG_TYPE operator^(...){...}  MY_FLAG_TYPE operator~(...){...)}using MY_FLAG_TYPE_NS::MY_FLAG_TYPE;// example use:// void do_stuff( MY_FLAG_TYPE flags );// // use of the do_stuff function:// do_stuff( MY_FLAG_TYPE_NS::FLAG_1 | MY_FLAG_TYPE_NS::FLAG_5 );// or:// using namespace MY_FLAG_TYPE_NS;// do_stuff( FLAG_1 | FLAG_3 );//// To test if a flag is set:// void func( MY_FLAG_TYPE flag ) {//   if (flag & MY_FLAG_TYPE_NS::FLAG_1) {//     ... (code goes here)//   } else if (flag & MY_FLAG_TYPE_NS::FLAG_3) {//     ... (code goes here)//   }// }

Naturally, you would pick good names for MY_FLAG_TYPE and the flags (FLAG_1, FLAG_2) that are valid.

By using an enum instead of an int, and defining the operators one likes to use on a flag, you allow the the code to be more type-safe. It also makes your code self-documenting -- just by looking at your function's signature and the types of the variables, you can tell what flags your function accepts.

HTH.

[Edited by - NotAYakk on March 1, 2006 7:10:04 PM]

Share on other sites
Why thank you. That's alot easier than I envisioned it. Thanks :)