Ask about new syntax of enum (C++) [duplicate] - c++

I did a search for this question thinking that somebody must have asked it before. I did not turn up any results, so if it has been, please post the link and feel free to close the question.
I ran across this code in EASTL:
enum : size_type { // size_type = size_t
npos = (size_type)-1,
kMaxSize = (size_type)-2
};
I have never encountered an enum declaration like that. What does the : do in this case?

In C++0x, you can specify the underlying type for the enum. In this case, it will be size_type.
(And it may be supported as an extension in other places prior to C++0x, obviously.)

This is a Microsoft extension that lets you choose the base type of the enum values. For example, this lets you specify that values are unsigned (Microsoft's compilers usually choose signed by default) or that they only occupy 8 or 16 bits (Microsoft normally defaults to 32 bits).
The syntax is documented here: http://msdn.microsoft.com/en-us/library/2dzy4k6e(v=VS.100).aspx but I'm not able to find official documentation of what it actually does.
C++11 adds a similar feature, but with slightly different syntax. In C++11 you'd write it like this:
enum MyEnum : size_type { .. values .. };

Related

Why do I have to cast an enum element when assigning it to a same enum variable type in C?

I have the following:
typedef enum
{
FLS_PROG_SUCCESS,
FLS_PROG_FAIL,
FLS_ERASE_SUCCESS2U,
FLS_ERASE_FAIL,
FLS_READ_SUCCESS,
FLS_READ_FAIL,
FLS_FORMAT_SUCCESS,
FLS_FORMAT_FAIL
}FLS_JobResult_t;
void Foo(void)
{
FLS_JobResult_t ProgramStatus;
/* Then I try to initialize the variable value */
ProgramStatus = FLS_PROG_SUCCESS;
...
}
Innocent uh, but when compiling MISRA C gives the error:
The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category
And I found out that I shall write the initialization as follows:
ProgramStatus = (FLS_JobResult_t)FLS_PROG_SUCCESS;
And this just doesn't look good to me, it's like MISRA wants me to throw casts in all the code and that's too much.
Do you know why is this? I don't think this should be an issue but I've tried everything that comes to my mind and this was the only way of getting rid of this error, but it simply does not make any sense, does it?
Regards.
(Hi, this is a new account so I cannot use the comments section yet to ask for further clarification, so, my answer may be broader than needed)
Based on the text of the warning message I assume you are talking about MISRA-C:2012 (the latest standard) which is a great improvement over the prior ones in that much more effort in stating the rationale along with many more compliant and non-compliant examples have been added. This being Rule 10.3, the rationale is: since C permits assignments between different arithmetic types to be performed automatically, the use of these implicit conversions can lead to unintended results, with the potential for loss of value, sign or precision.
Thus MISRA-C:2012 requires the use of stronger typing, as enforced by its essential type model, which reduces the likelihood of these problems occurring.
Unfortunately many tools have not properly implemented the rules and the type model. In this case, your tool is incorrect, this is not a violation of essential type rules because ProgramStatus and FLS_PROG_SUCCESS are both the same essential type. In fact a similar example is shown in the standard itself, under the rule’s list of compliant examples:
enum enuma { A1, A2, A3 } ena;
ena = A1;
If your tool vendor disagrees you can post your question on the "official" MISRA forum to get the official answer and forward that to the vendor.

'=' should initialize either all enum members or only the first;

I am trying to build my code with following enum values :
typedef enum {
YUV_420P=0,
YUV_422P,
RGB_P,
BAYER_P,
YUV_422IBE,
YUV_444IBE,
A_1BIT,
YUV_420SP,
COMPLEX_8BIT,
COMPLEX_16BIT,
COMPLEX_32BIT,
COMPLEX_U8BIT,
COMPLEX_U16BIT,
COMPLEX_U32BIT,
ALPHA_TYPE=0x8000
} Format;
But during building I am getting the below linting warning ..
sample.h: Note 960: Violates MISRA 2004 Required Rule 9.3, '=' should initialize either all enum members or only the first; enumerator: 'ALPHA_TYPE' ..
I don't want to change value of ALPHA_TYPE and I want to put the ALPHA_TYPE in this enum only. How can I resolve this?
Your code already does what you want. You just need to suppress this particular warning.
On the other hand, if you absolutely do need to adhere to this MISRA 2004 rule 9.3, then you will need to change your code and find a different solution. But you cannot have it both ways.
If values of other enums does not matter, you can do this
typedef enum {
ALPHA_TYPE=0x8000,
YUV_420P,
YUV_422P,
RGB_P,
BAYER_P,
YUV_422IBE,
YUV_444IBE,
1BIT,
YUV_420SP,
COMPLEX_8BIT,
COMPLEX_16BIT,
COMPLEX_32BIT,
COMPLEX_U8BIT,
COMPLEX_U16BIT,
COMPLEX_U32BIT
} Format;
Or
Define all your enum values like this (this avoid one of your enum value to change, if you add a new one)
typedef enum {
YUV_420P=0,
YUV_422P=1,
RGB_P=2,
BAYER_P=3,
YUV_422IBE=4,
YUV_444IBE=5,
1BIT=6,
YUV_420SP=7,
COMPLEX_8BIT=8,
COMPLEX_16BIT=9,
COMPLEX_32BIT=10,
COMPLEX_U8BIT=11,
COMPLEX_U16BIT=12,
COMPLEX_U32BIT=13,
ALPHA_TYPE=0x8000
} Format;
This is certainly not a C++ requirement.
[C++11: 7.2/2]: An enumerator-definition with = gives the associated enumerator the value indicated by the constant-expression. If the first enumerator has no initializer, the value of the corresponding constant is zero. An enumerator-definition without an initializer gives the enumerator the value obtained by increasing the value of the previous enumerator
by one.
The grammar above it allows multiple enumerators to have an initializer.
If you are allowed, perhaps you can turn off checks for compliance with this "MISRA 2004" rule. You could also simply ignore it since it appears to be a mere Note. Personally I would be a bit annoyed to have that popping up all the time, but perhaps that's just me.
Since the first enum value is 0, and since it is that also by default, simply use the default. ← I misread the warning, this point is not a solution.
And/or, turn off the MISRA rule checking.
And/or, ignore the specific note. Apparently you can do that via an +esym option. Or maybe -esym, just try out things and check the documentation.

What does this colon do in an enum declaration?

I did a search for this question thinking that somebody must have asked it before. I did not turn up any results, so if it has been, please post the link and feel free to close the question.
I ran across this code in EASTL:
enum : size_type { // size_type = size_t
npos = (size_type)-1,
kMaxSize = (size_type)-2
};
I have never encountered an enum declaration like that. What does the : do in this case?
In C++0x, you can specify the underlying type for the enum. In this case, it will be size_type.
(And it may be supported as an extension in other places prior to C++0x, obviously.)
This is a Microsoft extension that lets you choose the base type of the enum values. For example, this lets you specify that values are unsigned (Microsoft's compilers usually choose signed by default) or that they only occupy 8 or 16 bits (Microsoft normally defaults to 32 bits).
The syntax is documented here: http://msdn.microsoft.com/en-us/library/2dzy4k6e(v=VS.100).aspx but I'm not able to find official documentation of what it actually does.
C++11 adds a similar feature, but with slightly different syntax. In C++11 you'd write it like this:
enum MyEnum : size_type { .. values .. };

enum declaration in windows to linux

I have a C++ declaration:
enum SETTINGS:UINT32
{
a=1,
b=2,
};
what is the meaning of :UINT32?
how can I swich this declaration to linux?
Its part of the new C++0x way of declaring enums
enum <EnumTypeName> [: <Optinal-Type>] { <ValueList> };
By default an enum is represented by an integer.
The new syntax allows you to optionally define the type used to represent the enum
In this case it indicates that the enum underlying representation should be of type UINT32. What this means will depend on what the macro UINT32 has been defined to be. But it is probably an integer of at least 32 bits and is unsigned. :-)
See Bjornes description of the new enum stuff:
http://www2.research.att.com/~bs/C++0xFAQ.html#enum
Here, the :UINT32 syntax specifies the underlying enum type. However, this is not standard C++ (at least, not standard C++03) but a Visual Studio extension : g++ will probably reject it, and you should too.
See C++ Enumeration Declaration on MSDN for a description of this syntax
See this Wikipedia page regarding C++0x upcoming changes to enum declarations
EDIT As pointed in the comments by Martin York, g++ supports this syntax since version 4.4, so I guess the only issue for a Linux portage would be UINT32 being non standard.
u = unsigned
int = integer
32 = 32 bit
read this : "Uint32", "int16" and the like; are they standard c++?

Do all C++ compilers allow using a static const int class member variable as an array bound?

In VC++ when I need to specify an array bound for a class member variable I do it this way:
class Class {
private:
static const int numberOfColors = 16;
COLORREF colors[numberOfColors];
};
(please don't tell me about using std::vector here)
This way I have a constant that can be used as an array bound and later in the class code to specify loop-statement constraints and at the same time it is not visible anywhere else.
The question is whether this usage of static const int member variables only allowed by VC++ or is it typically allowed by other widespread compilers?
This is valid C++ and most (all?) reasonably modern compilers support it. If you are using boost, you can get portable support for this feature in the form of BOOST_STATIC_CONSTANT macro:
class Class {
private:
BOOST_STATIC_CONSTANT(int, numberOfColors = 16);
COLORREF colors[numberOfColors];
};
The macro is expanded to static const int numberOfColors = 16 if the compiler supports this, otherwise it resorts to enum { numberOfColors=16 };.
That behavior is valid according to the C++ Standard. Any recent compiler should support it.
I believe that Visual Studio 2005 and beyond supports it. The XCode C++ compiler as well (this is gcc actually).
If you want to be safe you could always use the old enum hack that I learned from Effective C++. It goes like this:
class Class {
private:
enum {
numberOfColors = 16
};
COLORREF colors[numberOfColors];
};
Hope this helps.
This has been standard C++ for more than a decade now. It's even supported by VC -- what more could you want? (#Neil: What about SunCC? :^>)
Yes, it's 100% legal and should be portable. The C++ standard says this in 5.19 - Constant expressions" (emphasis mine):
In several places, C++ requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case-expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3).
constant-expression:
conditional-expression
An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions.
That said, it appears that VC6 doesn't support it. See StackedCrooked's answer for a good workaround. In fact, I generally prefer the enum method StackedCrooked mentions for this type of thing.
As an FYI, the "static const" technique works in VC9, GCC 3.4.5 (MinGW), Comeau and Digital Mars.
And don't forget that if you use a "`static const'" member, you'll need a definition for it in addition to the declaration strictly speaking. However, virtually all compilers will let you get away with skipping the definition in this case.
Besides other answers you can use following function do determine number of elements in statically alocated arrays:
template<typename T, size_t length>
size_t arrayLength(T (&a)[length])
{
return length;
}
I'm pretty sure that this will also work with gcc and Solaris, but I can't verify this at the moment.
In the future you could extend the idea like this:
template<int size>
class Class {
private:
COLORREF colors[size];
};
and use it like this:
Class<5> c;
so that you are not limited to exactly one buffer size in your application.
I've stopped bothering about the portability of that years ago. There are perhaps still compilers which don't support it, but I haven't met any of them recently.
It is possible to answer questions like this by referencing the ISO C++ speicifcation but the spec is hard for people to get and harder to read.
I think the simplest answer hinges on two things:
Microsoft Visual Studio 2005 and up is a relatively conformant C++ implementation. If it allows you to do something, chances are its standard.
Download something like Code::Blocks to get a GCC compiler to try stuff out. If it works in MS and GCC, chances really are, its standard.