When using an enum in C++ how does one create getter and setters?
Example:
enum class FieldLayerStates
{
kEmpty = 0, // new to the game.
kActive = 1, // has fields already in the same.
kAdd = 2 // field layer is ready to have a field added.
};
FieldLayerStates _fieldLayerState;
inline FieldLayerStates getFieldLayerState() { return _fieldLayerState; };
inline void setFieldLayerState(FieldLayerStates i) { _fieldLayerState = i; };
I am getting errors at the inline functions:
: Unknown type name 'FieldLayerStates'
: Cannot initialize return object of type 'int' with an lvalue of type 'FieldLayer::FieldLayerStates'
and when I go to use it:
// check the status of the layer to see if it has fields in it already (loaded from CCUserDefaults
if (getFields().empty())
{
// nothing, this must be our first time in.
setFieldLayerStatus(kEmpty);
}
It says kEmpty is undeclared.
Can someone help me clear up my confusion?
You're using an enum class, are you sure that's what you want?
If you stop doing that your code will work.
otherwise refer to FieldLayerStates::kEmpty (because enumerators of an enum class must be qualified by their type name)
I don't know why you get the Unknown type name 'FieldLayerStates' error because you haven't shown enough context to understand the code, at a guess I'd say you're trying to define the functions outside the class and you need to say FieldLayer::FieldLayerStates
Please show the full code so we have a chance of seeing what you're really compiling.
enum class Foo
is a new C++11 language feature that means "strongly typed, and scoped" enumerations. It is significantly different than just
enum Foo
When you use strongly typed enums, you have to qualify them with the scope they are contained in.
enum class Colors { Red, Green, Blue };
enum class Moods { Happy, Bored, Blue };
Without the "class", this won't compile, because you have defined "Blue" twice. With the "Class" you have actually defined two scopes with their own, private, scoped enums, that require the "::" operator to access.
The "class" are also strongly typed, which means that they won't cast - e.g. to an integer type - without you explicitly casting them.
enum COLORS { RED, GREEN, BLUE };
enum class Colors { Red, Green Blue };
int i = RED; // Legal
Colors j = Colors::Red; // Legal
int i = Colors::Red; // Illegal: Colors::Red is not an integer, it's a Colors.
Colors j = Red; // Illegal: You didn't specify the scope.
Colors j = RED; // Illegal: RED is an integer, not a Colors.
for (int i = RED; i <= BLUE; ++i) { cout << i << endl; } // Legal
// But Colors is not a numeric type, you can't do math or increment on it,
// so the following is illegal:
for (auto j = Colors::Red; j <= Colors::Blue; ++j)
enum class Flags = { Herp = 1, Derp = 2 };
Flags combo = Flags::Herp;
combo |= Flags::Derp; // Illegal, no '|' operator for Flags, casting required.
I think you just want this
enum FieldLayerStates
{
kEmpty = 0, // new to the game.
kActive = 1, // has fields already in the same.
kAdd = 2 // field layer is ready to have a field added.
};
Related
I heard a few people recommending to use enum classes in C++ because of their type safety.
But what does that really mean?
C++ has two kinds of enum:
enum classes
Plain enums
Here are a couple of examples on how to declare them:
enum class Color { red, green, blue }; // enum class
enum Animal { dog, cat, bird, human }; // plain enum
What is the difference between the two?
enum classes - enumerator names are local to the enum and their values do not implicitly convert to other types (like another enum or int)
Plain enums - where enumerator names are in the same scope as the enum and their
values implicitly convert to integers and other types
Example:
enum Color { red, green, blue }; // plain enum
enum Card { red_card, green_card, yellow_card }; // another plain enum
enum class Animal { dog, deer, cat, bird, human }; // enum class
enum class Mammal { kangaroo, deer, human }; // another enum class
void fun() {
// examples of bad use of plain enums:
Color color = Color::red;
Card card = Card::green_card;
int num = color; // no problem
if (color == Card::red_card) // no problem (bad)
cout << "bad" << endl;
if (card == Color::green) // no problem (bad)
cout << "bad" << endl;
// examples of good use of enum classes (safe)
Animal a = Animal::deer;
Mammal m = Mammal::deer;
int num2 = a; // error
if (m == a) // error (good)
cout << "bad" << endl;
if (a == Mammal::deer) // error (good)
cout << "bad" << endl;
}
Conclusion:
enum classes should be preferred because they cause fewer surprises that could potentially lead to bugs.
From Bjarne Stroustrup's C++11 FAQ:
The enum classes ("new enums", "strong enums") address three problems
with traditional C++ enumerations:
conventional enums implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer.
conventional enums export their enumerators to the surrounding scope, causing name clashes.
the underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration
impossible.
The new enums are "enum class" because they combine aspects of traditional enumerations (names values) with aspects of classes (scoped members and absence of conversions).
So, as mentioned by other users, the "strong enums" would make the code safer.
The underlying type of a "classic" enum shall be an integer type large enough to fit all the values of the enum; this is usually an int. Also each enumerated type shall be compatible with char or a signed/unsigned integer type.
This is a wide description of what an enum underlying type must be, so each compiler will take decisions on its own about the underlying type of the classic enum and sometimes the result could be surprising.
For example, I've seen code like this a bunch of times:
enum E_MY_FAVOURITE_FRUITS
{
E_APPLE = 0x01,
E_WATERMELON = 0x02,
E_COCONUT = 0x04,
E_STRAWBERRY = 0x08,
E_CHERRY = 0x10,
E_PINEAPPLE = 0x20,
E_BANANA = 0x40,
E_MANGO = 0x80,
E_MY_FAVOURITE_FRUITS_FORCE8 = 0xFF // 'Force' 8bits, how can you tell?
};
In the code above, some naive coder is thinking that the compiler will store the E_MY_FAVOURITE_FRUITS values into an unsigned 8bit type... but there's no warranty about it: the compiler may choose unsigned char or int or short, any of those types are large enough to fit all the values seen in the enum. Adding the field E_MY_FAVOURITE_FRUITS_FORCE8 is a burden and doesn't forces the compiler to make any kind of choice about the underlying type of the enum.
If there's some piece of code that rely on the type size and/or assumes that E_MY_FAVOURITE_FRUITS would be of some width (e.g: serialization routines) this code could behave in some weird ways depending on the compiler thoughts.
And to make matters worse, if some workmate adds carelessly a new value to our enum:
E_DEVIL_FRUIT = 0x100, // New fruit, with value greater than 8bits
The compiler doesn't complain about it! It just resizes the type to fit all the values of the enum (assuming that the compiler were using the smallest type possible, which is an assumption that we cannot do). This simple and careless addition to the enum could subtlety break related code.
Since C++11 is possible to specify the underlying type for enum and enum class (thanks rdb) so this issue is neatly addressed:
enum class E_MY_FAVOURITE_FRUITS : unsigned char
{
E_APPLE = 0x01,
E_WATERMELON = 0x02,
E_COCONUT = 0x04,
E_STRAWBERRY = 0x08,
E_CHERRY = 0x10,
E_PINEAPPLE = 0x20,
E_BANANA = 0x40,
E_MANGO = 0x80,
E_DEVIL_FRUIT = 0x100, // Warning!: constant value truncated
};
Specifying the underlying type if a field have an expression out of the range of this type the compiler will complain instead of changing the underlying type.
I think that this is a good safety improvement.
So Why is enum class preferred over plain enum?, if we can choose the underlying type for scoped(enum class) and unscoped (enum) enums what else makes enum class a better choice?:
They don't convert implicitly to int.
They don't pollute the surrounding namespace.
They can be forward-declared.
The basic advantage of using enum class over normal enums is that you may have same enum variables for 2 different enums and still can resolve them(which has been mentioned as type safe by OP)
For eg:
enum class Color1 { red, green, blue }; //this will compile
enum class Color2 { red, green, blue };
enum Color1 { red, green, blue }; //this will not compile
enum Color2 { red, green, blue };
As for the basic enums, compiler will not be able to distinguish whether red is refering to the type Color1 or Color2 as in hte below statement.
enum Color1 { red, green, blue };
enum Color2 { red, green, blue };
int x = red; //Compile time error(which red are you refering to??)
Enumerations are used to represent a set of integer values.
The class keyword after the enum specifies that the enumeration is strongly typed and its enumerators are scoped. This way enum classes prevents accidental misuse of constants.
For Example:
enum class Animal{Dog, Cat, Tiger};
enum class Pets{Dog, Parrot};
Here we can not mix Animal and Pets values.
Animal a = Dog; // Error: which DOG?
Animal a = Pets::Dog // Pets::Dog is not an Animal
It's worth noting, on top of these other answers, that C++20 solves one of the problems that enum class has: verbosity. Imagining a hypothetical enum class, Color.
void foo(Color c)
switch (c) {
case Color::Red: ...;
case Color::Green: ...;
case Color::Blue: ...;
// etc
}
}
This is verbose compared to the plain enum variation, where the names are in the global scope and therefore don't need to be prefixed with Color::.
However, in C++20 we can use using enum to introduce all of the names in an enum to the current scope, solving the problem.
void foo(Color c)
using enum Color;
switch (c) {
case Red: ...;
case Green: ...;
case Blue: ...;
// etc
}
}
So now, there is no reason not to use enum class.
do not implicitly convert to int
can choose which type underlie
ENUM namespace to avoid polluting happen
Compared with normal class, can be declared forward, but do not have methods
C++11 FAQ mentions below points:
conventional enums implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer.
enum color
{
Red,
Green,
Yellow
};
enum class NewColor
{
Red_1,
Green_1,
Yellow_1
};
int main()
{
//! Implicit conversion is possible
int i = Red;
//! Need enum class name followed by access specifier. Ex: NewColor::Red_1
int j = Red_1; // error C2065: 'Red_1': undeclared identifier
//! Implicit converison is not possible. Solution Ex: int k = (int)NewColor::Red_1;
int k = NewColor::Red_1; // error C2440: 'initializing': cannot convert from 'NewColor' to 'int'
return 0;
}
conventional enums export their enumerators to the surrounding scope, causing name clashes.
// Header.h
enum vehicle
{
Car,
Bus,
Bike,
Autorickshow
};
enum FourWheeler
{
Car, // error C2365: 'Car': redefinition; previous definition was 'enumerator'
SmallBus
};
enum class Editor
{
vim,
eclipes,
VisualStudio
};
enum class CppEditor
{
eclipes, // No error of redefinitions
VisualStudio, // No error of redefinitions
QtCreator
};
The underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible.
// Header1.h
#include <iostream>
using namespace std;
enum class Port : unsigned char; // Forward declare
class MyClass
{
public:
void PrintPort(enum class Port p);
};
void MyClass::PrintPort(enum class Port p)
{
cout << (int)p << endl;
}
.
// Header.h
enum class Port : unsigned char // Declare enum type explicitly
{
PORT_1 = 0x01,
PORT_2 = 0x02,
PORT_3 = 0x04
};
.
// Source.cpp
#include "Header1.h"
#include "Header.h"
using namespace std;
int main()
{
MyClass m;
m.PrintPort(Port::PORT_1);
return 0;
}
One thing that hasn't been explicitly mentioned - the scope feature gives you an option to have the same name for an enum and class method. For instance:
class Test
{
public:
// these call ProcessCommand() internally
void TakeSnapshot();
void RestoreSnapshot();
private:
enum class Command // wouldn't be possible without 'class'
{
TakeSnapshot,
RestoreSnapshot
};
void ProcessCommand(Command cmd); // signal the other thread or whatever
};
Because, as said in other answers, class enum are not implicitly convertible to int/bool, it also helps to avoid buggy code like:
enum MyEnum {
Value1,
Value2,
};
...
if (var == Value1 || Value2) // Should be "var == Value2" no error/warning
I should start by saying I'm fairly new to OOP. I am trying to write a portable class which will probably be used in multiple programs. The class requires multiple enumerated lists to store information which are only relevant to the class so I was planning on nesting the enum inside the class. My questions are
Is there any reason to use an enum class inside a class, or should I just use enum? Just curious. I posted sample code for reference below.
Is there any reason why it would be a really bad idea to make enums in a class public?
#include <iostream>
enum class Color {
red = 0,
green = 1,
blue = 2
};
class CodeLibray {
public:
enum Color2 {
red = 0,
green = 1,
blue = 2
};
enum class Color3 {
red = 0,
green = 1,
blue = 2
};
Color color;
Color2 color2;
Color3 color3;
};
int main(){
CodeLibray c;
c.color = Color::red;
c.color2 = CodeLibray::Color2::blue;
c.color3 = CodeLibray::Color3::blue;
}
Is there any reason to use an enum class inside a class, or should I just use enum? Just curious. I posted sample code for
reference below.
It's pretty obvious that the enum values defined inside CodeLibray would become ambigous if you omit the enum class there.
Also, If I want enums to be accessible for assigning public member values but I do not want values in the enum to be changed is this
possible?
I don't fully understand what you mean. Just a shot in the dark, something like the following?
enum Color2 {
red = ::red,
// ^^ Refer to the enum declaration in the global namespace
green = ::green,
blue = ::blue
};
enum class Color3 {
red = ::red,
green = ::green,
blue = ::blue
};
UPDATE: I just did some benchmarking of the core conversion logic for various solutions. Here are the CPU times in nanoseconds for a single iteration, averaged out of five million iterations on Wandbox:
8 - switch statement
176 - static map
3800 - dynamic map
As you can see, creating a new map every time (dynamic mapping) is relatively time consuming. Creating the map once (static mapping) and just referring to it thereafter is almost 22 times faster. But, coincidentally, the original switch-based solution is 22 times faster than static mapping!
Hmm... I never considered dynamic mapping a viable solution but had hopes for static mapping. It's quite a bit slower than the good, old switch statement, but does 8 nanoseconds versus 176 nanoseconds really matter?
End of update
The core problem I'm trying to solve is translating from one "namespace" to another (in the general sense, not re the C++ namespace keyword). This is common in programming, usually solved in C++ with a switch statement like this:
#include <iostream>
enum MUSIC { ROCK, RAP, EDM, COUNTRY };
enum COLOR { RED, BLUE, ORANGE, WHITE };
COLOR convert(MUSIC music)
{
COLOR color = WHITE;
switch (music) {
case RAP: color = RED; break;
case EDM: color = BLUE; break;
case ROCK: color = RED; break;
}
return color;
}
int main()
{
COLOR c = convert(COUNTRY);
std::cout << c << std::endl;
}
The following is my solution (the templates will be tucked away in a header file somewhere). The convert() function works with any types that are valid for std::map, e.g., enum to enum and long to std::string. The first parameter is the key, or "from" value, the second is the default value if can't be converted, and the return value is the mapped, or "to," value. (Special thanks to #Yakk for help with template argument deduction.)
#include <iostream>
#include <map>
#include "boost/assign.hpp"
template<class T> struct no_deduction { typedef T type; };
template<typename Key, typename T>
T convert(const Key &k, const T &d, const typename no_deduction<std::map<Key, T> >::type &m) {
typename std::map<Key, T>::const_iterator it = m.find(k);
return it == m.end() ? d : it->second;
}
using boost::assign::map_list_of;
enum MUSIC { ROCK, RAP, EDM, COUNTRY };
enum COLOR { RED, BLUE, ORANGE, WHITE };
int main()
{
COLOR c = convert(COUNTRY, WHITE, map_list_of (RAP, RED) (EDM, BLUE) (ROCK, RED));
std::cout << c << std::endl;
}
Anyway, notice that map_list_of, above, creates the same list every time it's called. I'd like it to be static. This is the obvious solution:
static const std::map<MUSIC, COLOR> m = map_list_of (RAP, RED) (EDM, BLUE) (ROCK, RED);
COLOR c = convert(COUNTRY, WHITE, m);
But I'm trying to make it simple to use, in particular, as a single statement. Here's a macro solution, but I'd rather avoid that, too.
#define CONVERT(f,t,d,m) do{static const std::map<BOOST_TYPEOF(f), BOOST_TYPEOF(d)> m_ =\
map_list_of m; t = convert(f, d, m_);}while(0)
COLOR c;
CONVERT(COUNTRY, c, WHITE, (RAP, RED) (EDM, BLUE) (ROCK, RED));
Does anybody know of some C++ magic (C++03, actually) that can call my convert() function
with a static map,
as a single statement, and
without using a macro?
Why not just simply use a static array and index it ?
enum MUSIC { ROCK = 0, RAP = 1, EDM = 2, COUNTRY = 3 };
enum COLOR { RED, BLUE, ORANGE, WHITE };
static const COLOR music_to_color[] =
{
RED, //maps to 'ROCK = 0'
BLUE, //maps to 'RAP = 1'
ORANGE, //maps to 'EDM = 2'
WHITE //maps to 'COUNTRY = 3'
};
MUSIC music = RAP;
std::cout << music_to_color[music] << std::endl;
The body of your convert function can be only return music_to_color[music] (where music would be the argument) in this case.
The advantages of this approach are speed and lack of additional runtime overhead of creating a std::map of something simmilar. Disadvantage would be the fact that you cannot easily modify the map on runtime and it is more "C-like" than "C++ like" (you can ease the pain using std::array instead of static array if you need C++ interface: iterators, etc.)
Another way to do the same thing is to use template specializations, but it is a lot of typing and it would be difficult to maintain if you had a lot of values to map.
Uppercase names are conventionally reserved for macros, so I renamed them.
At some point you are going to have to do the work of coding how one enum type converts to another. The easiest way using a map is as follows:
Color convert(Music music)
{
static const std::map<Music, Color> converter = { { Rap, Red }, { Edm, Blue }, { Rock, Red } };
return converter.at(music);
}
This uses initializer lists which is a C++11 feature. If you can't use that, you can try:
Color convert(Music music)
{
static const struct Once
{
Once()
{
converter[Rap] = Red;
converter[Edm] = Blue;
converter[Rock] = Red;
}
std::map<Music, Color> converter;
} once;
std::map<Music, Color>::const_iterator find_it = once.converter.find(music);
assert(find_it != once.converter.end());
return find_it->second;
}
This code might not use fancy macros but it's safe, reasonably efficient (one instance of the map) and readable (although I did do a trick with that struct there). There are faster ways but they are more complicated and probably not necessary for your use case.
If there are less than a dozen enum values, I would consider just using a switch statement however. It is usually faster than a map.
(under Visual Studio 2012)
Consider the following class :
class pe_exception : public std::runtime_error
{
public:
//Exception IDs
enum exception_id
{
unknown_error,
bad_pe_file,
bad_dos_header,
image_nt_headers_not_found,
error_reading_image_nt_headers,
error_reading_data_directories,
error_reading_file,
pe_signature_incorrect,
...
Can you tell why is it possible to directly get the enum member with such code :
bool b = e.get_id() == pe_exception::error_reading_image_nt_headers;
Instead of having to go into the enum first ?
bool b = e.get_id() == pe_exception::exception_id::error_reading_image_nt_headers;
(library where this is taken from : https://code.google.com/p/portable-executable-library/)
That is just the way old-school enums work: they have no scope. This comes directly from C.
For example:
enum Colour { red, black, orange };
Colour c = orange; // OK
enum Fruit { banana, apple, orange }; // ERROR: orange has already been defined
C++11 class enums or scoped enumerations fix this (see scoped enumerations here for more information).
enum class Colour { red, black, orange };
Colour c = orange; // ERROR
Colour c = Color::red; // OK
enum class Fruit { banana, apple, orange }; // OK
An enum is absolutly equivalent to a list of static int declaration, except the compiler generates initialization value starting at 0, and incrementing by one between each value.
In your case
enum exception_id
{
unknown_error,
bad_pe_file,
bad_dos_header
};
int val = exception_id::unknown_error; //Not ok (except >MSVC 2010)
Note that on visual since VS 2010 (maybe before) you can add the nested scope to be more precise, but that was not standard (and not compiling on GCC and CLang).
is equivalent to:
static int unknown_error = 0;
static int bad_pe_file= 1;
static int bad_dos_header= 2;
The solution before C++11 was
struct exception_id{
enum exception_id_enum
{
unknown_error,
bad_pe_file,
bad_dos_header
};};
int val = exception_id::unknown_error; //ok
Now you can write
enum class exception_id{
{
unknown_error,
bad_pe_file,
bad_dos_header
};
auto val = exception_id::unknown_error; //ok
Last but very important point The typing changes, now you have strong typing on this.
I let you read the FAQ of bjarne
See here a nice explaination on MSDN
I am using fully qualified name of the enum inside a method in one of my class. But I am getting compiler warning which says "warning C4482: nonstandard extension used: enum 'Foo' used in qualified name". In C++, do we need to use enums without the qualified name? But IMO, that looks ugly.
Any thoughts?
Yes, enums don't create a new "namespace", the values in the enum are directly available in the surrounding scope. So you get:
enum sample {
SAMPLE_ONE = 1,
SAMPLE_TWO = 2
};
int main() {
std::cout << "one = " << SAMPLE_ONE << std::endl;
return 0;
}
To make it clean, replace:
enum Fruit {
ORANGE = 0,
BANANA = 1
};
with
namespace Fruit {
enum { //no enum name needed
ORANGE = 0,
BANANA = 1
};
};
...
int f = Fruit::BANANA; //No warning
While sth does answer the question, it didn't address how I've always used enums. Even though they're just more or less names for numbers, I've always used them to define types that can only have certain values.
If the enum is part of the class, then that helps consumers clearly identify an enum reference:
class Apple {
enum Variety {
Gala,
GoldenDelicious,
GrannySmith,
Fuji
}
...
};
Then consumers would be able declare instances of the enum, pass as parameters, and qualify them when referencing one of the types.
unsigned int GetCountOfApples( Apple::Variety appleVariety );
...
fujiCnt = GetCountOfApples( Apple::Fuji );
Sometimes you want an enum outside of a class or two enums in the same class, and you can do something like what Poy had. You won't be able to reference the enum type though, so just name it.
namespace Color {
enum ColorEnum {
Blue,
Red,
Black
};
Now using the enum and values would work like:
Color::ColorEnum firstColor = Color::Blue;
Color::ColorEnum secondColor = Color::Red;
if( firstColor == secondColor )
....
Now if there happens to be different enums with the same name in them, they will always be qualified with what type they are. Then you could handle what gamblor is asking about.
BananaColorEnum banCol = BananaColor::Yellow;
TomatoColorEnum tomCol = TomatoColor::Yellow;
Yes. Conceptually enum defines a type, and the possible values of that type. Even though it seems natural, to define enum foo { bar, baz }; and then refer to foo::baz is the same as referring to int::1.
namespace Company
{
typedef int Value;
enum
{
Microsoft= 0,
APPLE = 1,
};
};
namespace Fruit
{
typedef int Value;
enum
{
ORANGE = 0,
BANANA = 1,
APPLE = 2,
};
};
...
Fruit::Value f = Fruit::BANANA; //No warning
Company::Value f = Company::APPLE; //is different value then Fruit::APPLE
This works on GCC and MS compiler and Mac. And the advantage is that you can use namespace operator and pass conflicts. The little disadvantage is that instead of Fruit, you have to write Fruit::Value. it is more useful in large project when you don't know what enums are in other class.
If it is possible to use C++11 instead, it is much more simple, because the enum::namespace syntax is then possible.
The cleanest way I've found to do this is defining the enum as such
namespace Samples
{
enum Value
{
Sample1,
Sample2,
Sample3
};
}
typedef Samples::Value Sample;
Then in function and variable definitions you can use the typedef:
void Function(Sample eSample);
Sample m_eSample;
And in your .cpp file you can use the namespace to assign variables:
void Function(Sample eSample)
{
m_eSample = Samples::Sample1;
eSample = Samples::Sample2;
}
Personally, I think this is a compiler bug. I've been using C++ for lots of time. Sadly, no sample code in OP. The interpretation of an enum by the Java people was actually correct iMO. Mine, was like this ...
class Foo {
enum tMyEnum { eFirstVal = 0, eSecondVal = 1};
// ...
tMyEnum m_myVal;
};
void Foo::MyMethod() {
if(m_myVal == tMyEnum::eFirstVal) {
// ...
}
}
I also tried, Foo::tMyEnum::eFirstVal. Without the qualifiers, everything compiled.
I had the same problem and I'm not using C++ 11 yet. I much prefer fully qualified namespaces myself too.
I disabled this particular warning. I'm sure people will dislike the idea but some may be thankful..
#pragma warning( disable : 4482 )