NAV: Reflection on Enumeration Names and Values
Checklist
- Implement
NAV_DECLARE_ENUM
,NAV_DECLARE_ENUM_CLASS
andNAV_DECLARE_ENUM_STRUCT
without recursive macro instantiation - Remove limit on number of elements in an enumeration
- Support enumerations with non-trivial dependencies (these are enumerations whose values depend on other members of the enumeration)
- Support enumerations with arbitrarily large values, up to the numeric limits of the underlying integral type
- Avoid copying or returning large arrays by value (this speeds compile times)
- Avoid expensive type deductions (deducing a std::array type on a large number of values proved to be rather expensive)
- Make
nav::enum_names
andnav::enum_values
indexable and iterable - Make
nav::enum_names
andnav::enum_values
compile time constants - Store enumeration names in a contiguous block of memory to ensure good cache locality
- Provide option to null-terminate names (pass
-DNAV_ADD_NULL_TERMINATORS=1
to add null terminators after enum names) - Provide lowercase names for enum values (useful when writing CLIs and other applications that expose enumeration names to a user)
- Handle unknown enum types gracefully
- Handle compile-time string operations quickly and consistently via
nav::string_block
. This type represents a list of strings, backed together at compile time. It's iterable and provides random-access lookup of strings, and all strings are stored as a single contiguous block of memory, with (optional) null terminators between strings. Indexing into the block returns a string_view, and iterators fornav::string_block
similarly returnstring_view
s when dereferenced. - Get the minimum and maximum value in an enum
- Look up names from enumeration values
- Look up enumeration values from names
- Provide fast O(1) name lookup for compact enumerations (enumerations whose values fit in a reasonably small range)
- Look up lowercase names from values
- Look up values from lowercase names
- Provide functions for fuzzy matching on enum names. This is useful for reporting errors to a user. You can provide suggestions, like "You put X. Did you mean Y?"
- Provide charconv conversion functions
- Provide optional integration with libfmt (
#include <nav/nav_libfmt.hpp>
) - Provide optional integration for printing to ostreams
(
#include <nav/nav_iostream.hpp>
) - Benchmark compile times against other well-established enumeration reflection libraries
- Benchmark runtime performance against enum reflection in other languages (Java, Rust)
Graceful handling of unknown enumerations
Nav handles unknown enumerations gracefully. is_nav_enum<EnumType>
is false
for unknown enumerations, the number of states will be reported as 0, and the
number of names and values will be reported as 0 too. The type name and
qualified type name for the enumeration will be deduced via
nav::get_name_of_type()
, which is a generic function that can get the name of
most types.
// Snapshot of test code taken from tests/nav_core.cpp
enum class UnknownEnum { A, B, C };
CHECK(nav::enum_type_info<UnknownEnum>::type_name == "UnknownEnum");
REQUIRE_FALSE(nav::is_nav_enum<UnknownEnum>);
REQUIRE(nav::enum_names<UnknownEnum>.size() == 0);
REQUIRE(nav::enum_names<UnknownEnum>.begin() == nav::enum_names<UnknownEnum>.end());
REQUIRE(nav::enum_values<UnknownEnum>.size() == 0);
REQUIRE(nav::enum_values<UnknownEnum>.begin() == nav::enum_values<UnknownEnum>.end());
Nav supports non-trivial enumerations
Here, some members of the RainbowColors enumeration are declared in terms of preceeding members. For example, Green is defined in terms of Yellow and Red
nav_declare_enum_class(
RainbowColors,
int,
Red = 0xff0000,
Orange = (Red + 0xffff00) / 2 & 0xffff00,
Yellow = 0xffff00,
Green = Yellow - Red,
Blue = 0x0000ff,
Indigo = 0x8A2BE2,
Violet = Red + Blue);
Comparisons against other libraries
nav | magic_enum | better-enums | enum.hpp | wise_enum | |
---|---|---|---|---|---|
Requires macro | Yes | No | Yes | Yes | Yes |
Limits on min/max value? | No | Yes | |||
Limits on number of values? | No | Yes | |||
Supports aliased values? | Yes | No | |||
Supports using enum? | Yes | Yes | No | Yes | |
Special Declaration Syntax? | No | No | Yes | ||
Compact Names in Binary? | Yes | No | |||
Fuzzy Matching Support | Yes | No | |||
Lowercase name lookup | Yes | Yes | |||
libfmt support | Yes | ||||
charconv support | Yes |