1) The following code shows the index of the enum element wednesday .How can i make it to print the value instead of the index.
int main()
{
enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
day d=wednesday;
cout<<d;
return 0;
}
2) In what situation will I prefer anonymous enum over enum
1). Your code prints the value of the enum, not the index. In your specific example, the index is the same as the value (by default, the first value of an enum gets the numerical value 0, and the rest get consecutive increasing values.
To check:
int main()
{
enum day{sunday = 5,monday,tuesday,wednesday,thursday,friday,saturday};
day d=wednesday;
cout<<d; // will print 8 (as in 5 + 1 + 1 + 1)
return 0;
}
If by "print the value" you meant printing "wednesday", you should do this:
enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
std::ostream& operator << (std::ostream& out, const day d)
{
static const char *as_strings[] = {"sunday", "monday",
"tuesday", "wednesday", "thursday", "friday", "saturday"
};
return out << as_strings[static_cast<int>(d)]; // this only works
// for enum values starting from 0 and being consecutive
// otherwise you should use a switch(d) and
// print each value separately
}
int main()
{
day d=wednesday;
cout<<d; // will print wednesday
return 0;
}
Edit:
2) In what situation will I prefer anonymous enum over enum
You prefer an anonymous enum when you do not need to pass it as a parameter, but need to assign meaningful names to constant numeric values:
my_object record_to_myobject(record& r)
{
enum {id, value1, value2}; // indexes within record
int result_id = r[id]; // much more meaningful than r[0]
int result_value1 = r[value1];
int result_value2 = r[value2];
return my_object{result_id, result_value1, result_value2};
}
It's fine to use an anonymous enum here because where you pass the value as argument, you need an int, not an enum type. If you need an enum type, then you have to give it a name. Otherwise, you do not.
First, the language doesn't provide any means of mapping the
internal enum value to a string. It can't, really; consider:
enum Numbers {
one = 1,
two = 2,
three = 3,
un = 1,
deux = 2,
trois = 3
};
Once you've assigned the enum constant to an enum variable, it
contains the numerical value, and nothing else. And if the
numerical value in the above is 2, how can the system know
whether it should map to two or to deux.
In practice, the mapping is useful in many contexts. A long
time ago, I wrote a simple parser to generate the mapping code;
it ignores most of C++, won't work in cases where e.g. the
enum is wrapped in a macro, the code it generates won't
compile if the enum is private or protected, and it's undefined
which string you get in cases like the above, but I've still
found it extremely useful.
For the second question: anonymous enums are usually used when
the only purpose of the enum is to generate constants. Things
like:
enum { maxSize = 4096 };
were widely used before you could provide the initialization
constant for static member variables. And I've often found it
convenient to define bit masks using an anonymous enum, even
when the actual values were on some sort of unsigned type.
Things like:
enum {
offsetMask = 0xF000,
offsetShift = 12,
NS = 0x100,
CWR = 0x80,
ECE = 0x40,
URG = 0x20,
ACK = 0x10,
// ...
};
uint16_t flags;
// ...
flags = offset << offsetShift | ACK;
I don't want to declare my variables to have an enum; they must
be exactly 16 bits (according to the TCP specification). In C,
I'd probably have used a #define, and in modern C++, I might
use static uint16_t const member variables, but through out
most of my C++ career, something like the above would have been
the normal solution.
You have to manually maintain an array of string "descriptions" of the enum values, which is tedious and error-prone:
static const char *daydescs[] = {
"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"
};
int main()
{
enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
day d=wednesday;
cout<< daydescs[(unsigned)d];
return 0;
}
An enum is a number, the string representation (e.g. wednesday) is a compile time representation.
You would need something like:
const char *dayname[] = {"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};
...
cout << dayname[(unsigned)d];
...
Try code below :
int main()
{
enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
String days[7] = {"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};
day d=wednesday;
cout<<days[d];
return 0;
}
1) If you only want the integer value, you can write an operator << overload:
template<typename _stream>
_stream& operator << (const day& value) {
_stream << static_cast<int>(value);
return _stream;
}
Also, consider using enum class instead of a plain enum (if you are allowed to use C++11, of course).
2) I would say there could be 1 such case: namespace constants, say you have a Person class and want to have some in-class constants like MaxAge or MaxNameLength. But even in such cases, wrapping restrictions in something like enum class Settings is usually worth it.
A type-safe variation on this theme would be to use enum class and use it as a key in std::map
#include <string>
#include <map>
#include <iostream>
int main()
{
enum class day
{
sunday,
monday,
tuesday,
wednesday,
thursday,
friday,
saturday
};
std::map<day,std::string> days =
{
std::make_pair(day::sunday, "Sunday"),
std::make_pair(day::monday, "Monday"),
std::make_pair(day::tuesday, "Tuesday"),
std::make_pair(day::wednesday, "Wednesday"),
std::make_pair(day::thursday, "Thursday"),
std::make_pair(day::friday, "Friday"),
std::make_pair(day::saturday, "Saturday")
};
std::cout << days[day::sunday] << std::endl;
}
This means that accessing the map with an integral type will cause a compile-time error.
Related
Consider the case where I have to convert an int type to an enum. When doing this with static_cast the risk is that even values out of admissible values of the enum are casted. Take as example the following code:
#include<iostream>
int main(char argc, char* argv[])
{
enum class EnumType : uint8_t
{
A = 0,
B = 1,
default=255
};
EnumType enum_var;
uint8_t num_var_out_of_range = 31;
enum_var = static_cast<EnumType>(num_var_out_of_range);
std::cout<<static_cast<int>(enum_var)<<std::endl;
return 0;
}
31 is not in the set of the enum values. I guess that the cast is valid because the underlying type of the enum is able to represent that value, but in my opinion it would more appropriate to raise an error or warning in this case. Is there a way to manage such cases?
I am currently building a poor version of the game "Battleship" and have to use an array of Enums to display the board. For my header I have created:
enum class PlayerPiece {
AIRCRAFT,
BATTLESHIP,
CRUISER,
SUBMARINE,
PATROL,
EMPTY,
};
class Board {
public:
PlayerPiece playerBoard[100];
PlayerPiece enemyBoard[100];
void reset();
void display() const;
};
When I get to my source code, I try displaying the board as numbers. As of right now the board is EMPTY after I run my reset command. But after I want to display the array, I get an error saying "no operator << matches these operands ....", I understand that means I need to overload the << command to display properly, but why doesn't it just display the '5' that was assigned? Isn't that the point of Enums? What I have so far is:
void Board::reset(){
for (int i = 0; i < 100; ++i){
playerBoard[i] = PlayerPiece::EMPTY;
enemyBoard[i] = PlayerPiece::EMPTY;
};
}
void Board::display() const{
for (int i = 0; i < 100; ++i){
cout << playerBoard[i] << endl; //
};
}
I have made other codes where I don't have to overload the << operator to display the number attached with ENUM. Am I missing something? Any help would be appreciated.
If you want to see the number associated with the scoped enum type, use a static_cast like this:
cout << static_cast<int>(playerBoard[i]) << endl;
Normal (unscoped) enums don't need this cast, as their types implicitly cast to int, or whatever underlying type you specified. That's probably why this hasn't happened to you before.
If you remove the class and write enum with Unscoped enumeration
enum PlayerPiece {
AIRCRAFT,
BATTLESHIP,
CRUISER,
SUBMARINE,
PATROL,
EMPTY,
};
You can print the number you wanted.
The difference between scoped and unscoped(from cplusplus.com):
Before C++11, all enums were just, basically, integers. And you could use them like that. It made it too easy to give bad values to functions expecting a restricted set of values. For example:
1
2
3
4
5
6
7
8
9
10
enum round_mode { round_half_up, round_half_down, round_bankers };
double round( double x, round_mode = round_half_up )
{
...
};
int main()
{
double x = round( 2.5, 42 );
}
Edit & Run
It compiles, but it isn't pretty.
With C++11, the compiler now knows all kinds of things about your enums, and doesn't let you blithely mix them with incorrect values.
Essentially, it promotes an enum to a first-class object -- it isn't just an integer.
The other issue is that the name for each enumeration bleeds into the containing scope. So the following would be a name conflict:
1
2
enum color_masks { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF };
int red = 0xFF0000;
You can't have both the identifier 'red' as an enum value and as an integer variable name in the same scope.
While the example here is contrived, it isn't too far off from things that happen all the time -- and that programmers have to take pains to avoid.
(Some identifier names are common. For example, 'max'. If you #include , there's a 'max' macro in there, which plays havoc if you also #include and try to use the 'max' function, or #include and try to find the numeric_limit ::max(). I know that's a macro problem, but it's the first name conflict I could come up with...)
I want to initialize a strongly-typed enum in C++11 from its underlying type, which is a value I read from serialized stream and which I have to check for a correct number range.
Something like:
enum class MyEnum {
FOO, BAR
};
MyEnum test = static_cast<MyEnum>(1);
This works as expected, but the problem is:
MyEnum test2 = static_cast<MyEnum>(42);
also works and give no indication of an Error. As far as I see an enum class also does not have any notion of bounds or other indicators on how to check if the input is valid. In "old style" enums, we would include a MIN and MAX value and compare against those, but adding these values to the strongly-typed enum would add invalid values to this type again, undermining its purpose.
Any ideas how I could check the bounds or force an error in case the value is out of bounds?
Update:
I just tried std::numeric_limits, but this also does not work for enum classes:
cout << static_cast<unsigned int>(numeric_limits<MyEnum>::min()) << endl;
cout << static_cast<unsigned int>(numeric_limits<MyEnum>::max()) << endl;
both return 0.
There's currently no way to extract an enum's minimum or maximum enumerators, but http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html proposes enough new type traits to implement a library that can do this. The Reflection group was interested, but asked the authors to come back with a proposal that more clearly generalized to other reflection features. I believe http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4027.pdf is the result of that generalization, and it'll get discussed at the meeting this coming week.
std::numeric_limits returns the max possible value of enum (depends on datatype) and not the maximum existing enum value.
Examples:
enum class MyType : uint8_t
{
eType1 = 0,
eType2 = 1,
COUNT,
MAXVAL = std::numeric_limits<decltype(COUNT)>::max()
};
MAXVAL = 255
enum class MyType
{
eType1 = 0,
eType2 = 1,
COUNT,
MAXVAL = std::numeric_limits<decltype(COUNT)>::max()
};
MAXVAL = 2147483647
I have a question about enum variable in c++:
type enmu {
DAY1 = 1,
DAY2,
DAY3,
DAY4
} DAYS;
void main() {
DAYS days;
}
then what is the default value of days?
It's uninitialized and undefined behavior to read the value.
Just like saying
int x;
x doesn't have a value until you initialize it.
then what is the default value of days?`
Like for any automatic object, the value of the days object is indeterrminate.
Now if you declared your object with the static specifier:
static DAYS days;
Then like for any static object of an arithmetic type, the initial value would be 0.
Enumerations behave pretty much like integers, i.e. they don't have a well-defined default value. You cannot read the variable's value before initializing it without invoking undefined behavior.
BTW, adding to the words, said before: you really do may have default value for a static enum variable. But be carefull -- it will be 0 (as well as all other static variables). Consider following code:
#include <iostream>
enum _t_test {
test_1 = 1,
test_2 = 2,
test_3 = 3,
};
static enum _t_test t;
int main()
{
using namespace std;
cout << "Value of t is: " << t;
return 0;
}
It will print 0, but your enums are in range from 1..3. So be aware of it.
I was wondering in C++ if I have an enum can I access the value at the second index? For example I have
enum Test{hi, bye};
if I want 'hi', can I do something like Test[0], thanks.
Yes and no. If your Enum does not have explicit values then it is possible. Without an explicit values, enum values are given numeric values 0-N in order of declaration. For example ...
enum Test {
hi, // 0
bye // 1
}
This means that indexes just translates into a literal value.
Test EnumOfIndex(int i) { return static_cast<Test>(i); }
This of course does 0 validation at runtime and as soon as you add an explicit value it will break down. But it will work in the default scenario.
Unless specified otherwise, enums start numbering at 0, and increment by 1 each entry.
enum Test
{
hi, //0
bye, //1
count //2
}
You can cast an int to the type of the enum to get the value you want, such as:
(Test)0;
//or
Test(0);
Which lets you do things like:
for(int i = 0; i < count; i++)
{
DoSomething((Test)i);
}
Enumerations map names to values. In your case, (int)hi would have a value of 0, and (int)bye a value of 1. You can use a cast to get the value of hi:
int myInteger = 0;
Test myValue = (Test)myInteger;
Note, though, that myValue could be an invalid enum value if myInteger is out of range.
No, but you could cast from int
Test test = (Test)0;
Depends what you mean by "I want 'hi'".
If you mean you want the value, then you can get it by casting an int, as others have said.
Casting a numeric literal to enum type is usually pointless - if you know which value you're expecting, you can use the name. That way, the enum can change without breaking your code. I guess it's possible that something really weird is going on, where someone has created an enum, and documented what "3" means but not which enum value it is. But then you'd want to fix the API.
Casting an integer value known at runtime to enum might be helpful if you have serialized data. As long as you know it's in range of the enum, the result is defined.
If you mean you want the string "hi", then you can't have it. Unlike Java, in C++ the names of the values in enumerated types exist only at compile time, not at runtime, and only map in one direction.
Your best option might be something like this:
enum Test{hi = 0, bye};
Then you can simply refer to 'hi' with the number 0, and 'bye' with 1.
Although this really defeats the whole purpose of using an enumeration in the first place.
If you are excepting the value to returned as {Hi or bye} ,then you cannot get the value like that .
i would not suggest this to be done inorder to get the actual value but it can be used as hack
string return_value(int index)
{
string temp = "";
switch (index)
{
case 1: temp = "hi"
break;
case 2: temp = "bye";
break;
defualt :
break;
}
return temp;
}
typecasting to enum would again return the index but you can assign to some other enum variable
#include <iostream>
#define GENERATE_ENUM(ENUM) ENUM,
#define GENERATE_STRING(STRING) #STRING,
#define FOREACH_TEST(ID) ID(hi) ID(bye) ID(good)
enum TEST { FOREACH_TEST(GENERATE_ENUM) };
static const char * Test[] = { FOREACH_TEST(GENERATE_STRING) };
int main() {
printf("%s ",Test[0]);
printf("%s\n",Test[bye]);
for (int i=0; i<2; i++) printf("Test[%d] = %s\n", i, Test[i]); }
compile and run with: g++ enum-test.cpp -o enum-test; ./enum-test
output:
hi bye
Test[0] = hi
Test[1] = bye