Enum issues, or is it my understanding? - c++

I'm adding a enum type to the very few bits of C++ I've learnt so far, but having trouble to set it...Am i missing some fundamentals?
class Rectangle
{
public:
Rectangle();
~Rectangle();
enum rectangle_directions_t {R_LEFT = 0, R_DOWN = 1, R_RIGHT= 2, R_UP = 3, R_NONE = 4};
void setRect(rectangle_directions_t rec_dir) {rectangle_direction = rec_dir;}
private:
rectangle_directions_t rectangle_direction;
};
int main()
{
Rectangle pRect;
pRect.setRect(R_LEFT);
}
Can you not just set a variable of an enum type like any other type? Or am i missing something simple? The error I get is during the "set" in main which says R_LEFT is undefined. Which is odd because I don't usually declare an "int" first if I want to pass it to a method...

The enumeration is defined within your class Rectangle. You need to qualify R_LEFT:
pRect.setRect(Rectangle::R_LEFT);

Related

How to use an enum attribute of a class for an argument of a setter function for that class?

I have a class method that needs to know the value of a variable named mode which takes the values 1 an 0 and is a private attribute of the class. I want to write a setter function that can change mode to 1 or 0. However, I must use an enum to determine the new value that I should set mode to: enum sequence {error=0,active =1}; I want sequence to be an attribute (I was hoping to make it private) of the class. How can I write a setter function that takes as input active or error and sets the value of mode accordingly. Here is the basic structure of my code:
#include <iostream>
class Blink{
public:
void setter(...){
}
private:()
int mode = 0;
enum sequence {error = 0, active = 1};
};
Blink b;
int main() {
b.setter(active);
}
PS: I'm having a hard time coming up with a good title for this question, suggestions are appreciated!
It's pretty straight forward. This is how I would do it in C++11 and above:
class Blink {
public:
enum class Sequence { Error, Active };
void setter(Sequence s) {
if (s == Sequence::Active) {
mode = 1;
} else {
mode = 0;
}
}
private:
int mode = 0;
};
Blink b;
int main() {
b.setter(Blink::Sequence::Active);
}
The main difference is that Sequence is declared publicly. Note that mode is still a private variable so there is no harm. Sequence becomes part of the public interface because it needs to be understood from outside.
The second change is that I use enum class. Yes, you could also use a plain enum that implicitely casts to the integer, but see Why is enum class preferred over plain enum?
In this simple example, I would instead use private member Sequence mode = Sequence::Error; instead of int mode = 0;.

Referencing Enum C++ Unreal

I have created an Enum Class in Unreal C++
#include "GroundDirection.generated.h"
UENUM(BlueprintType)
enum UGroundDirection
{
BOTTOM = 0,
LEFT = 1,
TOP = 2,
RIGHT = 3
};
In C# or Java I could instantiate a copy of this Enum doing something like this:
GroundDirection groundDirection = GroundDirection.BOTTOM;
I thought I could do something similar with Unreal C++
UGroundDirection groundDirection = UGroundDirection.BOTTOM;
However when I do this I get the following error:
error C2228: left of '.BOTTOM' must have class/struct/union
How to I instantiate Enums in light of this error?
I have created an Enum Class in Unreal C++
No, you didn't. You just created a C-style enum.
Also, the UE++ coding standard states that an enum should have an E as a prefix.
So your declaration should actually look like this:
#include "GroundDirection.generated.h"
UENUM(BlueprintType)
enum class EGroundDirection
{
BOTTOM = 0,
LEFT = 1,
TOP = 2,
RIGHT = 3
};
To access the members of the enum, you access them like they are static members of a class:
EGroundDirection direction = EGroundDirection::BOTTOM;
This is, because you are not accessing a member of an instance, but a declaration which is always done by using :: in C++.
BOTTOM isn't a class but an integer. Moreover, UGroundDirection isn't a class/struct/union but an enum, and hence it is kind of considered as a namespace. You shall use :: instead of .
To solve your problem, you shall simply remove UGroundDirection from UGroundDirection groundDirection = UGroundDirection.BOTTOM; and replace it with: int groundDirection = UGroundDirection::BOTTOM
That's all!
In C++, you can use either the "namespace-enum" style or "enum class" style. Both of them will limit the elements in specific domain.
Well, some comments say I didn't proveide the solution.
You can try
#include "GroundDirection.generated.h"
UENUM(BlueprintType)
enum class EGroundDirection
{
BOTTOM = 0,
LEFT = 1,
TOP = 2,
RIGHT = 3
};
or
#include "GroundDirection.generated.h"
UENUM(BlueprintType)
namespace EGroundDirection
{
enum EGroundDirection
{
BOTTOM = 0,
LEFT = 1,
TOP = 2,
RIGHT = 3
};
};

Only allow a subset of an enum as return value - OR How to get the compiler to alert me ? in C++

My Goal
I have multiple functions that will return a large List of errorcodes.
Some functions will use same and distinct errorcodes of the "List of errorcodes"
for Example:
fun1() will ONLY return errorcode1 OR errorcode2 (errorcode2 is only used in this function)
fun2() will ONLY return errorcode1 OR errorcode3 (but errorcode1 is used in both functions)
The desired solution should consider the following points:
-
Have a definition what errorcode can be returned by which function
Get compile error if any function tries to return an errorcode that was not intended for this function
Whatever the function return or throws must be convertable to int (because these functions will be part of a C API)
My Approaches
So far I considered to options that use enums but the solutions do not appeal to me
Define for each function a separate enum
Define one global enum for all function
Define for each function a separate enum
enum errorcodefun1 {errorcode1=1, errorcode2=2}; // OK at least it is expressed what is expected for fun1
errorcodefun1 fun1() { };
enum errorcodefun2 {errorcode1_fun2=1, errorcode3_fun2=3 }; // minor problem: not expressing that errorcode1_fun2 is logical same as errorcode1
The more functions (which partly use same errorcode) the more code duplication I get.
Define one enum for all function
enum errorcodes {errorcode1=1, errorcode2=2, errorcode3=3};
errorcode fun1() {... } //do not like because I will get no compilation error if it returns errorcode3. Only errorcode1 and errocode2 is intended
errorcode fun2() {... }
My Question
I was thinking about writing a class that emulates the enum, but so far I see the solution that satisfies all my needs.
Do you have some suggestions or ideas how to accomplish my goal?
How about going with approach #1 but staying safe and expressing the equivalence of the enum members?
enum generic_error {
ERR_OK,
ERR_NOMEM,
ERR_IO,
ERR_GENERIC
};
enum first_error {
FIRSTERR_OK = ERR_OK,
FIRSTERR_NOMEM = ERR_NOMEM
};
enum second_error {
SECONDERR_OK = ERR_OK,
SECONDERR_IO = ERR_IO
};
int main()
{
enum first_error f = FIRSTERR_OK;
enum second_error s = SECONDERR_OK;
assert(f == s); // never fires
return 0;
}
Not that this would be particularly good practice, though... If I were you, I would really just opt to have one common error code enumeration.
Use bitmasks.
enum Code : unsigned int
{
None = 0,
SomeError= 1,
AnotherError = 2,
YetAnotherError = 4
};
unsigned int valid_error_codes_for_func1 = SomeError | YetAnotherError;

C++ enums and inline header functions

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.
};

Using enum inside types - Compiler warning C4482 C++

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 )