diff --git a/README.md b/README.md index 41c69d0..74dc18d 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,11 @@ Header-only C++17 library provides nameof macros and functions to simply obtain * Name of macro * Enum to string +## Documentation + +* [Reference](doc/reference.md) +* [limitations](doc/limitations.md) + ## [Examples](example/example.cpp) * Nameof @@ -97,92 +102,6 @@ Header-only C++17 library provides nameof macros and functions to simply obtain // type_name -> "int" ``` -## Remarks - -* Nameof returns `std::string_view`. If argument does not have name, returns empty string. - -* Nameof expression argument are identified, but are not evaluated. - -* Nameof type returns compiler-specific type name. In all cases, reference and cv-qualifiers are ignored by `nameof_type` (that is, `nameof_type() == nameof_type()`). If you need detailed name of full type, use `nameof_full_type`. - -* If you need name with template suffix, use NAMEOF_FULL. - ```cpp - // Full name of template function. - NAMEOF_FULL(foo()) -> "foo" - - // Full name of template member function. - NAMEOF_FULL(somevar.some_method()) -> "some_method" - ``` - -* If you need raw fully-qualified name, use NAMEOF_RAW. - ```cpp - NAMEOF_RAW(::somevar.somefield) -> "::somevar.somefield" - NAMEOF_RAW(&some_class::some_method) -> "&some_class::some_method" - ``` - -* Enum value must be in range `[NAMEOF_ENUM_RANGE_MIN, NAMEOF_ENUM_RANGE_MAX]`. By default `NAMEOF_ENUM_RANGE_MIN = -128`, `NAMEOF_ENUM_RANGE_MAX = 128`. - - If need another range for all enum types by default, redefine the macro `NAMEOF_ENUM_RANGE_MIN` and `NAMEOF_ENUM_RANGE_MAX`. - ```cpp - #define NAMEOF_ENUM_RANGE_MIN 0 - #define NAMEOF_ENUM_RANGE_MAX 256 - #include - ``` - - If need another range for specific enum type, add specialization `enum_range` for necessary enum type. - ```cpp - #include - - enum number { one = 100, two = 200, three = 300 }; - - namespace nameof { - template <> - struct enum_range { - static constexpr int min = 100; - static constexpr int max = 300; - }; - } - ``` - -* Nameof enum obtains the first defined value enums, and won't work if value are aliased. - ```cpp - enum ShapeKind { - ConvexBegin = 0, - Box = 0, // Won't work. - Sphere = 1, - ConvexEnd = 2, - Donut = 2, // Won't work too. - Banana = 3, - COUNT = 4, - }; - // NAMEOF_ENUM(ShapeKind::Box) -> "ConvexBegin" - // nameof::nameof_enum(ShapeKind::Box) -> "ConvexBegin" - ``` - Work around the issue: - ```cpp - enum ShapeKind { - // Convex shapes, see ConvexBegin and ConvexEnd below. - Box = 0, - Sphere = 1, - - // Non-convex shapes. - Donut = 2, - Banana = 3, - - COUNT = Banana + 1, - - // Non-reflected aliases. - ConvexBegin = Box, - ConvexEnd = Sphere + 1, - }; - // NAMEOF_ENUM(ShapeKind::Box) -> "Box" - // nameof::nameof_enum(ShapeKind::Box) -> "Box" - - // Non-reflected aliases. - // NAMEOF_ENUM(ShapeKind::ConvexBegin) -> "Box" - // nameof::nameof_enum(ShapeKind::ConvexBegin) -> "Box" - ``` - ## Integration You should add required file [nameof.hpp](include/nameof.hpp). diff --git a/doc/limitations.md b/doc/limitations.md new file mode 100644 index 0000000..72e4370 --- /dev/null +++ b/doc/limitations.md @@ -0,0 +1,82 @@ +# Nameof + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +# Nameof Type + +* This library uses a compiler-specific hack (based on `__PRETTY_FUNCTION__` / `__FUNCSIG__`), which works on Clang >= 5, MSVC >= 15.3 and GCC >= 7. + +* Nameof type returns compiler-specific type name. + +* In all cases, reference and cv-qualifiers are ignored by `nameof_type` (that is, `nameof_type() == nameof_type()`). + +* If you need detailed name of full type, use `nameof_full_type`. + +# Nameof Enum + +* This library uses a compiler-specific hack (based on `__PRETTY_FUNCTION__` / `__FUNCSIG__`), which works on Clang >= 5, MSVC >= 15.3 and GCC >= 9. + +* Enum can't reflect if the enum is a forward declaration. + +* Enum value must be in range `[MAGIC_ENUM_RANGE_MIN, MAGIC_ENUM_RANGE_MAX]`. By default `MAGIC_ENUM_RANGE_MIN = -128`, `MAGIC_ENUM_RANGE_MAX = 128`. + +* If need another range for all enum types by default, redefine the macro `MAGIC_ENUM_RANGE_MIN` and `MAGIC_ENUM_RANGE_MAX`. + ```cpp + #define MAGIC_ENUM_RANGE_MIN 0 + #define MAGIC_ENUM_RANGE_MAX 256 + #include + ``` + +* If need another range for specific enum type, add specialization `enum_range` for necessary enum type. + ```cpp + #include + + enum number { one = 100, two = 200, three = 300 }; + + namespace magic_enum { + template <> + struct enum_range { + static constexpr int min = 100; + static constexpr int max = 300; + }; + } + ``` + +* `magic_enum` obtains the first defined value enums, and won't work if value are aliased. + ```cpp + enum ShapeKind { + ConvexBegin = 0, + Box = 0, // Won't work. + Sphere = 1, + ConvexEnd = 2, + Donut = 2, // Won't work too. + Banana = 3, + COUNT = 4, + }; + // magic_enum::enum_cast("Box") -> std::nullopt + // magic_enum::enum_name(ShapeKind::Box) -> "ConvexBegin" + ``` + Work around the issue: + ```cpp + enum ShapeKind { + // Convex shapes, see ConvexBegin and ConvexEnd below. + Box = 0, + Sphere = 1, + + // Non-convex shapes. + Donut = 2, + Banana = 3, + + COUNT = Banana + 1, + + // Non-reflected aliases. + ConvexBegin = Box, + ConvexEnd = Sphere + 1, + }; + // magic_enum::enum_cast("Box") -> ShapeKind::Box + // magic_enum::enum_name(ShapeKind::Box) -> "Box" + + // Non-reflected aliases. + // magic_enum::enum_cast("ConvexBegin") -> std::nullopt + // magic_enum::enum_name(ShapeKind::ConvexBegin) -> "Box" + ``` diff --git a/doc/reference.md b/doc/reference.md new file mode 100644 index 0000000..dfb61f0 --- /dev/null +++ b/doc/reference.md @@ -0,0 +1,236 @@ +# Reference + +* [`NAMEOF` macro that obtains simple (unqualified) string name of variable, function, macro.](#NAMEOF) +* [`NAMEOF_FULL` macro that obtains simple (unqualified) full (with template suffix) string name of variable, function, macro.](#NAMEOF_FULL) +* [`NAMEOF_RAW` macro that obtains raw string name of variable, function, macro.](#NAMEOF_RAW) +* [`nameof_enum(E value)` function that obtains simple (unqualified) string enum name of enum variable.](#nameof_enum(value)) +* [`nameof_enum()` function that obtains simple (unqualified) string enum name of static storage enum variable.](#nameof_enum()) +* [`NAMEOF_ENUM` macro that obtains simple (unqualified) string enum name of enum variable.](#NAMEOF_ENUM) +* [`NAMEOF_CONST_ENUM` macro that obtains simple (unqualified) string enum name of static storage enum variable.](#NAMEOF_CONST_ENUM) +* [`nameof_type()` function that obtains string name of type, reference and cv-qualifiers are ignored.](#nameof_type()) +* [`nameof_full_type()` function that obtains string name of full type, with reference and cv-qualifiers.](#nameof_full_type()) +* [`NAMEOF_TYPE` macro that obtains string name of type, reference and cv-qualifiers are ignored.](#NAMEOF_TYPE) +* [`NAMEOF_FULL_TYPE` macro that obtains string name of full type, with reference and cv-qualifiers.](#NAMEOF_FULL_TYPE) +* [`NAMEOF_TYPE_EXPR` macro that obtains string name type of expression, reference and cv-qualifiers are ignored.](#NAMEOF_TYPE_EXPR) +* [`NAMEOF_FULL_TYPE_EXPR` macro that obtains string name full type of expression, with reference and cv-qualifiers.](#NAMEOF_FULL_TYPE_EXPR) + +## `NAMEOF` + +* Macro that obtains simple (unqualified) string name of variable, function, macro. + +* Returns `nameof::cstring` - constexpr implementation of an string. + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +* Examples + ```cpp + // Name of variable. + NAMEOF(somevar) -> "somevar" + + // Name of member variable. + NAMEOF(person.address.zip_code) -> "zip_code" + + // Name of function. + NAMEOF(foo()) -> "foo" + + // Name of member function. + NAMEOF(somevar.some_method()) -> "some_method" + NAMEOF(somevar.some_method()) -> "some_method" + + // Name of macro. + NAMEOF(__LINE__) -> "__LINE__" + NAMEOF(NAMEOF(structvar)) -> "NAMEOF" + ``` + +## `NAMEOF_FULL` + +* Macro that obtains simple (unqualified) full (with template suffix) string name of variable, function, macro. + +* Returns `nameof::cstring` - constexpr implementation of an string. + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +* Examples + ```cpp + // Full name of template function. + NAMEOF_FULL(foo()) -> "foo" + + // Full name of template member function. + NAMEOF_FULL(somevar.some_method()) -> "some_method" + ``` + +## `NAMEOF_RAW` + +* Macro that obtains raw string name of variable, function, macro. + +* Returns `nameof::cstring` - constexpr implementation of an string. + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +* Examples + ```cpp + NAMEOF_RAW(::somevar.somefield) -> "::somevar.somefield" + NAMEOF_RAW(&some_class::some_method) -> "&some_class::some_method" + ``` + +## `nameof_enum(value)` + +* Function that obtains simple (unqualified) string enum name of enum variable. + +* Returns `std::string_view`. + +* If argument does not have name, returns empty `std::string_view`. + +* Examples + ```cpp + auto color = Color::RED; + nameof::nameof_enum(color) -> "RED" + ``` + +## `nameof_enum()` + +* Function that obtains simple (unqualified) string enum name of static storage enum variable. + +* Returns `std::string_view`. + +* This version is much lighter on the compile times and is not restricted to the enum_range [limitation](limitations.md). + +* If argument does not have name, returns empty `std::string_view`. + +* Examples + ```cpp + nameof::nameof_enum() -> "GREEN" + ``` + +## `NAMEOF_ENUM` + +* Macro that obtains simple (unqualified) string enum name of enum variable. + +* Returns `std::string_view`. + +* If argument does not have name, returns empty `std::string_view`. + +* Examples + ```cpp + auto color = Color::RED; + NAMEOF_ENUM(color) -> "RED" + ``` + +## `NAMEOF_CONST_ENUM` + +* Macro macro that obtains simple (unqualified) string enum name of static storage enum variable. + +* Returns `std::string_view`. + +* This version is much lighter on the compile times and is not restricted to the enum_range [limitation](limitations.md). + +* If argument does not have name, returns empty `std::string_view`. + +* Examples + ```cpp + NAMEOF_CONST_ENUM(Color::GREEN) -> "GREEN" + ``` + +## `nameof_type()` + +* Function macro that obtains string name of type, reference and cv-qualifiers are ignored. + +* Returns `nameof::cstring` - constexpr implementation of an string. + +* In all cases, reference and cv-qualifiers are ignored by `nameof_type` (that is, `nameof_type() == nameof_type()`). + +* Returns compiler-specific type name. + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +* Examples + ```cpp + using T = const int&; + nameof::nameof_type() -> "int" + ``` + +## `nameof_full_type()` + +* Function that obtains string name of full type, with reference and cv-qualifiers. + +* Returns `nameof::cstring` - constexpr implementation of an string. + +* Returns compiler-specific type name. + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +* Examples + ```cpp + using T = const int&; + nameof::nameof_full_type() -> "const int&" + ``` + +## `NAMEOF_TYPE` + +* Macro macro that obtains string name of type, reference and cv-qualifiers are ignored. + +* Returns `nameof::cstring` - constexpr implementation of an string. + +* In all cases, reference and cv-qualifiers are ignored by `NAMEOF_TYPE` (that is, `NAMEOF_TYPE(const T&) == NAMEOF_TYPE(T)`). + +* Returns compiler-specific type name. + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +* Examples + ```cpp + using T = const int&; + NAMEOF_TYPE(T) -> "int" + ``` + +## `NAMEOF_FULL_TYPE` + +* Macro that obtains string name of full type, with reference and cv-qualifiers. + +* Returns `nameof::cstring` - constexpr implementation of an string. + +* Returns compiler-specific type name. + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +* Examples + ```cpp + using T = const int&; + NAMEOF_TYPE(T) -> "const int&" + ``` + +## `NAMEOF_TYPE_EXPR` + +* Macro that obtains string name type of expression, reference and cv-qualifiers are ignored. + +* Returns `nameof::cstring` - constexpr implementation of an string. + +* Returns returns compiler-specific type name. + +* In all cases, reference and cv-qualifiers are ignored. + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +* Examples + ```cpp + using T = const int&; + T var = 42; + NAMEOF_TYPE_EXPR(var) -> "int" + ``` + +## `NAMEOF_TYPE_EXPR` + +* Macro that obtains string name full type of expression, with reference and cv-qualifiers. + +* Returns `nameof::cstring` - constexpr implementation of an string. + +* Returns compiler-specific type name. + +* If argument does not have name, occurs the compilation error `"Expression does not have a name."`. + +* Examples + ```cpp + using T = const int&; + T var = 42; + NAMEOF_FULL_TYPE_EXPR(var) -> "const int&" + ```