Tuesday Coding Tip 21 — Dangers of Enums

4 12 59
calendar_today agoschedule1 min read
— Originally published at medium.com

Tuesday coding tips are super short posts about various tidbits mainly from C++, but also from other programming languages I use. You can also follow the #TuesdayCodingTips hashtag on Mastodon and Linkedin.


C++ and C# have a caveat in their enum types. Each enum has an underlying storage type which limits a maximum number of values and how much space it takes in memory. However, it also works the other way — it says how many distinct values the enum handles.

If you define an enum with just three values, if it has an underlying type of uint8, it handles 256 distinct values. You can take any integer up to 255, cast it to that enum type, and get a “valid” value. When branching on an enum, you need to keep in mind that you might get an undefined value, especially if it was deserialized from the wire.

To add insult to injury, compilers won’t warn you by default. Only pattern matching does for C#. C++ can warn you if you don’t cover a defined enum value in a switch statement, but you must not use the default case — preventing you from correctly handling ill-formed values.

#include <iostream>

enum class Mode : char {
    Primary,
    Secondary
};

std::string to_string(Mode mode)
{   
    switch (mode)
    {
        case Mode::Primary: return "Primary";
        // With -Wswitch-enum
        // warning: enumeration value 'Secondary' not handled in switch
    }
}

std::string to_string2(Mode mode)
{
    switch (mode)
    {
        case Mode::Primary: return "Primary";
        // With -Wswitch-enum
        // no other warning
        default: return "Undefined";
    }
}

std::string to_string3(Mode mode)
{
    switch (mode)
    {
        case Mode::Primary: return "Primary";
        case Mode::Secondary: return "Secondary";
        // With -Wswitch-enum
        // no other warning
    }
}

int main()
{
    auto&& str = to_string3(static_cast<Mode>(42));
    std::cout << str << std::endl; // Output is an undefined behaviour
    return 0;
}
Part 21 of 21 in Tuesday Coding Tips
🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

Tuesday Coding Tip 06 - Explicit template instantiation

Jakub Neruda - Apr 7

Tuesday Coding Tip 02 - Template with type-specific API

Jakub Neruda - Mar 10

Tuesday Coding Tip 17 — Wrapping C APIs

Jakub Neruda - Jun 30

Tuesday Coding Tip 08 — Explicit template specialization

Jakub Neruda - Apr 21

Tuesday Coding Tip 05 - Object initialization in C++

Jakub Neruda - Mar 31
chevron_left
1.5k Points75 Badges
Brno, Czech Republiclinkedin.com/in/jakub-neruda
29Posts
27Comments
11Connections
Experienced C++ developer, team lead and hobby gamedev. I enjoy writing stuff about C++, clean code, clean architecture, and game development.

Related Jobs

View all jobs →

Commenters (This Week)

5 comments
2 comments

Contribute meaningful comments to climb the leaderboard and earn badges!