MRDOCS_DESCRIBE_ENUM_UNDEFINED

Mark one enumerator as the enum's undefined (empty) state.

Synopsis

#define MRDOCS_DESCRIBE_ENUM_UNDEFINED(E, U)

Description

Some enums have a value that means "not set", like None. Marking it makes the string helpers treat it as empty, and makes generators treat a field holding it as absent (an empty optional) instead of printing it. Place it at namespace scope, in the namespace of the enum, after the enum's MRDOCS_DESCRIBE_ENUM:

namespace shapes {

enum class Fill { None, Solid, Hatched };

MRDOCS_DESCRIBE_ENUM(Fill, None, Solid, Hatched)
MRDOCS_DESCRIBE_ENUM_UNDEFINED(Fill, None)

} // namespace shapes

It expands to a small function that ADL finds from the enum type:

// MRDOCS_DESCRIBE_ENUM_UNDEFINED(Fill, None)
[[maybe_unused]]
inline constexpr Fill
mrdocs_undefined_descriptor_fn(Fill**) noexcept { return Fill::None; }

Afterwards:

namespace describe = mrdocs::describe;
using shapes::Fill;

static_assert(describe::has_undefined_enumerator<Fill>);
static_assert(describe::undefined_enumerator<Fill> == Fill::None);

// The undefined state renders as the empty string
static_assert(mrdocs::toString(Fill::None).empty());
static_assert(describe::enum_to_string(Fill::None).empty());
static_assert(mrdocs::toString(Fill::Solid) == "solid");

void
demo()
{
    // and the empty string parses back to it
    Fill f = Fill::Solid;
    describe::enum_from_string("", f); // returns true, f == Fill::None
}

Things to keep in mind:

  • Use it at most once per enum; a second use is a redefinition error.

  • Like MRDOCS_DESCRIBE_ENUM, it must be in the namespace of the enum and not inside a class, or lookup won't find it.

  • The function is inline, so it's safe in headers.

  • It ends with a closing brace, so don't add a semicolon.

Parameters

Name

Description

E

The enum type.

U

The enumerator that represents the undefined state, written without the E:: prefix.

Created with MrDocs