Solutions using enum within class/struct (struct defaults with public members) and overloaded operators:
struct Color
{
enum Enum { RED, GREEN, BLUE };
Enum e;
Color() {}
Color(Enum e) : e(e) {}
Color operator=(Enum o) { e = o; return *this; }
Color operator=(Color o) { e = o.e; return *this; }
bool operator==(Enum o) { return e == o; }
bool operator==(Color o) { return e == o.e; }
operator Enum() const { return e; }
std::string toString() const
{
switch (e)
{
case Color::RED:
return "red";
case Color::GREEN:
return "green";
case Color::BLUE:
return "blue";
default:
return "unknown";
}
}
};
From the outside it looks nearly exactly like a class enum:
Color red;
red = Color::RED;
Color blue = Color::BLUE;
cout << red.toString() << " " << Color::GREEN << " " << blue << endl;
This will output "red 1 2". You could possibly overload << to make blue output a string (although it might cause ambiguity so not possible), but it wouldn't work with Color::GREEN since it doesn't automatically convert to Color.
The purpose of having an implicit convert to Enum (which implicitly converts to int or type given) is to be able to do:
Color color;
switch (color) ...
This works, but it also means that this work too:
int i = color;
With an enum class it wouldn't compile. You ought to be careful if you overload two functions taking the enum and an integer, or remove the implicit conversion...
Another solution would involve using an actual enum class and static members:
struct Color
{
enum class Enum { RED, GREEN, BLUE };
static const Enum RED = Enum::RED, GREEN = Enum::GREEN, BLUE = Enum::BLUE;
//same as previous...
};
It possibly takes more space, and is longer to make, but causes a compile error for implicit int conversions. I'd use this one because of that!
There's surely overhead with this though, but I think it's just simpler and looks better than other code I've seen. There's also potential for adding functionality, which could all be scoped within the class.
Edit: this works and most can be compiled before execution:
class Color
{
public:
enum class Enum { RED, GREEN, BLUE };
static const Enum RED = Enum::RED, GREEN = Enum::GREEN, BLUE = Enum::BLUE;
constexpr Color() : e(Enum::RED) {}
constexpr Color(Enum e) : e(e) {}
constexpr bool operator==(Enum o) const { return e == o; }
constexpr bool operator==(Color o) const { return e == o.e; }
constexpr operator Enum() const { return e; }
Color& operator=(Enum o) { const_cast(this->e) = o; return *this; }
Color& operator=(Color o) { const_cast(this->e) = o.e; return *this; }
std::string toString() const
{
switch (e)
{
case Enum::RED:
return "red";
case Enum::GREEN:
return "green";
case Enum::BLUE:
return "blue";
default:
return "unknown";
}
}
private:
const Enum e;
};