v0.6.2
This commit is contained in:
parent
16f010ef08
commit
68ad4fba4e
5 changed files with 43 additions and 35 deletions
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.6)
|
cmake_minimum_required(VERSION 3.6)
|
||||||
|
|
||||||
project(nameof VERSION "0.6.1" LANGUAGES CXX)
|
project(nameof VERSION "0.6.2" LANGUAGES CXX)
|
||||||
|
|
||||||
option(NAMEOF_OPT_BUILD_EXAMPLES "Build nameof examples" ON)
|
option(NAMEOF_OPT_BUILD_EXAMPLES "Build nameof examples" ON)
|
||||||
option(NAMEOF_OPT_BUILD_TESTS "Build and perform nameof tests" ON)
|
option(NAMEOF_OPT_BUILD_TESTS "Build and perform nameof tests" ON)
|
||||||
|
|
16
README.md
16
README.md
|
@ -15,7 +15,7 @@ master |[![Build Status](https://travis-ci.org/Neargye/nameof.svg?branch=master)
|
||||||
|
|
||||||
## What is Nameof?
|
## What is Nameof?
|
||||||
|
|
||||||
Header-only C++17 library provides nameof macros and functions to obtain the simple name of variable, type, function, macro, and enum.
|
Header-only C++17 library provides nameof macros and functions to obtain simple name of variable, type, function, macro, and enum.
|
||||||
|
|
||||||
Before, you had to use string literals to refer to definitions, which is brittle when renaming code elements because tools do not know to check these string literals.
|
Before, you had to use string literals to refer to definitions, which is brittle when renaming code elements because tools do not know to check these string literals.
|
||||||
|
|
||||||
|
@ -56,9 +56,9 @@ static_assert("foo" == cx_name);
|
||||||
* Name of enum
|
* Name of enum
|
||||||
```cpp
|
```cpp
|
||||||
// Name of enum
|
// Name of enum
|
||||||
const auto c = Color::RED;
|
auto c = Color::RED;
|
||||||
NAMEOF_ENUM(c) -> "RED"
|
NAMEOF_ENUM(c) -> "RED"
|
||||||
// Name of enum function
|
// Name of enum
|
||||||
nameof::nameof_enum(c) -> "RED"
|
nameof::nameof_enum(c) -> "RED"
|
||||||
|
|
||||||
constexpr auto cx_name = NAMEOF_ENUM(c);
|
constexpr auto cx_name = NAMEOF_ENUM(c);
|
||||||
|
@ -71,9 +71,9 @@ static_assert("RED" == cx_name);
|
||||||
NAMEOF_TYPE(Color::RED) -> "Color"
|
NAMEOF_TYPE(Color::RED) -> "Color"
|
||||||
// Name of type
|
// Name of type
|
||||||
NAMEOF_TYPE_T(int) -> "int"
|
NAMEOF_TYPE_T(int) -> "int"
|
||||||
// Name of variable type function
|
// Name of variable type
|
||||||
nameof::nameof_type(Color::RED) -> "Color"
|
nameof::nameof_type(Color::RED) -> "Color"
|
||||||
// Name of type function
|
// Name of type
|
||||||
nameof::nameof_type<int> -> "int"
|
nameof::nameof_type<int> -> "int"
|
||||||
|
|
||||||
constexpr auto cx_name = NAMEOF_TYPE(Color::RED);
|
constexpr auto cx_name = NAMEOF_TYPE(Color::RED);
|
||||||
|
@ -82,6 +82,7 @@ static_assert("Color" == cx_name);
|
||||||
|
|
||||||
* Name of macro
|
* Name of macro
|
||||||
```cpp
|
```cpp
|
||||||
|
// Name of macro
|
||||||
NAMEOF(__LINE__) -> "__LINE__"
|
NAMEOF(__LINE__) -> "__LINE__"
|
||||||
|
|
||||||
constexpr auto cx_name = NAMEOF(__LINE__);
|
constexpr auto cx_name = NAMEOF(__LINE__);
|
||||||
|
@ -92,12 +93,13 @@ static_assert("__LINE__" == cx_name);
|
||||||
|
|
||||||
* Nameof return std::string_view.
|
* Nameof return std::string_view.
|
||||||
|
|
||||||
* The argument expression identifies a code definition, but it is never evaluated.
|
* The argument expression identifies code definition, but it is never evaluated.
|
||||||
|
|
||||||
* If you need raw fully-qualified name, use NAMEOF_RAW.
|
* If you need raw fully-qualified name, use NAMEOF_RAW.
|
||||||
```cpp
|
```cpp
|
||||||
NAMEOF_RAW(somevar.somefield) -> "somevar.somefield"
|
NAMEOF_RAW(somevar.somefield) -> "somevar.somefield"
|
||||||
NAMEOF_RAW(&SomeStruct::SomeMethod) -> "&SomeStruct::SomeMethod"
|
NAMEOF_RAW(&SomeStruct::SomeMethod) -> "&SomeStruct::SomeMethod"
|
||||||
|
NAMEOF_RAW(std::string) -> "std::string"
|
||||||
```
|
```
|
||||||
|
|
||||||
* NAMEOF_ENUM does not work on the GCC.
|
* NAMEOF_ENUM does not work on the GCC.
|
||||||
|
@ -122,6 +124,6 @@ You should add required file [nameof.hpp](include/nameof.hpp).
|
||||||
* Clang/LLVM >= 5
|
* Clang/LLVM >= 5
|
||||||
* MSVC >= 15.3 / Visual Studio 2017
|
* MSVC >= 15.3 / Visual Studio 2017
|
||||||
* Xcode >= 9
|
* Xcode >= 9
|
||||||
* GCC >= 7 (NAMEOF_ENUM not support)
|
* GCC >= 7
|
||||||
|
|
||||||
## Licensed under the [MIT License](LICENSE)
|
## Licensed under the [MIT License](LICENSE)
|
||||||
|
|
|
@ -130,6 +130,7 @@ int main() {
|
||||||
std::cout << NAMEOF_RAW(__LINE__) << std::endl; // __LINE__
|
std::cout << NAMEOF_RAW(__LINE__) << std::endl; // __LINE__
|
||||||
std::cout << NAMEOF_RAW(structvar.somefield) << std::endl; // structvar.somefield
|
std::cout << NAMEOF_RAW(structvar.somefield) << std::endl; // structvar.somefield
|
||||||
std::cout << NAMEOF_RAW(&SomeStruct::SomeMethod1) << std::endl; // &SomeStruct::SomeMethod1
|
std::cout << NAMEOF_RAW(&SomeStruct::SomeMethod1) << std::endl; // &SomeStruct::SomeMethod1
|
||||||
|
std::cout << NAMEOF_RAW(const SomeClass<int> volatile *) << std::endl; // const SomeClass<int> volatile *
|
||||||
|
|
||||||
// Some more example.
|
// Some more example.
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// | |\ | (_| | | | | | | __/ (_) | | | |____|_| |_|
|
// | |\ | (_| | | | | | | __/ (_) | | | |____|_| |_|
|
||||||
// |_| \_|\__,_|_| |_| |_|\___|\___/|_| \_____|
|
// |_| \_|\__,_|_| |_| |_|\___|\___/|_| \_____|
|
||||||
// https://github.com/Neargye/nameof
|
// https://github.com/Neargye/nameof
|
||||||
// vesion 0.6.1
|
// vesion 0.6.2
|
||||||
//
|
//
|
||||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
@ -44,19 +44,19 @@ namespace nameof {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct identity {
|
struct identity final {
|
||||||
using type = T;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr bool is_name_char(char s) noexcept {
|
[[nodiscard]] constexpr bool is_name_char(char s) noexcept {
|
||||||
return (s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || s == '_';
|
return (s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || s == '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool is_bracket_char(char s) noexcept {
|
[[nodiscard]] constexpr bool is_bracket_char(char s) noexcept {
|
||||||
return s == ')' || s == '}' || s == '>' || s == '(' || s == '{' || s == '<';
|
return s == ')' || s == '}' || s == '>' || s == '(' || s == '{' || s == '<';
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr std::string_view pretty_name(std::string_view name, bool with_suffix) noexcept {
|
[[nodiscard]] constexpr std::string_view pretty_name(std::string_view name, bool with_suffix) noexcept {
|
||||||
for (std::size_t i = name.size(), h = 0, s = 0; i > 0; --i) {
|
for (std::size_t i = name.size(), h = 0, s = 0; i > 0; --i) {
|
||||||
if (h == 0 && !is_name_char(name[i - 1]) && !is_bracket_char(name[i - 1])) {
|
if (h == 0 && !is_name_char(name[i - 1]) && !is_bracket_char(name[i - 1])) {
|
||||||
++s;
|
++s;
|
||||||
|
@ -114,7 +114,7 @@ constexpr std::string_view pretty_name(std::string_view name, bool with_suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E>
|
template <typename E>
|
||||||
constexpr int nameof_enum_impl_() noexcept {
|
[[nodiscard]] constexpr int nameof_enum_impl_() noexcept {
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
return sizeof(__PRETTY_FUNCTION__) - sizeof("int nameof::detail::nameof_enum_impl_() [E = ") - sizeof("]") + 1;
|
return sizeof(__PRETTY_FUNCTION__) - sizeof("int nameof::detail::nameof_enum_impl_() [E = ") - sizeof("]") + 1;
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
|
@ -127,7 +127,7 @@ constexpr int nameof_enum_impl_() noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, E V>
|
template <typename E, E V>
|
||||||
constexpr std::string_view nameof_enum_impl() noexcept {
|
[[nodiscard]] constexpr std::string_view nameof_enum_impl() noexcept {
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
const auto str = __PRETTY_FUNCTION__;
|
const auto str = __PRETTY_FUNCTION__;
|
||||||
const auto size = sizeof(__PRETTY_FUNCTION__) - 1;
|
const auto size = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||||
|
@ -152,8 +152,8 @@ constexpr std::string_view nameof_enum_impl() noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, int V>
|
template <typename E, int V>
|
||||||
struct nameof_enum_t {
|
struct nameof_enum_t final {
|
||||||
constexpr std::string_view operator()(int value) const noexcept {
|
[[nodiscard]] constexpr std::string_view operator()(int value) const noexcept {
|
||||||
switch (value - V) {
|
switch (value - V) {
|
||||||
case 0:
|
case 0:
|
||||||
return nameof_enum_impl<E, E{V}>();
|
return nameof_enum_impl<E, E{V}>();
|
||||||
|
@ -178,13 +178,13 @@ struct nameof_enum_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename E>
|
template <typename E>
|
||||||
struct nameof_enum_t<E, NAMEOF_ENUM_MAX_SEARCH_DEPTH> {
|
struct nameof_enum_t<E, NAMEOF_ENUM_MAX_SEARCH_DEPTH> final {
|
||||||
constexpr std::string_view operator()(int) const noexcept {
|
[[nodiscard]] constexpr std::string_view operator()(int) const noexcept {
|
||||||
return {"nameof_enum::out_of_range"};
|
return {"nameof_enum::out_of_range"};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr std::string_view nameof_type_impl_(std::string_view name) noexcept {
|
[[nodiscard]] constexpr std::string_view nameof_type_impl_(std::string_view name) noexcept {
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
if (name.size() > sizeof("enum") && name[0] == 'e' && name[1] == 'n' && name[2] == 'u' && name[3] == 'm' && name[4] == ' ') {
|
if (name.size() > sizeof("enum") && name[0] == 'e' && name[1] == 'n' && name[2] == 'u' && name[3] == 'm' && name[4] == ' ') {
|
||||||
name.remove_prefix(sizeof("enum"));
|
name.remove_prefix(sizeof("enum"));
|
||||||
|
@ -204,7 +204,7 @@ constexpr std::string_view nameof_type_impl_(std::string_view name) noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr std::string_view nameof_type_impl() noexcept {
|
[[nodiscard]] constexpr std::string_view nameof_type_impl() noexcept {
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
const auto str = __PRETTY_FUNCTION__;
|
const auto str = __PRETTY_FUNCTION__;
|
||||||
const auto size = sizeof(__PRETTY_FUNCTION__) - 1;
|
const auto size = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||||
|
@ -229,49 +229,48 @@ constexpr std::string_view nameof_type_impl() noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename = std::enable_if_t<!std::is_reference_v<T>>>
|
template <typename T, typename = std::enable_if_t<!std::is_reference_v<T>>>
|
||||||
constexpr std::string_view nameof_impl(std::string_view name, bool with_suffix) noexcept {
|
[[nodiscard]] constexpr std::string_view nameof_impl(std::string_view name, bool with_suffix) noexcept {
|
||||||
return detail::pretty_name(name, with_suffix);
|
return detail::pretty_name(name, with_suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
[[nodiscard]] constexpr std::string_view nameof_raw_impl(std::string_view name) noexcept {
|
||||||
constexpr std::string_view nameof_raw_impl(std::string_view name) noexcept {
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T, typename = std::enable_if_t<std::is_enum_v<std::decay_t<T>>>>
|
template <typename T, typename = std::enable_if_t<std::is_enum_v<std::decay_t<T>>>>
|
||||||
constexpr std::string_view nameof_enum(T value) noexcept {
|
[[nodiscard]] constexpr std::string_view nameof_enum(T value) noexcept {
|
||||||
constexpr auto s = std::is_signed_v<std::underlying_type_t<std::decay_t<T>>>;
|
constexpr auto s = std::is_signed_v<std::underlying_type_t<std::decay_t<T>>>;
|
||||||
return detail::nameof_enum_t<std::decay_t<T>, s ? -NAMEOF_ENUM_MAX_SEARCH_DEPTH : 0>{}(static_cast<int>(value));
|
return detail::nameof_enum_t<std::decay_t<T>, s ? -NAMEOF_ENUM_MAX_SEARCH_DEPTH : 0>{}(static_cast<int>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr std::string_view nameof_type() noexcept {
|
[[nodiscard]] constexpr std::string_view nameof_type() noexcept {
|
||||||
return detail::nameof_type_impl<detail::identity<T>>();
|
return detail::nameof_type_impl<detail::identity<T>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr std::string_view nameof_type(T) noexcept {
|
[[nodiscard]] constexpr std::string_view nameof_type(T) noexcept {
|
||||||
return nameof_type<T>();
|
return nameof_type<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace nameof
|
} // namespace nameof
|
||||||
|
|
||||||
// Used to obtain the simple (unqualified) string name of variable, function, enum, macro.
|
// NAMEOF used to obtain the simple (unqualified) string name of variable, function, enum, macro.
|
||||||
#define NAMEOF(...) ::nameof::detail::nameof_impl<decltype(__VA_ARGS__)>(#__VA_ARGS__, false)
|
#define NAMEOF(...) ::nameof::detail::nameof_impl<decltype(__VA_ARGS__)>(#__VA_ARGS__, false)
|
||||||
|
|
||||||
// Used to obtain the full string name of variable, function, enum, macro.
|
// NAMEOF_FULL used to obtain the full string name of variable, function, enum, macro.
|
||||||
#define NAMEOF_FULL(...) ::nameof::detail::nameof_impl<decltype(__VA_ARGS__)>(#__VA_ARGS__, true)
|
#define NAMEOF_FULL(...) ::nameof::detail::nameof_impl<decltype(__VA_ARGS__)>(#__VA_ARGS__, true)
|
||||||
|
|
||||||
// Used to obtain the raw string name of variable, function, enum, macro.
|
// NAMEOF_ENUM used to obtain the simple (unqualified) string name of enum variable.
|
||||||
#define NAMEOF_RAW(...) ::nameof::detail::nameof_raw_impl<decltype(__VA_ARGS__)>(#__VA_ARGS__)
|
|
||||||
|
|
||||||
// Used to obtain the simple (unqualified) string name of enum variable.
|
|
||||||
#define NAMEOF_ENUM(...) ::nameof::nameof_enum<decltype(__VA_ARGS__)>(__VA_ARGS__)
|
#define NAMEOF_ENUM(...) ::nameof::nameof_enum<decltype(__VA_ARGS__)>(__VA_ARGS__)
|
||||||
|
|
||||||
// Used to obtain the string name of variable type.
|
// NAMEOF_TYPE used to obtain the string name of variable type.
|
||||||
#define NAMEOF_TYPE(...) ::nameof::nameof_type<decltype(__VA_ARGS__)>()
|
#define NAMEOF_TYPE(...) ::nameof::nameof_type<decltype(__VA_ARGS__)>()
|
||||||
|
|
||||||
// Used to obtain the string name of type.
|
// NAMEOF_TYPE_T used to obtain the string name of type.
|
||||||
#define NAMEOF_TYPE_T(...) ::nameof::nameof_type<__VA_ARGS__>()
|
#define NAMEOF_TYPE_T(...) ::nameof::nameof_type<__VA_ARGS__>()
|
||||||
|
|
||||||
|
// NAMEOF_RAW used to obtain the raw string name of variable, function, enum, macro.
|
||||||
|
#define NAMEOF_RAW(...) ::nameof::detail::nameof_raw_impl(#__VA_ARGS__)
|
||||||
|
|
|
@ -201,6 +201,12 @@ TEST_CASE("NAMEOF_RAW") {
|
||||||
REQUIRE(NAMEOF_RAW(__LINE__) == "__LINE__");
|
REQUIRE(NAMEOF_RAW(__LINE__) == "__LINE__");
|
||||||
REQUIRE(NAMEOF_RAW(__FILE__) == "__FILE__");
|
REQUIRE(NAMEOF_RAW(__FILE__) == "__FILE__");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("type") {
|
||||||
|
REQUIRE(NAMEOF_RAW(const SomeStruct volatile *) == "const SomeStruct volatile *");
|
||||||
|
REQUIRE(NAMEOF_RAW(SomeClass<int>) == "SomeClass<int>");
|
||||||
|
REQUIRE(NAMEOF_RAW(decltype(othervar)) == "decltype(othervar)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("NAMEOF_ENUM") {
|
TEST_CASE("NAMEOF_ENUM") {
|
||||||
|
|
Loading…
Reference in a new issue