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)
|
||||
|
||||
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_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?
|
||||
|
||||
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.
|
||||
|
||||
|
@ -56,9 +56,9 @@ static_assert("foo" == cx_name);
|
|||
* Name of enum
|
||||
```cpp
|
||||
// Name of enum
|
||||
const auto c = Color::RED;
|
||||
auto c = Color::RED;
|
||||
NAMEOF_ENUM(c) -> "RED"
|
||||
// Name of enum function
|
||||
// Name of enum
|
||||
nameof::nameof_enum(c) -> "RED"
|
||||
|
||||
constexpr auto cx_name = NAMEOF_ENUM(c);
|
||||
|
@ -71,9 +71,9 @@ static_assert("RED" == cx_name);
|
|||
NAMEOF_TYPE(Color::RED) -> "Color"
|
||||
// Name of type
|
||||
NAMEOF_TYPE_T(int) -> "int"
|
||||
// Name of variable type function
|
||||
// Name of variable type
|
||||
nameof::nameof_type(Color::RED) -> "Color"
|
||||
// Name of type function
|
||||
// Name of type
|
||||
nameof::nameof_type<int> -> "int"
|
||||
|
||||
constexpr auto cx_name = NAMEOF_TYPE(Color::RED);
|
||||
|
@ -82,6 +82,7 @@ static_assert("Color" == cx_name);
|
|||
|
||||
* Name of macro
|
||||
```cpp
|
||||
// Name of macro
|
||||
NAMEOF(__LINE__) -> "__LINE__"
|
||||
|
||||
constexpr auto cx_name = NAMEOF(__LINE__);
|
||||
|
@ -92,12 +93,13 @@ static_assert("__LINE__" == cx_name);
|
|||
|
||||
* 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.
|
||||
```cpp
|
||||
NAMEOF_RAW(somevar.somefield) -> "somevar.somefield"
|
||||
NAMEOF_RAW(&SomeStruct::SomeMethod) -> "&SomeStruct::SomeMethod"
|
||||
NAMEOF_RAW(std::string) -> "std::string"
|
||||
```
|
||||
|
||||
* 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
|
||||
* MSVC >= 15.3 / Visual Studio 2017
|
||||
* Xcode >= 9
|
||||
* GCC >= 7 (NAMEOF_ENUM not support)
|
||||
* GCC >= 7
|
||||
|
||||
## Licensed under the [MIT License](LICENSE)
|
||||
|
|
|
@ -130,6 +130,7 @@ int main() {
|
|||
std::cout << NAMEOF_RAW(__LINE__) << std::endl; // __LINE__
|
||||
std::cout << NAMEOF_RAW(structvar.somefield) << std::endl; // structvar.somefield
|
||||
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.
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// | |\ | (_| | | | | | | __/ (_) | | | |____|_| |_|
|
||||
// |_| \_|\__,_|_| |_| |_|\___|\___/|_| \_____|
|
||||
// https://github.com/Neargye/nameof
|
||||
// vesion 0.6.1
|
||||
// vesion 0.6.2
|
||||
//
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
@ -44,19 +44,19 @@ namespace nameof {
|
|||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
struct identity {
|
||||
struct identity final {
|
||||
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 == '_';
|
||||
}
|
||||
|
||||
constexpr bool is_bracket_char(char s) noexcept {
|
||||
[[nodiscard]] constexpr bool is_bracket_char(char s) noexcept {
|
||||
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) {
|
||||
if (h == 0 && !is_name_char(name[i - 1]) && !is_bracket_char(name[i - 1])) {
|
||||
++s;
|
||||
|
@ -114,7 +114,7 @@ constexpr std::string_view pretty_name(std::string_view name, bool with_suffix)
|
|||
}
|
||||
|
||||
template <typename E>
|
||||
constexpr int nameof_enum_impl_() noexcept {
|
||||
[[nodiscard]] constexpr int nameof_enum_impl_() noexcept {
|
||||
#if defined(__clang__)
|
||||
return sizeof(__PRETTY_FUNCTION__) - sizeof("int nameof::detail::nameof_enum_impl_() [E = ") - sizeof("]") + 1;
|
||||
#elif defined(__GNUC__)
|
||||
|
@ -127,7 +127,7 @@ constexpr int nameof_enum_impl_() noexcept {
|
|||
}
|
||||
|
||||
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__)
|
||||
const auto str = __PRETTY_FUNCTION__;
|
||||
const auto size = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||
|
@ -152,8 +152,8 @@ constexpr std::string_view nameof_enum_impl() noexcept {
|
|||
}
|
||||
|
||||
template <typename E, int V>
|
||||
struct nameof_enum_t {
|
||||
constexpr std::string_view operator()(int value) const noexcept {
|
||||
struct nameof_enum_t final {
|
||||
[[nodiscard]] constexpr std::string_view operator()(int value) const noexcept {
|
||||
switch (value - V) {
|
||||
case 0:
|
||||
return nameof_enum_impl<E, E{V}>();
|
||||
|
@ -178,13 +178,13 @@ struct nameof_enum_t {
|
|||
};
|
||||
|
||||
template <typename E>
|
||||
struct nameof_enum_t<E, NAMEOF_ENUM_MAX_SEARCH_DEPTH> {
|
||||
constexpr std::string_view operator()(int) const noexcept {
|
||||
struct nameof_enum_t<E, NAMEOF_ENUM_MAX_SEARCH_DEPTH> final {
|
||||
[[nodiscard]] constexpr std::string_view operator()(int) const noexcept {
|
||||
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 (name.size() > sizeof("enum") && name[0] == 'e' && name[1] == 'n' && name[2] == 'u' && name[3] == 'm' && name[4] == ' ') {
|
||||
name.remove_prefix(sizeof("enum"));
|
||||
|
@ -204,7 +204,7 @@ constexpr std::string_view nameof_type_impl_(std::string_view name) noexcept {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr std::string_view nameof_type_impl() noexcept {
|
||||
[[nodiscard]] constexpr std::string_view nameof_type_impl() noexcept {
|
||||
#if defined(__clang__)
|
||||
const auto str = __PRETTY_FUNCTION__;
|
||||
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>>>
|
||||
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);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr std::string_view nameof_raw_impl(std::string_view name) noexcept {
|
||||
[[nodiscard]] constexpr std::string_view nameof_raw_impl(std::string_view name) noexcept {
|
||||
return name;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
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>>>;
|
||||
return detail::nameof_enum_t<std::decay_t<T>, s ? -NAMEOF_ENUM_MAX_SEARCH_DEPTH : 0>{}(static_cast<int>(value));
|
||||
}
|
||||
|
||||
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>>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr std::string_view nameof_type(T) noexcept {
|
||||
[[nodiscard]] constexpr std::string_view nameof_type(T) noexcept {
|
||||
return nameof_type<T>();
|
||||
}
|
||||
|
||||
} // 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)
|
||||
|
||||
// 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)
|
||||
|
||||
// Used to obtain the raw string name of variable, function, enum, macro.
|
||||
#define NAMEOF_RAW(...) ::nameof::detail::nameof_raw_impl<decltype(__VA_ARGS__)>(#__VA_ARGS__)
|
||||
|
||||
// Used to obtain the simple (unqualified) string name of enum variable.
|
||||
// NAMEOF_ENUM used to obtain the simple (unqualified) string name of enum variable.
|
||||
#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__)>()
|
||||
|
||||
// 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__>()
|
||||
|
||||
// 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(__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") {
|
||||
|
|
Loading…
Reference in a new issue