Consider the following C++ enumerations:
enum Identity
{
UNKNOWN = 1,
CHECKED = 2,
UNCHECKED = 3
};
enum Status
{
UNKNOWN = 0,
PENDING = 1,
APPROVED = 2,
UNAPPROVED = 3
};
The Compiler conflicted the both UNKNOWN items and threw this error:
error: redeclaration of 'UNKNOWN'
I am able to solve this error changing one of the UNKNOWN to UNKNOWN_a, but I would like to do not change the names.
How can I solve this conflict without changing the enum items name?
You can use scoped enumerations for this. This requires C++11 or higher support.
enum class Identity
{
UNKNOWN = 1,
CHECKED = 2,
UNCHECKED =3
};
enum class Status
{
UNKNOWN = 0,
PENDING = 1,
APPROVED = 2,
UNAPPROVED =3
};
int main ()
{
Identity::UNKNOWN;
Status::UNKNOW;
}
Live Example
Use scoped enums (C++ 11) - enum classes. They will not pollute the outer scope with duplicate names.
But, you'll need to access the enumerated values with a scope resolution operator - Identity::UNKNOWN, which is not a bad thing.
If using C++11 is not feasible(It really should by now, I mean, it's already 2015), consider using namespaces:
namespace Identity {
enum {
UNKNOWN = 1,
CHECKED = 2,
UNCHECKED =3
};
}
namespace Status {
enum {
UNKNOWN = 0,
PENDING = 1,
APPROVED = 2,
UNAPPROVED =3
};
}
But, really, enum class is much better.
This is how I would usually declare such enums (if I don't need something more fancy, like automatic conversions of the enum names to strings, serialization/deserialization etc.):
struct Identities
{
enum Type
{
UNKNOWN = 1,
CHECKED = 2,
UNCHECKED = 3
};
};
typedef Identities::Type Identity;
struct States
{
enum Type
{
UNKNOWN = 0,
PENDING = 1,
APPROVED = 2,
UNAPPROVED = 3
};
};
typedef States::Type Status;
// usage
Identity identity = Identities::UNKNOWN;
Status status = States::UNKNOWN;
Works in every C++ version and is type safe as well. Namespaces can be also used instead of structs (but I normally use structs).
Related
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
};
};
I am trying to use enumerations of std::vector<bool> because i'd like to represent some values as a vector of bits.
So I tried the following code:
enum class ProximityStateEnum : std::vector<bool> {
Unknown = std::vector<bool>{false,false},
NotConnected = std::vector<bool>{false,true},
Connected = std::vector<bool>{true,false},
ConnectedButNotLatched = std::vector<bool>{true,true}
};
But when I compile the code with this, I get the error underlying type ‘std::vector<bool>’ of ‘ProximityStateEnum’ must be an integral type. How can I do to create an enum of vectors ?
enum and enum class are not meant as aliases to instances of arbitrary objects - they're limited to integral types, and every explicit value must be a constant expression. See the cppreference page on enum for more information.
If you want to give a name to particular instances of std::vector<bool>, either use functions or inline variables:
auto Unknown() { return std::vector<bool>{false,false}; }
auto NotConnected() { return std::vector<bool>{false,true}; }
auto Connected() { return std::vector<bool>{true,false}; }
auto ConnectedButNotLatched() { return std::vector<bool>{true,true}; }
// ...or, in C++17:
inline auto Unknown = std::vector<bool>{false,false};
inline auto NotConnected = std::vector<bool>{false,true};
inline auto Connected = std::vector<bool>{true,false};
inline auto ConnectedButNotLatched = std::vector<bool>{true,true};
In your particular use case, you don't really need an std::vector because you know the size of your bitset in advance - std::bitset or binary literals will work well:
enum class ProximityStateEnum : /* some suitable type */
{
Unknown = 0b00,
NotConnected = 0b01,
Connected = 0b10,
ConnectedButNotLatched = 0b11
};
You cannot; enums can only be based on integral types.
If it can be helpful, since C++14 you can use binary literals to specify their values:
enum class ProximityStateEnum {
Unknown = 0b00,
NotConnected = 0b01,
Connected = 0b10,
ConnectedButNotLatched = 0b11
};
which is pretty much as clear as your idea, but way more compact and orders of magnitude more efficient than any hypothetical std::vector based solution.
Another possibility that is often used in enums where particular bits have particular meaning is to build them with expressions:
enum ProximityStateEnum {
Unknown = 0b00,
NotConnected = 0b01,
Connected = 0b10,
ConnectedButNotLatched = Connected | NotConnected
};
As said by other, enums can only be integral types.
If the lenght of your vectors of bool is constant (as in you example, where is 2), you can substitute the std::vector<bool> with a std::array<bool, length>. One advantage in using std::array instead of std::vector is that you can define it as constexpr.
So a reasonable (IMHO) alternative is define a enum type based on std::size_t, with sequential values starting from 0,
enum ProximityStateEnum : std::size_t
{
Unknown = 0U,
NotConnected,
Connected,
ConnectedButNotLatched
};
and a static constexpr std::array of std::arrays of bool
// .......................... last value of the enum vvvvvvvvvvvvvvvvvvvvvv
static constexpr std::array<std::array<bool, 2U>, 1U+ConnectedButNotLatched>
pseArr { { { {false, false} }, { {false, true} },
{ {true, false} }, { {true, true} } } };
that you can use as follows
pseArr[NotConnected][0]
I have the following class:
class washm_t
{
public:
enum door_t { closed = 0, open = 1 };
private:
door_t door_state ;
public:
int open() ;
};
The problem with the class is that the open name is defined as both the name of the method inside of the class and the value of the enum type.
The question is: can I somehow modify the code so that both open names work inside of the class or should I pick some other name for the open() method or for the open enum type value?
This is how the open() function looks like:
int washm_t::open()
{
if(door_state == open) // ~fails, 'open' interpreted as name of method
// not as name of enum type value
return 1 ;
else
return door_state = open, 0 ;
}
In C++11 you can use enum class:
enum class door_t { closed = 0, open = 1 };
But then you have to refer to door_t::open instead of simply open. This has the advantages and disadvantages of verboseness. enum class is good in these cases where a name conflict is likely, and it effectively adds a generic prefix to the enumerators of the enumeration.
(Actually, in C++11 you don't need to use the class keyword. Simply referring to door_t::open resolves the conflict with no other change.)
You can arrive at a similar solution in C++03 by putting an enum inside a class (hence the syntax of the C++11 feature)
struct door_state {
enum door_t { closed = 0, open = 1 };
};
You can make this a nested class, or define it before washm_t and use it as a base class
class washm_t : public door_state {
int open();
};
Now the the member open() overrides the enumerator, but the enumerator is still available as door_state::open, and closed is still available using the same syntax as before.
How about capitalizing the enums, or giving them a sensible prefix?
enum door_t { CLOSED = 0, OPEN = 1 };
enum door_t { door_closed = 0, door_open = 1 };
You can't have symbols under the same namespace or scope with the same name. Compiler can't differentiate one from the other.
The problem here is with the coding convention. I usually prefer to use caps letters for named constants like enums
enum door_t { CLOSED = 0, OPEN = 1 };
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);
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 )