MRDOCS_DESCRIBE_ENUM
Describe the enumerators of an enum.
Description
Pass the enum type followed by the enumerators you want to describe, up to 128 of them. Place it at namespace scope, in the same namespace as the enum, after the enum definition:
namespace shapes {
enum class Shape { Circle, RoundedRect, Triangle };
MRDOCS_DESCRIBE_ENUM(Shape, Circle, RoundedRect, Triangle)
} // namespace shapes
The macro declares a function that is found by argument‐dependent lookup and whose return type lists one descriptor per enumerator:
// Simplified: whitespace changed; each lambda is a distinct closure
// type that only returns the stringized enumerator name.
// MRDOCS_DESCRIBE_ENUM(Shape, Circle, RoundedRect, Triangle)
static_assert(std::is_enum_v<Shape>,
"MRDOCS_DESCRIBE_ENUM should only be used with enums");
[[maybe_unused]]
decltype(::mrdocs::describe::detail::enum_descriptor_fn_impl(0
, ::mrdocs::describe::detail::enum_descriptor<
Shape::Circle, []{ return "Circle"; }>{}
, ::mrdocs::describe::detail::enum_descriptor<
Shape::RoundedRect, []{ return "RoundedRect"; }>{}
, ::mrdocs::describe::detail::enum_descriptor<
Shape::Triangle, []{ return "Triangle"; }>{}
)) mrdocs_enum_descriptor_fn(Shape**);
// The return type is describe::list<D1, D2, D3>, where each Di has
// `static constexpr Shape value` and `static constexpr char const*
// name`. The function is declared only; it's never called.
Afterwards the enum works with the describe queries and the string helpers, all usable in constant expressions:
namespace describe = mrdocs::describe;
using shapes::Shape;
static_assert(describe::has_describe_enumerators<Shape>::value);
// Kebab-case name, as used in the generated output
static_assert(mrdocs::toString(Shape::RoundedRect) == "rounded-rect");
// Declared name
static_assert(
describe::enum_to_string(Shape::RoundedRect) == "RoundedRect");
void
demo()
{
// Declared name back to the enumerator
Shape s{};
bool ok = describe::enum_from_string("Triangle", s);
// ok == true, s == Shape::Triangle
// Visit every described enumerator
describe::for_each(
describe::describe_enumerators<Shape>{},
[](auto d) {
// d.value: Shape::Circle, then RoundedRect, then Triangle
// d.name: "Circle", then "RoundedRect", then "Triangle"
});
}
Things to keep in mind:
-
Don't put it inside a class, even for a nested enum. There it declares a member function that lookup never finds, so the enum silently stays undescribed. For a nested enum, write it at namespace scope after the class and qualify the type:
MRDOCS_DESCRIBE_ENUM(Canvas::Layer, background, foreground). -
Writing it in a different namespace also leaves the enum undescribed, for the same reason.
-
It already ends with a semicolon, so don't add one.
-
Enumerators you leave out are unknown to the helpers:
toStringanddescribe::enum_to_stringreturn an empty string for them, anddescribe::enum_from_stringnever produces them. -
Works for scoped and unscoped enums, since each entry is spelled
E::name. -
When the enumerators already live in an X‐macro
.incfile, useMRDOCS_DESCRIBE_ENUM_BEGINandMRDOCS_DESCRIBE_ENUM_ENDinstead. They also have no limit on the number of enumerators. -
To mark one enumerator as the empty state, follow it with
MRDOCS_DESCRIBE_ENUM_UNDEFINED.
Parameters
Name |
Description |
E |
The enum type. |
Created with MrDocs