Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

narrowing conversion from int to long unsigned int {} is ill-formed in C++11

when I run the below code - I'm getting the warning "narrowing conversion from int to long unsigned int inside {} is ill-formed in C++11 [-Wnarrowing]. I'm using GNU 4.8 compiler.

typedef struct TableEntry
{
    unsigned long value;
    const char *label;
} TableEntry;

enum FunctionType
{
    NORMAL   = 0, 
    RANGE    = 1
};


TableEntry functionTypes[] = 
{
    {NORMAL,   "NORMAL"},
    {RANGE, "RANGE"}
};

I don't understand why compiler is considering enum as an int?
Is this a bug in GCC 4.8? Is there any workaround? Any help is appreciated.

like image 723
Wild Widow Avatar asked Feb 11 '14 23:02

Wild Widow


People also ask

How do you fix narrowing conversion error?

If you make a narrowing conversion intentionally, make your intentions explicit by using a static cast. Otherwise, this error message almost always indicates you have a bug in your code. You can fix it by making sure the objects you initialize have types that are large enough to handle the inputs.

What is a narrowing conversion?

A narrowing conversion changes a value to a data type that might not be able to hold some of the possible values. For example, a fractional value is rounded when it is converted to an integral type, and a numeric type being converted to Boolean is reduced to either True or False .


2 Answers

Usually underlying type of unscoped enumerations is int ( it can be any integral type that can represent all values of enumerators).

However I do not see any narrowing conversion because type unsigned long can represent all values of type int.

EDIT: It seems I am wrong because I found an example in the Standard that contradicts my assumption

unsigned int ui1 = {-1}; // error: narrows

So unsigned int can not be initialized by using an initializer list that contains a negative number.

So to avoid the warning the enumeration could be written as

enum FunctionType : unsigned int // or unsigned long
{
    NORMAL   = 0, 
    RANGE    = 1
};
like image 28
Vlad from Moscow Avatar answered Oct 01 '22 12:10

Vlad from Moscow


If practical do:

enum FunctionType
{
    NORMAL   = 0, 
    RANGE    = 1
};

typedef struct TableEntry
{
    FunctionType value;
    const char *label;
} TableEntry;


TableEntry functionTypes[] = 
{
    {NORMAL,   "NORMAL"},
    {RANGE, "RANGE"}
};

Otherwise, change the type in the struct to int, or explicitly base the enumeration on the same type as in the struct.

Btw., I the think g++ warning is unfounded and wrong, since the original code is valid C++03. Correction: As I understand it now, the diagnostic is correct, and this is a breaking change in C++11. I just couldn't believe it.


About the naming convention: those all uppercase identifiers are good for Java programmers (who are used to that convention), but in C++ they increase the chances of inadvertent text substitution. There are also the aesthetic considerations. Much win in reserving all uppercase for macros.

like image 93
Cheers and hth. - Alf Avatar answered Oct 01 '22 14:10

Cheers and hth. - Alf