Search code examples
c++enumsbitwise-operatorsflags

cannot initialize a variable of type 'designFlags' with an rvalue of type 'int'


i am trying to create an enum flag that would see if a certain thing was bold and italic, but i am getting compilation error: error: cannot initialize a variable of type 'designFlags' with an rvalue of type 'int' designFlags myDesign = BOLD | UNDERLINE;

#include <iostream>
using namespace std;

enum designFlags {
    BOLD = 1,
    ITALICS = 2,
    UNDERLINE = 4
};

int main() 
{
    designFlags myDesign = BOLD | UNDERLINE; 

        //    00000001
        //  | 00000100
        //  ___________
        //    00000101

    cout << myDesign;

    return 0;
}

Solution

  • The C++ standard prevents you from performing an implicit cast from int to enum (Note: implicit conversion from enum to int is allowed).

    However, you can perform an static cast instead:

    designFlags myDesign = static_cast<designFlags>(BOLD | UNDERLINE);
    cout << myDesign; // prints 5
    

    Have in mind that it is most like that the resulting value is not one of the values specifies in designFlags. This is usually a common practice, but you have to rely to bit-wise operations to perform comparisons:

    For example:

    // wrong
    if (myDesign == BOLD)
    
    // ok (most of the time)
    if (myDesign & BOLD)
    
    // always ok
    if ((myDesign & BOLD) == BOLD)
    

    Update: Why is myDesign & BOLD ok most of the time?

    When you use flags, the values must be powers of two: 1, 2, 4, 8, etc. Therefore, every possible value has only one bit set, and this bit is different for each one.

    Then, when you do myDesign & BOLD, you are testing for one specific bit, and just that. If the bit is set, the result will be non-zero (bitwise AND). If the bit it not set, the result will be zero.

    When it can go wrong? Well, if you use flags that are not a power of two, each individual value will have more than one bit set, making it difficult to perform these checks.

    For instance, suppose you have this definition:

    enum designFlags {
        BOLD = 2,
        ITALICS = 4,
        UNDERLINE = 6
    };
    

    And then you set your design to UNDERLINE:

    myDesign = UNDERLINE
    

    What is the result of the following tests?

    myDesign & BOLD
    myDesign & ITALICS
    

    It will be non-zero for both of them, surely an undesired behavior.

    Of course you can do the following:

    if ((myDesign & BOLD) == BOLD) {
        ...
    

    but i rather use flags with only one bit set.