add nameof_member
This commit is contained in:
parent
6df582978d
commit
2cf013dbf3
3 changed files with 86 additions and 0 deletions
|
@ -168,6 +168,15 @@ int main() {
|
||||||
std::cout << NAMEOF_FULL_TYPE_EXPR(std::declval<const SomeClass<int>>()) << std::endl; // 'const SomeClass<int> &&'
|
std::cout << NAMEOF_FULL_TYPE_EXPR(std::declval<const SomeClass<int>>()) << std::endl; // 'const SomeClass<int> &&'
|
||||||
std::cout << NAMEOF_SHORT_TYPE_EXPR(std::declval<const SomeClass<int>>()) << std::endl; // 'SomeClass'
|
std::cout << NAMEOF_SHORT_TYPE_EXPR(std::declval<const SomeClass<int>>()) << std::endl; // 'SomeClass'
|
||||||
|
|
||||||
|
#if defined(NAMEOF_MEMBER_SUPPORTED)
|
||||||
|
// Nameof member
|
||||||
|
std::cout << nameof::nameof_member<&SomeStruct::somefield>() << std::endl; // somefield
|
||||||
|
std::cout << nameof::nameof_member<&SomeStruct::SomeMethod1>() << std::endl; // SomeMethod1
|
||||||
|
std::cout << NAMEOF_MEMBER(&Long::LL::field) << std::endl; // field
|
||||||
|
constexpr auto member_ptr = &SomeStruct.somefield;
|
||||||
|
std::cout << NAMEOF_MEMBER(member_ptr) << std::endl; // field
|
||||||
|
#endif
|
||||||
|
|
||||||
// Nameof macro.
|
// Nameof macro.
|
||||||
std::cout << NAMEOF(__LINE__) << std::endl; // '__LINE__'
|
std::cout << NAMEOF(__LINE__) << std::endl; // '__LINE__'
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,12 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Checks nameof_member compiler compatibility.
|
||||||
|
#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 7
|
||||||
|
# undef NAMEOF_MEMBER_SUPPORTED
|
||||||
|
# define NAMEOF_MEMBER_SUPPORTED 1
|
||||||
|
#endif
|
||||||
|
|
||||||
// Checks nameof_enum compiler compatibility.
|
// Checks nameof_enum compiler compatibility.
|
||||||
#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1910
|
#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1910
|
||||||
# undef NAMEOF_ENUM_SUPPORTED
|
# undef NAMEOF_ENUM_SUPPORTED
|
||||||
|
@ -169,6 +175,12 @@ constexpr string_view type_name() noexcept {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If need cunstom name for member, add specialization member_name for necessary type.
|
||||||
|
template <auto V>
|
||||||
|
constexpr string_view member_name() noexcept {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace nameof::customize
|
} // namespace nameof::customize
|
||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
|
@ -696,6 +708,14 @@ struct nameof_type_rtti_supported
|
||||||
: std::false_type {};
|
: std::false_type {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
struct nameof_member_supported
|
||||||
|
#if defined(NAMEOF_MEMBER_SUPPORTED) && NAMEOF_MEMBER_SUPPORTED || defined(NAMEOF_TYPE_NO_CHECK_SUPPORT)
|
||||||
|
: std::true_type {};
|
||||||
|
#else
|
||||||
|
: std::false_type {};
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(__clang__)
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct identity {
|
struct identity {
|
||||||
|
@ -829,6 +849,27 @@ string nameof_short_type_rtti(const char* tn) noexcept {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <auto V>
|
||||||
|
constexpr auto n() noexcept {
|
||||||
|
constexpr auto custom_name = customize::member_name<V>();
|
||||||
|
|
||||||
|
if constexpr (custom_name.empty()) {
|
||||||
|
static_cast<void>(custom_name);
|
||||||
|
#if defined(NAMEOF_TYPE_SUPPORTED) && NAMEOF_TYPE_SUPPORTED
|
||||||
|
constexpr auto name = pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 2});
|
||||||
|
|
||||||
|
return cstring<name.size()>{name};
|
||||||
|
#else
|
||||||
|
return string_view{}; // Unsupported compiler.
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
return cstring<custom_name.size()>{custom_name};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <auto V>
|
||||||
|
inline constexpr auto member_name_v = n<V>();
|
||||||
|
|
||||||
} // namespace nameof::detail
|
} // namespace nameof::detail
|
||||||
|
|
||||||
// Checks is nameof_type supported compiler.
|
// Checks is nameof_type supported compiler.
|
||||||
|
@ -837,6 +878,9 @@ inline constexpr bool is_nameof_type_supported = detail::nameof_type_supported<v
|
||||||
// Checks is nameof_type_rtti supported compiler.
|
// Checks is nameof_type_rtti supported compiler.
|
||||||
inline constexpr bool is_nameof_type_rtti_supported = detail::nameof_type_rtti_supported<void>::value;
|
inline constexpr bool is_nameof_type_rtti_supported = detail::nameof_type_rtti_supported<void>::value;
|
||||||
|
|
||||||
|
// Checks is nameof_member supported compiler.
|
||||||
|
inline constexpr bool is_nameof_member_supported = detail::nameof_member_supported<void>::value;
|
||||||
|
|
||||||
// Checks is nameof_enum supported compiler.
|
// Checks is nameof_enum supported compiler.
|
||||||
inline constexpr bool is_nameof_enum_supported = detail::nameof_enum_supported<void>::value;
|
inline constexpr bool is_nameof_enum_supported = detail::nameof_enum_supported<void>::value;
|
||||||
|
|
||||||
|
@ -942,6 +986,16 @@ template <typename T>
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Obtains name of member.
|
||||||
|
template <auto V>
|
||||||
|
[[nodiscard]] constexpr auto nameof_member() noexcept -> std::enable_if_t<std::is_member_pointer_v<decltype(V)>, string_view> {
|
||||||
|
static_assert(detail::nameof_member_supported<decltype(V)>::value, "nameof::nameof_memder unsupported compiler (https://github.com/Neargye/nameof#compiler-compatibility).");
|
||||||
|
constexpr string_view name = detail::member_name_v<V>;
|
||||||
|
static_assert(name.size() > 0, "Member does not have a name.");
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace nameof
|
} // namespace nameof
|
||||||
|
|
||||||
// Obtains name of variable, function, macro.
|
// Obtains name of variable, function, macro.
|
||||||
|
@ -1008,6 +1062,9 @@ template <typename T>
|
||||||
// Obtains short type name, using RTTI.
|
// Obtains short type name, using RTTI.
|
||||||
#define NAMEOF_SHORT_TYPE_RTTI(...) ::nameof::detail::nameof_short_type_rtti<decltype(__VA_ARGS__)>(typeid(__VA_ARGS__).name())
|
#define NAMEOF_SHORT_TYPE_RTTI(...) ::nameof::detail::nameof_short_type_rtti<decltype(__VA_ARGS__)>(typeid(__VA_ARGS__).name())
|
||||||
|
|
||||||
|
// Obtains name of member.
|
||||||
|
#define NAMEOF_MEMBER(...) ::nameof::nameof_member<__VA_ARGS__>()
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
# pragma clang diagnostic pop
|
# pragma clang diagnostic pop
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
|
|
|
@ -879,3 +879,23 @@ TEST_CASE("NAMEOF_SHORT_TYPE_RTTI") {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(NAMEOF_MEMBER_SUPPORTED) && NAMEOF_MEMBER_SUPPORTED
|
||||||
|
|
||||||
|
TEST_CASE("NAMEOF_MEMBER") {
|
||||||
|
REQUIRE(NAMEOF_MEMBER(&SomeStruct::somefield) == "Derived");
|
||||||
|
REQUIRE(NAMEOF_MEMBER(&SomeStruct::SomeMethod1) == "Derived");
|
||||||
|
REQUIRE(NAMEOF_MEMBER(&Long::LL::field) == "Derived");
|
||||||
|
constexpr auto member_ptr = &SomeStruct.somefield;
|
||||||
|
REQUIRE(NAMEOF_MEMBER(member_ptr) == "Derived");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("nameof_member") {
|
||||||
|
REQUIRE(nameof::nameof_member<&SomeStruct::somefield>() == "Derived");
|
||||||
|
REQUIRE(nameof::nameof_member<&SomeStruct::SomeMethod1>() == "Derived");
|
||||||
|
REQUIRE(nameof::nameof_member<&Long::LL::field>() == "Derived");
|
||||||
|
constexpr auto member_ptr = &SomeStruct.somefield;
|
||||||
|
REQUIRE(nameof::nameof_member<member_ptr>() == "Derived");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue