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...)
Related
I have theenumerated type, colors:
enum colors {green, red, blue};
Is colors mycolors=red the same as int yourcolors=red and is the type of each enumerator int? The both will have a value of 1, right?
Thanks!
I just want to post a little code snippet to prove the comments of Jason Lang and Kerrek SB:
#include <iostream>
#include <typeinfo>
enum colors {green, red, blue};
int main()
{
colors mycolors=red;
int yourcolors=red;
if (mycolors == yourcolors)
std::cout << "same values" << std::endl;
if (typeid(mycolors) != typeid(yourcolors))
std::cout << "not the same types" << std::endl;
return 0;
}
Running this code will lead into the following console output:
same values
not the same types
Also (as Daniel Kamil Kozar mentioned) there is enum class (only C++11 and later!). See this Question for more information about why to prefer enum class over enum.
Regarding the question 'why are enums after not just ints (or longs or ...) just think of operator overloading. That is ++ colors(green) == 1 must not be true.
Confirm this Question that operator overloading is possible for plain enums and this question and the accepted answer to see how to avoid casting in overloading operators of an 'enum class'.
At last keep in mind that the usage of enums - if used reasonable - improves code readability.
I think enum seems a little more type-safety. You can do int yourcolors=red, but not colors mycolors=1.
When I'm debugging enum usage is helpful. It shows enumeration name
instead of its value.
Enumeration values aren’t lvalues. So, when you pass them by
reference, no static memory is used. It’s almost exactly as if you
passed the computed value as a literal.
enum KEYS
{
UP,
RIGHT,
DOWN,
LEFT
};
void (KEYS select)
{
switch (select)
{
case UP:
case RIGHT:
case DOWN:
case LEFT: break;
default: exit(1);
}
}
after making a fresh start on a new program i made for learning how arrays work in combinatio0n with void ive ran into the following problem.
cpp(15): error C2182: 'input' : illegal use of type 'void'
Does anyone know what causes this? I am new to the concept of void and array.
#include "stdafx.h"
#include <iostream>
using namespace std;
void input (int x );
int main()
{
int x = 0;
int a[ 5 ];
input ( a[ 5 ]);
{
void input(x);
for(int i = 1; i < 5; i++) {
cin >> a [ i ];
}
cin.get();
cout << a [ 3 ];
cin.get();
}
}
Your code has many problems with it. It's just not valid C++ as it is. Remember that C++, like any other programming language, is unforgiving when it comes to syntax. If it's not exactly the right syntax, it's not going to compile. You can't just write what you think makes sense. You need to learn the correct syntax and apply it.
It looks like you want everything from the for loop to the last cin.get() to be part of a function called input. To do that, you need to use the appropriate syntax for defining a function and you need to do it outside any other functions:
void input(int x) {
for(int i = 1; i < 5; i++) {
cin >> a [ i ];
}
cin.get();
cout << a [ 3 ];
cin.get();
}
This still has a problem though. The parameter type is int, yet it looks like you want to pass the entire array:
void input(int x[])
Note that this is not actually an array type parameter, but is really a pointer. When you pass an array to this function, x will be a pointer to its first element. The [] is just a convenient syntax.
Then, instead of passing a[5] to the function (which is an element that does not exist, since only a[0] to a[4] exist), you should be passing just a:
input(a);
You also loop from 1 to 4 - I'm not sure if this is intentional. If you want to input a value for each element of the array, you should be looping from 0 to 4.
You're going to have more errors after resolving the current one. Here's some quick pointers that may help. I don't want to just give you a solution because you are still learning and that won't help:
void as a keyword refers to the "nothing type" and is used in functions to denote having no return value
curly braces {} denote scope and can be used to define the body of a function, loop, or control statement
Functions themselves need to be declared and defined. The definition, or body of the function, can be later on in your code but the declaration needs to be present before you call it
Here's an example program to illustrate basic function parts:
#include <iostream>
// declaration
void Welcome();
int main()
{
// function call
Welcome(); // displays "Hello World"
return 0;
}
// definition
void Welcome()
{
std::cout << "Hello World" << std::endl;
}
More on functions
As far as arrays they are basically a contiguous block of memory large enough to hold a given amount of the same type. Here's a few things to remember about arrays:
They work with integral types as well as objects but are usually used for plain old data. e.g. int intArray[5]; is an array of 5 int types.
The index starts at 0 meaning intArray[0] from previous example is the first integer.
Using the array operator you can get and set values e.g. int last = intArray[4]; or intArray[0] = -1;
More on arrays
Check out the other answers for more on how to pass arrays as parameters but I also recommend picking a Good C++ Book ;-)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Should I use #define, enum or const?
Advantage and disadvantages of #defines vs. constants?
How enum will be more useful than #define and const.
memory and code visibilty point of view and readability point of view.
can I convert (type cast) enum to array of int, If I have taken all value within integer.
Example:
class MapPlt_clContainer {
public:
enum tagVectorType {
enVTAll = 0,
enVTPolygon,
enVTLines
}
};
tVoid MapPlt_clRender::vDrawLineClass( MapPlt_clContainer::tagVectorType* )
While calling function enum pass
vDrawLineClass( ClassArray_Group ); //Working
While calling array base address pass
int test[3] =
{
5,
6,
7,
};
vDrawLineClass( test); //Not Working
Error!!
Should it type cast it automatically? or it is compiler dependent. In my case it is giving error.
enum is a separate type unlike #define and the language (with the help of compiler) will help you ensure you are not mixing values of different types (even if they are of the same numerical value).
Additionally the value of an enum is available to the debugger whereas the original meaning of the #define is lost during the pre-processing time (before the code generation has even begun).
Type-casting an enum to an int is an automatic built-in process while the opposite conversion is trickier as not all the int values could be valid for your particular enum.
Modern compilers will also warn you if you have used all the possible enum's values in a switch statement that has no default clause, something that cannot be checked for #defines
If you are using an enum as an integer in C++ you have a smell. An enum defines a type, and only the values of that type should be used. (I realize this isn't enforced and the enum can be interpreted as an int, but with C++ it generally shouldn't).
Also, a big pet peeve of mine: Don't put "Type" in the name for an enum in C++. The values of an enum are not "types" (in the C++ sense of the word). As soon as you start doing template code, you will HATE all the enums with the word Type in their type name.
Also, any time you are trying to typecast in your design, you are doing it wrong. That is an awful smell in C++. You shouldn't have to do it, and you certainly shouldn't design it into your code (i.e. use it as a "feature").
Finally, this part:
int test[3] =
{
5,
6,
7,
};
vDrawLineClass( test); //Not Working
This is a straight up ugly hack. Do what you say, say what you do:
MapPlt_clContainer::tagVectorType test[3] =
{
MapPlt_clContainer::enVTAll,
MapPlt_clContainer::enVTPolygon,
MapPlt_clContainer::enVTLines
};
vDrawLineClass( test);
In addition to the points made in other answers, I would like to add the following:
If you have multiple types and you need to iterate on them, you will have to use an array of constants, which will be something like this:
const int states[] = {STATE_1,STATE_2, STATE_3, STATE_4 };
int numStates = sizeof(states)/sizeof(state[0]);
for (int i = 0; i < numStates; i++) {
// Do something with states[i]..
}
With enumerations, this can be simplified as
enum states{cState_1 = 0, cState_2, cState_3, cState_4, cNumStates};
for (int i = 0; i < numStates; i++) {
// do something with i
}
I have a enumerated type StackID, and I am using the enumeration to refer to an index of a particular vector and it makes my code easier to read.
However, I now have the need to create a variable called nextAvail of type StackID. (it actually refers to a particular stackID ). I tried to increment it but in C++, the following is illegal:
nextAvail++;
Which sort of makes sense to me ... because there's no bounds checking.
I'm probably overlooking something obvious, but what's a good substitute?
I also want to link to this question.
I'm probably overlooking something obvious, but what's a good substitute?
Overloading operator++:
// Beware, brain-compiled code ahead!
StackID& operator++(StackID& stackID)
{
#if MY_ENUMS_ARE_CONTIGUOUS && I_DO_NOT_WORRY_ABOUT_OVERFLOW
return stackID = static_cast<StackID>( ++static_cast<int>(stackID) );
#else
switch(stackID) {
case value1 : return stackID = value2;
case value2 : return stackID = value3;
...
case valueN : return stackID = value1;
}
assert(false);
return stackID; // some compilers might warn otherwise
#endif
}
StackID operator++(StackID& stackID, int)
{
StackID tmp(stackID);
++stackID;
return tmp;
}
Because enumerations do not have to be contiguous. E.g. take this example:
enum Colors {
cRed, // = 0
cBlue, // = 1
cGreen = 3
}
What should happen in this scenario?
Colors color = cBlue;
Colors other = color++;
Should other be cGreen or should it be 2. In that case it's not a valid enumeration member anymore. What about this?
Colors color = cGreen;
Colors other = color++;
Should other be cRed (wrap around) or 4?
As you can see, being able to increment enumeration values introduces a whole lot of questions and complicates the simple mechanism that they intend to be.
If all you care about is the integer value being incremented, then simply cast to int and increment that.
Casting back and forth to/from int is of course the obvious solution, then you make clear that you understand that the addition is happening "outside" the enum:
nextAvail = static_cast<StackID>(static_cast<int>(nextAvail) + 1);
Why not store nextAvail as an int instead if you're going to do arithmetic operations on it?
Another option would be to wrap the enum in your own type and overload operator ++ for it (which also could wrap around or something for instance).
An enumeration is semantically supposed to represent a set of distinct related, values.
So you could have
enum Colour {RED, GREEN, BLUE};
But that should be equivalent to:
enum Colour {GREEN, BLUE, RED};
The problem is that if you increment an enum then those representations are not the same. GREEN++ in the first case is not the same as GREEN++ in the second.
Making your program dependent on the declaration of the enum is a recipe for disaster - maintainers may assume that the order of the enum doesnt matter, introducing many silent bugs.
Very Simple:
nextAvail = (StackID)(nextAvail + 1);
Enums are going to be type int, so you can cast them. Is this what you're trying to do?
int ndx = (int) StackID.SomeValue;
...
++ndx;
This is going to make someone very confused down the line, of course.
It occurs to me that you're using an enum where you should be using const, or even #define. enum is most appropriate when you have arbitrary values (where the exact value is not meaningful).
I've overloaded the ++/-- operator in this way:
enum STATE {STATE_1, STATE_2, STATE_3, STATE_4, STATE_5, STATE_6};
// Overload the STATE++ operator
inline STATE& operator++(STATE& state, int) {
const int i = static_cast<int>(state)+1;
state = static_cast<STATE>((i) % 6);
return state;
}
// Overload the STATE-- operator
inline STATE& operator--(STATE& type, int) {
const int i = static_cast<int>(type)-1;
if (i < 0) {
type = static_cast<STATE>(6);
} else {
type = static_cast<STATE>((i) % 6);
}
return type;
}
With respect to oprator++, $5.2.6/1 states- "The type of the operand shall be an arithmetic type or a pointer to a complete object type."
StackID does not fit the bill here. It is of enumeration type.
One option is like this
$5.7/1 - "For addition, either both operands shall have arithmetic or enumeration type, or one operand shall be a pointer to a completely defined object type and the other shall have integral or enumeration type."
enum Possibility {Yes, No, Maybe};
Possibility operator++(Possibility const& r){
return Possibility(r + 1); // convert r to integer, add 1, convert back to Enum
}
int main(){
Possibility p = Yes;
Possibility p1 = ++p;
}
I'm quite happy with this C plus C++ solution for a for loop incrementing an enum.
for (Dwg_Version_Type v = R_INVALID; v <= R_AFTER; v++)
=>
int vi;
for (Dwg_Version_Type v = R_INVALID;
v <= R_AFTER;
vi = (int)v, vi++, v = (Dwg_Version_Type)vi)
The other solutions here are not C backcompat, and quite large.
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