62 lines
2.8 KiB
Text
62 lines
2.8 KiB
Text
# Hook
|
|
"There should be one, and preferably only one, obvious way to do it." --- The Zen of Python
|
|
A principle which C++ defies in many fronts, enums being one of them,
|
|
assuming you know the basics, let's learn more about enums!
|
|
|
|
# Ways to declare enums
|
|
There are mainly 3 ways we could declare one.
|
|
|
|
1: The classic -- unscoped enum
|
|
-> Which allows implicit conversion to integer types
|
|
-> And pollutes the enclosing namespace
|
|
-> Pretty dangerous
|
|
|
|
2: The modern -- scoped enum, using the `class` (or `struct`) keywrod
|
|
-> Which prohibits implicit conversions (even to the direct underlying type)
|
|
-> And requires proper qualification when accessing its elements
|
|
|
|
3: The anonymous enum
|
|
-> Much like the classic enum, but without a qualifier
|
|
-> It was used as a way of storing constants before constexprs were a thing
|
|
-> There's a neat trick you coud do with anonymous or unscoped enums, and that is to put it inside a namespace and have the middle-ground of scoped and unscoped enums
|
|
-> It allows implicit conversion to integer types.
|
|
-> But, it still requires proper qualification when accessing its elements. And won't pollute the enclosing namespace.
|
|
|
|
# Which is the way?
|
|
But what's the right way?
|
|
That depends on how you wanna shoot yourself in the foot.
|
|
|
|
1- Use the classic one when writing C or your C++ is too old.
|
|
2- Use the namespace trick when you can't be arsed to explicitly convert.
|
|
3- And prefer the scoped enum in literary all the other cases.
|
|
|
|
Now, let's get to some tips and tricks...
|
|
# Tips & Tricks
|
|
1: Prefer Scoped Enums.
|
|
Explicit is safer than implicit
|
|
|
|
2: Specify the Underlying Type
|
|
Like this! always do this, even if the type is int--- It serves as documentation and explicitly states your intent.
|
|
|
|
3: Avoid the "default" Case
|
|
This may be too much in certain cases, but try to develop a preference for explicitly handling all enums values.
|
|
Even if multiple values execute the same code, you could fall-through them if you don't put breaks in-between.
|
|
You could enable warnings as errors for catching incomplete switch statements.
|
|
So when you inevitably add new values to your enums, the compiler will have your back.
|
|
|
|
4: Utilize [Dio: ZERO]
|
|
Since zero evaluates to false, and other values to true, you could treat it as a special value for making a binary decision.
|
|
For example, in Vulkan API, the VkResult has 0 for success, and errors are set to non-zero values.
|
|
This makes the decision to handle-error or move-on a binary decision like this.
|
|
|
|
5: Utilize Its Counting Nature
|
|
The values are implicitly incremented, this means you could have a "count" element at the end like so.
|
|
|
|
6: (Are you using it as a) Bitfield? (Then consider) Overload(ing) the Bitwise Operators.
|
|
|
|
|
|
|
|
# Zoom out to outro...
|
|
Anyways! Here are some enum utilities from the standard library...
|
|
If you want more of these kind of videos, consider subscribing.
|
|
chao ^~^!
|