Assume all I need is a type Color
inhabited by only 3 values, red
, green
, blue
, (just like bool
is inhabited just by 2 values, true
and false
), and the ability to tell those 3 values apart from each other, i.e. the ability to test that e.g. red == red
and red != blue
are both true
.
In Haskell, such a type would be define with a one-liner:
data Color = Red | Green | Blue deriving Eq -- ctors have a capital first letter
but what about C++?
I've learned that enum
s can be tricky, so I was thinking of using std::variant
for the job.
The best I could come up with is the following:
namespace colors {
namespace detail {
inline constexpr struct Red{} red;
inline constexpr struct Green{} green;
inline constexpr struct Blue{} blue;
}
using detail::red;
using detail::green;
using detail::blue;
using Color = std::variant<detail::Red, detail::Green, detail::Blue>;
inline constexpr bool operator==(Color const& first, Color const& second) {
return first.index() == second.index();
}
inline constexpr bool operator!=(Color const& first, Color const& second) {
return !(first == second);
}
}
where I've enclosed the 3 types in the detail
namespace only to not clutter code completion lists of an IDE, as the client code would rarely need those 3 types, and will most often just use the 3 variables.
To me, using such a type seems seamless and convenient:
#include <cassert>
#include "the-file-above.hpp"
int main() {
using namespace colors;
Color color;
assert(color == red);
color = green;
assert(color == green);
color = blue;
assert(color == blue);
color = red;
assert(color == red);
}
Are there any objective reason why I should prefer the most basic enum
approach to this one, in terms of performance?