Accidental recursion

Author:Wojciech Muła
Added on:2018-04-14

Another bug I bumped into. There is the enum:

enum class Color {
    red,
    green
};

And the associated ostream operator, which is merely a switch; all operators for enums looks like this.

std::ostream& operator<<(std::ostream& s, const Color c) {
    switch (c) {
        case Color::red:
            s << "red";
            break;

        case Color::green:
            s << "green";
            break;

        default:
            s << "invalid " << c;
            break;
    }

    return s;
}

The author clearly wanted to handle all possible cases, including invalid enum values, that might appear due to memory corruption or simply as a result of invalid casting. Sadly, the handler would fail in such an erroneous case --- there is an infinite recursion in the default case.

The correct solution would be extract enumeration type and print it as a numeric value:

default:
    s << "unknown " << static_cast<std::underlying_type<Color>::type>(c);
    break;

This is not the nicest code in the world, but does the job well.