clean-up
This commit is contained in:
parent
96995e87ce
commit
ea58b9d963
3 changed files with 87 additions and 89 deletions
|
@ -121,7 +121,7 @@ int main() {
|
||||||
|
|
||||||
// Type full name.
|
// Type full name.
|
||||||
std::cout << NAMEOF_TYPE_RAW(othervar.ll) << std::endl; // Long::LL
|
std::cout << NAMEOF_TYPE_RAW(othervar.ll) << std::endl; // Long::LL
|
||||||
std::cout << NAMEOF_TYPE_RAW(std::declval<const SomeClass<int>>()) << std::endl; // SomeClass<int>&&
|
std::cout << NAMEOF_TYPE_RAW(std::declval<const SomeClass<int>>()) << std::endl; // const SomeClass<int>&&
|
||||||
|
|
||||||
// Raw name.
|
// Raw name.
|
||||||
std::cout << NAMEOF_RAW(volatile const int) << std::endl; // volatile const int
|
std::cout << NAMEOF_RAW(volatile const int) << std::endl; // volatile const int
|
||||||
|
|
|
@ -51,9 +51,12 @@ struct identity {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct remove_all_pointers
|
struct remove_all_pointers
|
||||||
: std::conditional<std::is_pointer<T>::value,
|
: std::conditional<std::is_pointer<T>::value,
|
||||||
remove_all_pointers<typename std::remove_pointer<T>::type>,
|
remove_all_pointers<typename std::remove_cv<typename std::remove_pointer<T>::type>::type>,
|
||||||
identity<T>>::type {};
|
identity<T>>::type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using Decay = std::remove_reference<typename std::remove_cv<typename remove_all_pointers<T>::type>::type>;
|
||||||
|
|
||||||
// STD like compile-time string.
|
// STD like compile-time string.
|
||||||
class cstring final {
|
class cstring final {
|
||||||
const char* str_;
|
const char* str_;
|
||||||
|
@ -150,51 +153,48 @@ class cstring final {
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr bool IsLexeme(char s) noexcept {
|
inline constexpr bool IsLexeme(char s) noexcept {
|
||||||
return !((s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') ||
|
return !((s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || s == '_');
|
||||||
(s >= 'A' && s <= 'Z') || s == '_');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr cstring NameofBase(const char* name, std::size_t length) noexcept {
|
inline constexpr cstring NameofBase(const char* name, std::size_t length, bool with_suffix) noexcept {
|
||||||
for (std::size_t i = length; i > 0; --i) {
|
|
||||||
if (IsLexeme(name[i - 1])) {
|
|
||||||
return {&name[i], length - i};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {name, length};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline constexpr cstring NameofTemplate(const char* name, std::size_t length, bool with_suffix) noexcept {
|
|
||||||
std::size_t p = 0;
|
std::size_t p = 0;
|
||||||
for (std::size_t i = length, h = 0; i > 0; --i) {
|
if(IsLexeme(name[length - 1])) {
|
||||||
if (h == 0 && (name[i - 1] == '&' || name[i - 1] == '*')) {
|
for (std::size_t i = length, h = 0; i > 0; --i) {
|
||||||
++p;
|
if (h == 0 && (IsLexeme(name[i - 1]) && name[i - 1] != '>')) {
|
||||||
continue;
|
++p;
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (name[i - 1] == '>') {
|
if (name[i - 1] == '>') {
|
||||||
++h;
|
++h;
|
||||||
++p;
|
++p;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name[i - 1] == '<') {
|
if (name[i - 1] == '<') {
|
||||||
--h;
|
--h;
|
||||||
++p;
|
++p;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h != 0) {
|
if (h != 0) {
|
||||||
++p;
|
++p;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsLexeme(name[i - 1]) && h == 0) {
|
if (h == 0) {
|
||||||
return {&name[i], length - i - (with_suffix ? 0 : p)};
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NameofBase(name, length - (with_suffix ? 0 : p));
|
for (std::size_t i = length - p; i > 0; --i) {
|
||||||
|
if (IsLexeme(name[i - 1])) {
|
||||||
|
return {&name[i], length - i - (with_suffix ? 0 : p)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {name, length - (with_suffix ? 0 : p)};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr cstring NameofRaw(const char* name, std::size_t length) noexcept {
|
inline constexpr cstring NameofRaw(const char* name, std::size_t length) noexcept {
|
||||||
|
@ -206,11 +206,8 @@ inline constexpr cstring NameofRaw(const char* name, std::size_t length) noexcep
|
||||||
template <typename T,
|
template <typename T,
|
||||||
typename = typename std::enable_if<!std::is_reference<T>::value &&
|
typename = typename std::enable_if<!std::is_reference<T>::value &&
|
||||||
!std::is_void<T>::value>::type>
|
!std::is_void<T>::value>::type>
|
||||||
inline constexpr detail::cstring Nameof(const T&, const char* name, std::size_t length) noexcept {
|
inline constexpr detail::cstring Nameof(const T&, const char* name, std::size_t length, bool with_suffix = false) noexcept {
|
||||||
// TODO: conditional expression is constant
|
return detail::NameofBase(name, length, with_suffix);
|
||||||
return (std::is_function<T>::value || std::is_member_function_pointer<T>::value)
|
|
||||||
? detail::NameofTemplate(name, length, false)
|
|
||||||
: detail::NameofBase(name, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T,
|
template <typename T,
|
||||||
|
@ -220,49 +217,31 @@ template <typename T,
|
||||||
inline constexpr detail::cstring Nameof(T&&, const char*, std::size_t) = delete;
|
inline constexpr detail::cstring Nameof(T&&, const char*, std::size_t) = delete;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr detail::cstring NameofType(bool full = false) noexcept {
|
inline constexpr detail::cstring NameofTypeRaw() noexcept {
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
const auto function_name = __PRETTY_FUNCTION__;
|
const auto function_name = __PRETTY_FUNCTION__;
|
||||||
const auto total_length = sizeof(__PRETTY_FUNCTION__) - 1;
|
const auto total_length = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||||
constexpr auto prefix_length = sizeof("nameof::detail::cstring nameof::NameofType(bool) [T = ") - 1;
|
constexpr auto prefix_length = sizeof("detail::cstring nameof::NameofTypeRaw() [T = ") - 1;
|
||||||
constexpr auto suffix_length = sizeof("]") - 1;
|
constexpr auto suffix_length = sizeof("]") - 1;
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
const auto function_name = __PRETTY_FUNCTION__;
|
const auto function_name = __PRETTY_FUNCTION__;
|
||||||
const auto total_length = sizeof(__PRETTY_FUNCTION__) - 1;
|
const auto total_length = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||||
constexpr auto prefix_length = sizeof("constexpr nameof::detail::cstring nameof::NameofType(bool) [T = ") - 1;
|
constexpr auto prefix_length = sizeof("constexpr nameof::detail::cstring nameof::NameofTypeRaw() [with T = ") - 1;
|
||||||
constexpr auto suffix_length = sizeof("]") - 1;
|
constexpr auto suffix_length = sizeof("]") - 1;
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
const auto function_name = __FUNCSIG__;
|
const auto function_name = __FUNCSIG__;
|
||||||
const auto total_length = sizeof(__FUNCSIG__) - 1;
|
const auto total_length = sizeof(__FUNCSIG__) - 1;
|
||||||
constexpr auto prefix_length = sizeof("class nameof::detail::cstring __cdecl nameof::NameofType<") - 1;
|
constexpr auto prefix_length = sizeof("class nameof::detail::cstring __cdecl nameof::NameofTypeRaw<") - 1;
|
||||||
constexpr auto suffix_length = sizeof(">(bool) noexcept") - 1;
|
constexpr auto suffix_length = sizeof(">(void) noexcept") - 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const auto raw_type_name = detail::cstring{function_name + prefix_length, total_length - prefix_length - suffix_length};
|
return {function_name + prefix_length, total_length - prefix_length - suffix_length};
|
||||||
|
}
|
||||||
|
|
||||||
const auto type_name = full ? raw_type_name : detail::NameofTemplate(raw_type_name.begin(), raw_type_name.length(), false);
|
template <typename T, typename D = typename detail::Decay<T>::type>
|
||||||
|
inline constexpr detail::cstring NameofType() noexcept {
|
||||||
#if defined(_MSC_VER)
|
const auto raw_type_name = NameofTypeRaw<D>();
|
||||||
|
return detail::NameofBase(raw_type_name.begin(), raw_type_name.length(), false);
|
||||||
constexpr auto class_length = sizeof("class") - 1;
|
|
||||||
constexpr auto struct_length = sizeof("struct") - 1;
|
|
||||||
constexpr auto enum_length = sizeof("enum") - 1;
|
|
||||||
|
|
||||||
using D = typename detail::remove_all_pointers<typename std::remove_reference<T>::type>::type;
|
|
||||||
|
|
||||||
if (!full && (std::is_class<D>::value || std::is_enum<D>::value) && (std::is_reference<T>::value || std::is_pointer<T>::value)) {
|
|
||||||
if (std::is_class<D>::value && type_name[0] == 'c' && type_name[1] == 'l' && type_name[2] == 'a' && type_name[3] == 's' && type_name[4] == 's') {
|
|
||||||
return type_name.remove_prefix(class_length);
|
|
||||||
} else if (std::is_class<D>::value && type_name[0] == 's' && type_name[1] == 't' && type_name[2] == 'r' && type_name[3] == 'u' && type_name[4] == 'c' && type_name[5] == 't') {
|
|
||||||
return type_name.remove_prefix(struct_length);
|
|
||||||
} else if(std::is_enum<D>::value && type_name[0] == 'e' && type_name[1] == 'n' && type_name[2] == 'u' && type_name[3] == 'm') {
|
|
||||||
return type_name.remove_prefix(enum_length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return type_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace nameof
|
} // namespace nameof
|
||||||
|
@ -278,8 +257,11 @@ inline constexpr detail::cstring NameofType(bool full = false) noexcept {
|
||||||
// Used to obtain the simple (unqualified) string name of a variable, member, function.
|
// Used to obtain the simple (unqualified) string name of a variable, member, function.
|
||||||
#define NAMEOF(name) ::nameof::Nameof<decltype(name)>(name, #name, (sizeof(#name) / sizeof(char)) - 1)
|
#define NAMEOF(name) ::nameof::Nameof<decltype(name)>(name, #name, (sizeof(#name) / sizeof(char)) - 1)
|
||||||
|
|
||||||
|
// Used to obtain the full string name of a variable, member, function.
|
||||||
|
#define NAMEOF_FULL(name) ::nameof::Nameof<decltype(name)>(name, #name, (sizeof(#name) / sizeof(char)) - 1, true)
|
||||||
|
|
||||||
// Used to obtain the simple (unqualified) string name of a type.
|
// Used to obtain the simple (unqualified) string name of a type.
|
||||||
#define NAMEOF_TYPE(name) ::nameof::NameofType<decltype(name)>(false)
|
#define NAMEOF_TYPE(name) ::nameof::NameofType<decltype(name)>()
|
||||||
|
|
||||||
// Used to obtain the raw string name of a type.
|
// Used to obtain the raw string name of a type.
|
||||||
#define NAMEOF_TYPE_RAW(name) ::nameof::NameofType<decltype(name)>(true)
|
#define NAMEOF_TYPE_RAW(name) ::nameof::NameofTypeRaw<decltype(name)>()
|
||||||
|
|
|
@ -50,7 +50,7 @@ template <typename T>
|
||||||
class SomeClass {
|
class SomeClass {
|
||||||
public:
|
public:
|
||||||
void SomeMethod5() const {
|
void SomeMethod5() const {
|
||||||
std::cout << nameof::NameofType<T>(false) << std::endl;
|
std::cout << nameof::NameofType<T>() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
|
@ -75,7 +75,7 @@ Long othervar;
|
||||||
SomeStruct& refvar = somevar;
|
SomeStruct& refvar = somevar;
|
||||||
SomeStruct* ptrvar = &somevar;
|
SomeStruct* ptrvar = &somevar;
|
||||||
|
|
||||||
#if (__cplusplus >= 201402L || (defined(_MSVC_LANG ) && _MSVC_LANG >= 201402L))
|
#if 0 && (__cplusplus >= 201402L || (defined(_MSVC_LANG ) && _MSVC_LANG >= 201402L))
|
||||||
// Compile-time supported by C++14.
|
// Compile-time supported by C++14.
|
||||||
TEST_CASE("constexpr") {
|
TEST_CASE("constexpr") {
|
||||||
SECTION("NAMEOF") {
|
SECTION("NAMEOF") {
|
||||||
|
@ -120,10 +120,10 @@ TEST_CASE("constexpr") {
|
||||||
constexpr auto cx1 = NAMEOF_TYPE(a);
|
constexpr auto cx1 = NAMEOF_TYPE(a);
|
||||||
static_assert(cx1 == "SomeClass", "");
|
static_assert(cx1 == "SomeClass", "");
|
||||||
|
|
||||||
constexpr auto cx2 = nameof::NameofType<SomeClass<int>>(false);
|
constexpr auto cx2 = nameof::NameofType<SomeClass<int>>();
|
||||||
static_assert(cx2 == "SomeClass", "");
|
static_assert(cx2 == "SomeClass", "");
|
||||||
|
|
||||||
constexpr auto cx3 = nameof::NameofType<decltype(a)>(false);
|
constexpr auto cx3 = nameof::NameofType<decltype(a)>();
|
||||||
static_assert(cx3 == "SomeClass", "");
|
static_assert(cx3 == "SomeClass", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,8 +131,8 @@ TEST_CASE("constexpr") {
|
||||||
SomeClass<int> a;
|
SomeClass<int> a;
|
||||||
|
|
||||||
constexpr auto cx1 = NAMEOF_TYPE_RAW(a);
|
constexpr auto cx1 = NAMEOF_TYPE_RAW(a);
|
||||||
constexpr auto cx2 = nameof::NameofType<SomeClass<int>>(true);
|
constexpr auto cx2 = nameof::NameofTypeRaw<SomeClass<int>>();
|
||||||
constexpr auto cx3 = nameof::NameofType<decltype(a)>(true);
|
constexpr auto cx3 = nameof::NameofTypeRaw<decltype(a)>();
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
static_assert(cx1 == "class SomeClass<int>", "");
|
static_assert(cx1 == "class SomeClass<int>", "");
|
||||||
|
@ -208,9 +208,6 @@ TEST_CASE("raw name") {
|
||||||
REQUIRE(NAMEOF_RAW(&SomeStruct::SomeMethod1) == "&SomeStruct::SomeMethod1");
|
REQUIRE(NAMEOF_RAW(&SomeStruct::SomeMethod1) == "&SomeStruct::SomeMethod1");
|
||||||
REQUIRE(NAMEOF_RAW(&SomeStruct::SomeMethod2) == "&SomeStruct::SomeMethod2");
|
REQUIRE(NAMEOF_RAW(&SomeStruct::SomeMethod2) == "&SomeStruct::SomeMethod2");
|
||||||
REQUIRE(NAMEOF_RAW(SomeMethod3) == "SomeMethod3");
|
REQUIRE(NAMEOF_RAW(SomeMethod3) == "SomeMethod3");
|
||||||
REQUIRE(NAMEOF_RAW(SomeMethod4<int>) == "SomeMethod4<int>");
|
|
||||||
REQUIRE(NAMEOF_RAW(&SomeClass<int>::SomeMethod5) == "&SomeClass<int>::SomeMethod5");
|
|
||||||
REQUIRE(NAMEOF_RAW(&SomeClass<int>::SomeMethod6<int>) == "&SomeClass<int>::SomeMethod6<int>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("enum") {
|
SECTION("enum") {
|
||||||
|
@ -254,7 +251,19 @@ TEST_CASE("type raw name") {
|
||||||
REQUIRE(NAMEOF_TYPE_RAW(Color::RED) == "enum Color");
|
REQUIRE(NAMEOF_TYPE_RAW(Color::RED) == "enum Color");
|
||||||
|
|
||||||
REQUIRE(NAMEOF_TYPE_RAW(std::declval<const SomeClass<int>>()) == "const classSomeClass<int>&&");
|
REQUIRE(NAMEOF_TYPE_RAW(std::declval<const SomeClass<int>>()) == "const classSomeClass<int>&&");
|
||||||
#else
|
#elif defined(__clang__)
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW(somevar) == "SomeStruct");
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW(ptrvar) == "SomeStruct *");
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW(refvar) == "SomeStruct &");
|
||||||
|
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW(othervar) == "Long");
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW(othervar.ll) == "Long::LL");
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW(othervar.ll.field) == "int");
|
||||||
|
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW(Color::RED) == "Color");
|
||||||
|
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW(std::declval<const SomeClass<int>>()) == "const SomeClass<int>&&");
|
||||||
|
#elif defined(__GNUC__)
|
||||||
REQUIRE(NAMEOF_TYPE_RAW(somevar) == "SomeStruct");
|
REQUIRE(NAMEOF_TYPE_RAW(somevar) == "SomeStruct");
|
||||||
REQUIRE(NAMEOF_TYPE_RAW(ptrvar) == "SomeStruct*");
|
REQUIRE(NAMEOF_TYPE_RAW(ptrvar) == "SomeStruct*");
|
||||||
REQUIRE(NAMEOF_TYPE_RAW(refvar) == "SomeStruct&");
|
REQUIRE(NAMEOF_TYPE_RAW(refvar) == "SomeStruct&");
|
||||||
|
@ -265,23 +274,30 @@ TEST_CASE("type raw name") {
|
||||||
|
|
||||||
REQUIRE(NAMEOF_TYPE_RAW(Color::RED) == "Color");
|
REQUIRE(NAMEOF_TYPE_RAW(Color::RED) == "Color");
|
||||||
|
|
||||||
REQUIRE(NAMEOF_TYPE_RAW(std::declval<const SomeClass<int>>()) == "const SomeClass<int>&&");
|
REQUIRE(NAMEOF_TYPE_RAW(std::declval<const SomeClass<int>>()) == "const SomeClass<int> &&");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Spaces and Tabs ignored") {
|
TEST_CASE("Spaces and Tabs ignored") {
|
||||||
SECTION("Spaces") {
|
SECTION("Spaces") {
|
||||||
REQUIRE(NAMEOF( somevar ) == "somevar");
|
REQUIRE(NAMEOF( somevar ) == "somevar");
|
||||||
REQUIRE(NAMEOF_RAW( somevar ) == "somevar");
|
REQUIRE(NAMEOF_RAW( somevar ) == "somevar");
|
||||||
REQUIRE(NAMEOF_TYPE( int{} ) == "int");
|
REQUIRE(NAMEOF_TYPE( somevar ) == "SomeStruct");
|
||||||
REQUIRE(NAMEOF_TYPE_RAW( int{} ) == "int");
|
#if defined(_MSC_VER)
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW( somevar ) == "struct SomeStruct");
|
||||||
|
#else
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW( somevar ) == "SomeStruct");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Tabs") {
|
SECTION("Tabs") {
|
||||||
REQUIRE(NAMEOF( somevar ) == "somevar");
|
REQUIRE(NAMEOF( somevar ) == "somevar");
|
||||||
REQUIRE(NAMEOF_RAW( somevar ) == "somevar");
|
REQUIRE(NAMEOF_RAW( somevar ) == "somevar");
|
||||||
REQUIRE(NAMEOF_TYPE( int{} ) == "int");
|
REQUIRE(NAMEOF_TYPE( somevar ) == "SomeStruct");
|
||||||
REQUIRE(NAMEOF_TYPE_RAW( int{} ) == "int");
|
#if defined(_MSC_VER)
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW( somevar ) == "struct SomeStruct");
|
||||||
|
#else
|
||||||
|
REQUIRE(NAMEOF_TYPE_RAW( somevar ) == "SomeStruct");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue