diff --git a/CMakeLists.txt b/CMakeLists.txt index 18371ce..0713a46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ include(CheckCXXCompilerFlag) project(nameof) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/example/example.cpp b/example/example.cpp index d18f79e..91188fc 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -39,13 +39,9 @@ std::string operator"" _string(const char* str, std::size_t) { struct SomeStruct { int somefield = 0; - void SomeMethod1(const int i) { - somefield = i; - } + void SomeMethod1(const int i) { somefield = i; } - int SomeMethod2() const { - return somefield; - } + int SomeMethod2() const { return somefield; } }; void SomeMethod3() { @@ -57,6 +53,15 @@ T SomeMethod4() { return T{}; } +template +class SomeClass { +public: + void SomeMethod5() const {} + + template + C SomeMethod6() const { return C{}; } +}; + struct Long { struct LL { int field = 0; @@ -68,12 +73,12 @@ enum class Color { RED, GREEN, BLUE }; SomeStruct somevar; Long othervar; -int intvar = 0; +SomeStruct& refvar = somevar; SomeStruct* ptrvar = &somevar; int main() { // constexpr - constexpr auto constexpr_work_fine = NAMEOF(intvar); + constexpr auto constexpr_work_fine = NAMEOF(somevar); std::cout << constexpr_work_fine << std::endl; // intvar // enum @@ -82,7 +87,6 @@ int main() { // variable std::cout << NAMEOF(somevar) << std::endl; // somevar std::cout << NAMEOF(::somevar) << std::endl; // somevar - std::cout << NAMEOF(&somevar) << std::endl; // somevar // member std::cout << NAMEOF(somevar.somefield) << std::endl; // somefield @@ -90,23 +94,37 @@ int main() { std::cout << NAMEOF(othervar.ll.field) << std::endl; // field // function + std::cout << NAMEOF(&SomeStruct::SomeMethod1) << std::endl; // SomeMethod1 std::cout << NAMEOF(&SomeStruct::SomeMethod2) << std::endl; // SomeMethod2 std::cout << NAMEOF(SomeMethod3) << std::endl; // SomeMethod3 + std::cout << NAMEOF(SomeMethod4) << std::endl; // SomeMethod4 + std::cout << NAMEOF(&SomeClass::SomeMethod5) << std::endl; // SomeMethod5 + std::cout << NAMEOF(&SomeClass::SomeMethod6) << std::endl; // SomeMethod6 + + // function with template prefix + std::cout << NAMEOF_T(SomeMethod4) << std::endl; // SomeMethod4 + std::cout << NAMEOF_T(&SomeClass::SomeMethod6) << std::endl; // SomeMethod6 // type - std::cout << NAMEOF(int[]) << std::endl; // int[] - std::cout << NAMEOF(SomeStruct) << std::endl; // SomeStruct - std::cout << NAMEOF(Long::LL) << std::endl; // LL - std::cout << NAMEOF(volatile const int) << std::endl; // volatile const int + std::cout << NAMEOF_TYPE(std::string{}) << std::endl; // basic_string + std::cout << NAMEOF_TYPE(somevar) << std::endl; // SomeStruct + std::cout << NAMEOF_TYPE(refvar) << std::endl; // basic_string + std::cout << NAMEOF_TYPE(ptrvar) << std::endl; // basic_string + std::cout << NAMEOF_TYPE(Color::RED) << std::endl; // Color + + std::cout << NAMEOF_RAW(int[]) << std::endl; // int[] + std::cout << NAMEOF_RAW(SomeStruct) << std::endl; // SomeStruct + std::cout << NAMEOF_RAW(Long::LL) << std::endl; // LL + std::cout << NAMEOF_RAW(volatile const int) << std::endl; // volatile const int // macros - std::cout << NAMEOF(__LINE__) << std::endl; // __LINE__ - std::cout << NAMEOF(__FILE__) << std::endl; // __FILE__ + std::cout << NAMEOF_RAW(__LINE__) << std::endl; // __LINE__ + std::cout << NAMEOF_RAW(__FILE__) << std::endl; // __FILE__ // full name - std::cout << NAMEOF_FULL(somevar.somefield) << std::endl; // somevar.somefield - std::cout << NAMEOF_FULL(&SomeStruct::SomeMethod2) << std::endl; // &SomeStruct::SomeMethod2 - std::cout << NAMEOF_FULL(Long::LL) << std::endl; // Long::LL + std::cout << NAMEOF_RAW(somevar.somefield) << std::endl; // somevar.somefield + std::cout << NAMEOF_RAW(&SomeClass::SomeMethod6) << std::endl; // &SomeStruct::SomeMethod2 + std::cout << NAMEOF_RAW(Long::LL) << std::endl; // Long::LL const auto div = [](int x, int y) -> int { if (y == 0) { @@ -125,10 +143,11 @@ int main() { /* Remarks */ // Spaces and Tabs ignored - std::cout << NAMEOF( std::string ) << std::endl; // string - std::cout << NAMEOF( std::string ) << std::endl; // string + std::cout << NAMEOF( somevar ) << std::endl; // string + std::cout << NAMEOF( somevar ) << std::endl; // string - // Bad case +#if 0 + // This expression does not have a name. std::cout << NAMEOF("Bad case") << std::endl; // '"Bad case"' std::cout << NAMEOF("Bad case"_string) << std::endl; // '"Bad case"_string' std::cout << NAMEOF("somevar.somefield") << std::endl; // 'somefield"' @@ -148,6 +167,7 @@ int main() { std::cout << NAMEOF(decltype(intvar)) << std::endl; // 'decltype(intvar)' std::cout << NAMEOF(typeid(intvar)) << std::endl; // 'typeid(intvar)' std::cout << NAMEOF((intvar)) << std::endl; // '(intvar)' +#endif return 0; } diff --git a/include/nameof.hpp b/include/nameof.hpp index a4db4ea..419b5e7 100644 --- a/include/nameof.hpp +++ b/include/nameof.hpp @@ -5,7 +5,7 @@ // | |\ | (_| | | | | | | __/ (_) | | | |____|_| |_| // |_| \_|\__,_|_| |_| |_|\___|\___/|_| \_____| // https://github.com/Neargye/nameof -// vesion 0.4.0 +// vesion 0.5.0 // // Licensed under the MIT License . // Copyright (c) 2016, 2018 Daniil Goncharov . @@ -32,53 +32,276 @@ #include #include +#include namespace nameof { namespace detail { +template +struct identity { + using type = T; +}; + +template +struct remove_all_pointers + : std::conditional_t::value, + remove_all_pointers::type>, + identity> {}; +class cstring final { + const char* str_; + std::size_t size_; + + public: + constexpr cstring(const char* str, std::size_t size) noexcept : str_(str), size_(size) {} + + template + constexpr cstring(const char(&str)[N]) noexcept : str_(str), size_(N - 1) {} + + cstring() = delete; + + cstring(const cstring&) = default; + + cstring(cstring&&) = default; + + cstring& operator=(const cstring&) = default; + + cstring& operator=(cstring&&) = default; + + ~cstring() = default; + + inline constexpr std::size_t size() const noexcept { return size_; } + + inline constexpr std::size_t length() const noexcept { return size_; } + + inline constexpr std::size_t max_size() const noexcept { return std::numeric_limits::max(); } + + inline constexpr bool empty() const noexcept { return size_ == 0; } + + inline constexpr const char* begin() const noexcept { return str_; } + + inline constexpr const char* end() const noexcept { return str_ + size_; } + + inline constexpr const char* cbegin() const noexcept { return begin(); } + + inline constexpr const char* cend() const noexcept { return end(); } + + inline constexpr const char& operator[](std::size_t i) const { return str_[i]; } + + inline friend constexpr bool operator==(const cstring& lhs, const cstring& rhs) noexcept; + + inline friend constexpr bool operator!=(const cstring& lhs, const cstring& rhs) noexcept; + + template + inline friend constexpr bool operator==(const cstring& lhs, const char(&str)[N]) noexcept; + + template + inline friend constexpr bool operator!=(const cstring& lhs, const char(&str)[N]) noexcept; + + inline friend std::ostream& operator<<(std::ostream& os, const cstring& str); + + inline operator std::string() const { return std::string(begin(), end()); } +}; + +inline constexpr bool operator==(const cstring& lhs, const cstring& rhs) noexcept { + if (lhs.size_ != rhs.size_) + return false; + + for (std::size_t i = 0; i < lhs.size_; ++i) { + if (lhs.str_[i] != rhs.str_[i]) + return false; + } + + return true; +} + +inline constexpr bool operator!=(const cstring& lhs, const cstring& rhs) noexcept { + return !(lhs == rhs); +} + +template +inline constexpr bool operator==(const cstring& lhs, const char(&str)[N]) noexcept { + return lhs == cstring{str, N - 1}; +} + +template +constexpr bool operator!=(const cstring& lhs, const char(&str)[N]) noexcept { + return !(lhs == cstring{str, N - 1}); +} + +inline std::ostream& operator<<(std::ostream& os, const cstring& str) { + os.write(str.begin(), str.size()); + return os; +} + inline constexpr bool IsLexeme(char s) noexcept { - return (s == '.' || s == '>' || s == ':' || s == '&' || s == '*' || - s == '+' || s == '~' || s == '-' || s == '!'); + return !((s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') || + (s >= 'A' && s <= 'Z') || s == '_'); +} + +inline constexpr cstring NameofBase(const char* name, std::size_t length) noexcept { + if (length == 0) + return {name, length}; + + 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 NameofFunction(const char* name, std::size_t length, bool with_template_prefix) noexcept { + if (length == 0) + return {name, length}; + + std::size_t h = 0; + std::size_t p = 0; + for (std::size_t i = length; i > 0; --i) { + if (name[i - 1] == '>') { + ++h; + ++p; + continue; + } + + if (name[i - 1] == '<') { + --h; + ++p; + continue; + } + + if (h != 0) { + ++p; + continue; + } + + if (IsLexeme(name[i - 1]) && h == 0) { + return {&name[i], length - i - (with_template_prefix ? 0 : p)}; + } + } + + return {name, length - (with_template_prefix ? 0 : p)}; +} + +inline constexpr cstring NameofType(const char* name, std::size_t length) noexcept { + if (length == 0) + return {name, length}; + + std::size_t h = 0; + for (std::size_t i = length; i > 0; --i) { + if (h == 0 && (name[i - 1] == '&' || name[i - 1] == '*')) { + continue; + } + + if (name[i - 1] == '>') { + ++h; + continue; + } + + if (name[i - 1] == '<') { + --h; + continue; + } + + if (h != 0) { + continue; + } + + if (IsLexeme(name[i - 1]) && h == 0) { + return {&name[i], length - i}; + } + } + + return {name, length}; +} + +inline constexpr cstring NameofRaw(const char* name, std::size_t length) noexcept { + return {name, length}; } } // namespace detail -inline constexpr const char* Nameof(const char* name, std::size_t length) noexcept { - return ((length == 0) ? name : (detail::IsLexeme(name[length - 1]) - ? &name[length] - : Nameof(name, length - 1))); +template ::value && + !std::is_void::value>::type> +inline constexpr detail::cstring Nameof(const T&, const char* name, std::size_t length, bool with_template_prefix) noexcept { + // TODO: conditional expression is constant + if (std::is_function::value || std::is_member_function_pointer::value) + return detail::NameofFunction(name, length, with_template_prefix); + + return detail::NameofBase(name, length); } template ::value && - !std::is_void::value && - !std::is_function::value && - !std::is_member_function_pointer::value - >::type> -inline constexpr const char* NameofVariable(const T&, const char* name, std::size_t length) noexcept { - return Nameof(name, length); -} + typename = typename std::enable_if::value && + !std::is_function::value && + !std::is_member_function_pointer::value>::type> +inline constexpr detail::cstring Nameof(T&&, const char*, std::size_t) = delete; template -inline constexpr const char* NameofVariable(T&&, const char*, std::size_t) = delete; +inline constexpr detail::cstring NameofType() { +#if defined(__GNUC__) || defined(__clang__) + constexpr auto function_name = __PRETTY_FUNCTION__; + constexpr auto total_length = sizeof(__PRETTY_FUNCTION__) - 1; + constexpr auto prefix_length = sizeof("nameof::detail::cstring nameof::NameofType() [T = ") - 1; + constexpr auto suffix_length = sizeof("]") - 1; +#elif defined(_MSC_VER) + constexpr auto function_name = __FUNCSIG__; + constexpr auto total_length = sizeof(__FUNCSIG__) - 1; + constexpr auto prefix_length = sizeof("class nameof::detail::cstring __cdecl nameof::NameofType<") - 1; + constexpr auto suffix_length = sizeof(">(void)") - 1; +#endif + constexpr auto type_name = detail::cstring{function_name + prefix_length, total_length - prefix_length - suffix_length}; + +#if defined(_MSC_VER) + constexpr auto class_length = sizeof("class") - 1; + constexpr auto struct_length = sizeof("struct") - 1; + constexpr auto enum_length = sizeof("enum") - 1; + + if (std::is_class::type>::type>::value) { + if (type_name[0] == 'c') { + if (type_name[class_length] == ' ') { + return detail::cstring{type_name.begin() + class_length + 1, type_name.length() - class_length - 1}; + } + return detail::cstring{type_name.begin() + class_length, type_name.length() - class_length}; + } + + if (type_name[0] == 's') { + if (type_name[struct_length] == ' ') { + return detail::cstring{type_name.begin() + struct_length + 1, type_name.length() - struct_length - 1}; + } + return detail::cstring{type_name.begin() + struct_length, type_name.length() - struct_length}; + } + } + + if (std::is_enum::type>::type>::value) { + if (type_name[0] == 'e') { + if (type_name[enum_length] == ' ') { + return detail::cstring{type_name.begin() + enum_length + 1, type_name.length() - enum_length - 1}; + } + return detail::cstring{type_name.begin() + enum_length, type_name.length() - enum_length}; + } + } +#endif + + return type_name; +} } // namespace nameof #if defined(__GNUC__) || defined(__clang__) -// Used to obtain the simple (unqualified) string name of a variable, type, member, function, macros. -# define NAMEOF(name) ::nameof::Nameof(#name, (((sizeof(#name) / sizeof(char)) - 1) + (0 * sizeof(void(*)(__typeof__(name)))))) -// Used to obtain the full string name of a variable, type, member, function, macros. -# define NAMEOF_FULL(name) ::nameof::Nameof(#name, (0 * sizeof(void(*)(__typeof__(name))))) +// Used to obtain the raw string name of a variable, type, member, function, macros. +# define NAMEOF_RAW(name) ::nameof::detail::NameofRaw(#name, ((sizeof(#name) / sizeof(char)) - 1) + (0 * sizeof(void (*)(__typeof__(name))))) #elif defined(_MSC_VER) -// Used to obtain the simple (unqualified) string name of a variable, type, member, function, macros. -# define NAMEOF(name) ::nameof::Nameof(#name, (((sizeof(#name) / sizeof(char)) - 1) + (0 * sizeof(typeid(name))))) -// Used to obtain the full string name of a variable, type, member, function, macros. -# define NAMEOF_FULL(name) ::nameof::Nameof(#name, (0 * sizeof(typeid(name)))) +// Used to obtain the raw string name of a variable, type, member, function, macros. +# define NAMEOF_RAW(name) ::nameof::detail::NameofRaw(#name, ((sizeof(#name) / sizeof(char)) - 1) + (0 * sizeof(typeid(name)))) #endif -// Used to obtain the simple (unqualified) string name of a variable or member. -#define NAMEOF_VARIABLE(name) ::nameof::NameofVariable(name, #name, (sizeof(#name) / sizeof(char)) - 1) -// Used to obtain the full string name of a variable or member. -#define NAMEOF_VARIABLE_FULL(name) ::nameof::NameofVariable(name, #name, 0) +// Used to obtain the simple (unqualified) string name of a variable, member, function. +#define NAMEOF(name) ::nameof::Nameof(name, #name, (sizeof(#name) / sizeof(char)) - 1, false) + +#define NAMEOF_T(name) ::nameof::Nameof(name, #name, (sizeof(#name) / sizeof(char)) - 1, true) + +// Used to obtain the simple (unqualified) string name of a type. +#define NAMEOF_TYPE(name) ::nameof::NameofType() diff --git a/test/test.cpp b/test/test.cpp index f91e3f9..2ef11d7 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -33,18 +33,28 @@ struct SomeStruct { int somefield = 0; - void SomeMethod1(const int i) { - somefield = i; - throw std::exception{}; - } + void SomeMethod1(const int i) { somefield = i; } - int SomeMethod2() const { - throw std::exception{}; - return somefield; - } + int SomeMethod2() const { return somefield; } }; -void SomeMethod3() { throw std::exception{}; } +void SomeMethod3() { + std::cout << NAMEOF(SomeMethod3) << " no called!" << std::endl; +} + +template +T SomeMethod4() { + return T{}; +} + +template +class SomeClass { +public: + void SomeMethod5() const {} + + template + C SomeMethod6() const { return C{}; } +}; struct Long { struct LL { @@ -57,236 +67,159 @@ enum class Color { RED, GREEN, BLUE }; SomeStruct somevar; Long othervar; -int intvar = 0; SomeStruct* ptrvar = &somevar; -SomeStruct** ptrptrvar = &ptrvar; TEST_CASE("constexpr") { SECTION("NAMEOF") { // variable - constexpr auto cx1 = NAMEOF((&somevar)->somefield); - REQUIRE(std::strcmp(cx1, "somefield") == 0); - // type - constexpr auto cx2 = NAMEOF(std::string); - REQUIRE(std::strcmp(cx2, "string") == 0); + constexpr auto cx1 = NAMEOF(somevar); + static_assert(cx1 == "somevar", ""); + // member + constexpr auto cx2 = NAMEOF((&somevar)->somefield); + static_assert(cx2 == "somefield", ""); // function constexpr auto cx3 = NAMEOF(&SomeStruct::SomeMethod2); - REQUIRE(std::strcmp(cx3, "SomeMethod2") == 0); + static_assert(cx3 == "SomeMethod2", ""); // enum constexpr auto cx4 = NAMEOF(Color::RED); - REQUIRE(std::strcmp(cx4, "RED") == 0); - // macros - constexpr auto cx5 = NAMEOF(__cplusplus); - REQUIRE(std::strcmp(cx5, "__cplusplus") == 0); + static_assert(cx4 == "RED", ""); } - SECTION("NAMEOF_FULL") { + SECTION("NAMEOF_RAW") { // variable - constexpr auto cx1 = NAMEOF_FULL((&somevar)->somefield); - REQUIRE(std::strcmp(cx1, "(&somevar)->somefield") == 0); + constexpr auto cx1 = NAMEOF_RAW(somevar); + static_assert(cx1 == "somevar", ""); + // member + constexpr auto cx2 = NAMEOF_RAW((&somevar)->somefield); + static_assert(cx2 == "(&somevar)->somefield", ""); // type - constexpr auto cx2 = NAMEOF_FULL(std::string); - REQUIRE(std::strcmp(cx2, "std::string") == 0); + constexpr auto cx3 = NAMEOF_RAW(std::string); + static_assert(cx3 == "std::string", ""); // function - constexpr auto cx3 = NAMEOF_FULL(&SomeStruct::SomeMethod2); - REQUIRE(std::strcmp(cx3, "&SomeStruct::SomeMethod2") == 0); + constexpr auto cx4 = NAMEOF_RAW(&SomeStruct::SomeMethod2); + static_assert(cx4 == "&SomeStruct::SomeMethod2", ""); // enum - constexpr auto cx4 = NAMEOF_FULL(Color::RED); - REQUIRE(std::strcmp(cx4, "Color::RED") == 0); + constexpr auto cx5 = NAMEOF_RAW(Color::RED); + static_assert(cx5 == "Color::RED", ""); // macros - constexpr auto cx5 = NAMEOF_FULL(__cplusplus); - REQUIRE(std::strcmp(cx5, "__cplusplus") == 0); + constexpr auto cx6 = NAMEOF_RAW(__cplusplus); + static_assert(cx6 == "__cplusplus", ""); } -#if !defined(_MSC_VER) || _MSC_VER > 1910 - - SECTION("NAMEOF_VARIABLE") { - constexpr auto cx1 = NAMEOF_VARIABLE((&somevar)->somefield); - REQUIRE(std::strcmp(cx1, "somefield") == 0); - } - - SECTION("NAMEOF_VARIABLE_FULL") { - constexpr auto cx1 = NAMEOF_VARIABLE_FULL((&somevar)->somefield); - REQUIRE(std::strcmp(cx1, "(&somevar)->somefield") == 0); - } - -#endif } TEST_CASE("simple name") { SECTION("variable") { - REQUIRE(std::strcmp(NAMEOF(somevar), "somevar") == 0); - REQUIRE(std::strcmp(NAMEOF(&somevar), "somevar") == 0); - REQUIRE(std::strcmp(NAMEOF(::somevar), "somevar") == 0); - - REQUIRE(std::strcmp(NAMEOF(somevar.somefield), "somefield") == 0); - REQUIRE(std::strcmp(NAMEOF((&somevar)->somefield), "somefield") == 0); - - REQUIRE(std::strcmp(NAMEOF(othervar.ll.field), "field") == 0); - - REQUIRE(std::strcmp(NAMEOF(ptrvar), "ptrvar") == 0); - REQUIRE(std::strcmp(NAMEOF(*ptrvar), "ptrvar") == 0); - - REQUIRE(std::strcmp(NAMEOF(ptrptrvar), "ptrptrvar") == 0); - REQUIRE(std::strcmp(NAMEOF(*ptrptrvar), "ptrptrvar") == 0); - REQUIRE(std::strcmp(NAMEOF(**ptrptrvar), "ptrptrvar") == 0); - - REQUIRE(std::strcmp(NAMEOF(+intvar), "intvar") == 0); - REQUIRE(std::strcmp(NAMEOF(-intvar), "intvar") == 0); - REQUIRE(std::strcmp(NAMEOF(~intvar), "intvar") == 0); - REQUIRE(std::strcmp(NAMEOF(!intvar), "intvar") == 0); + REQUIRE(NAMEOF(somevar) == "somevar"); + REQUIRE(NAMEOF(::somevar) == "somevar"); + REQUIRE(NAMEOF(ptrvar) == "ptrvar"); } - SECTION("type") { - REQUIRE(std::strcmp(NAMEOF(int[]), "int[]") == 0); - REQUIRE(std::strcmp(NAMEOF(int), "int") == 0); - REQUIRE(std::strcmp(NAMEOF(const volatile int[]), "const volatile int[]") == 0); - REQUIRE(std::strcmp(NAMEOF(std::string), "string") == 0); - - REQUIRE(std::strcmp(NAMEOF(SomeStruct), "SomeStruct") == 0); - REQUIRE(std::strcmp(NAMEOF(Long::LL), "LL") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(Color), "Color") == 0); + SECTION("member") { + REQUIRE(NAMEOF(somevar.somefield) == "somefield"); + REQUIRE(NAMEOF((&somevar)->somefield) == "somefield"); + REQUIRE(NAMEOF(othervar.ll.field) == "field"); } SECTION("function") { - REQUIRE(std::strcmp(NAMEOF(&SomeStruct::SomeMethod2), "SomeMethod2") == 0); - REQUIRE(std::strcmp(NAMEOF(SomeMethod3), "SomeMethod3") == 0); + REQUIRE(NAMEOF(&SomeStruct::SomeMethod1) == "SomeMethod1"); + REQUIRE(NAMEOF(&SomeStruct::SomeMethod2) == "SomeMethod2"); + REQUIRE(NAMEOF(SomeMethod3) == "SomeMethod3"); + REQUIRE(NAMEOF(SomeMethod4) == "SomeMethod4"); + REQUIRE(NAMEOF(&SomeClass::SomeMethod5) == "SomeMethod5"); + REQUIRE(NAMEOF(&SomeClass::SomeMethod6) == "SomeMethod6"); } SECTION("enum") { - REQUIRE(std::strcmp(NAMEOF(Color::RED), "RED") == 0); - REQUIRE(std::strcmp(NAMEOF(Color::BLUE), "BLUE") == 0); - } - - SECTION("macros") { - REQUIRE(std::strcmp(NAMEOF(__cplusplus), "__cplusplus") == 0); - REQUIRE(std::strcmp(NAMEOF(__LINE__), "__LINE__") == 0); - REQUIRE(std::strcmp(NAMEOF(__FILE__), "__FILE__") == 0); + REQUIRE(NAMEOF(Color::RED) == "RED"); + REQUIRE(NAMEOF(Color::BLUE) == "BLUE"); } } - -TEST_CASE("full name") { +TEST_CASE("raw name") { SECTION("variable") { - REQUIRE(std::strcmp(NAMEOF_FULL(somevar), "somevar") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(&somevar), "&somevar") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(::somevar), "::somevar") == 0); - - REQUIRE(std::strcmp(NAMEOF_FULL(somevar.somefield), "somevar.somefield") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL((&somevar)->somefield), "(&somevar)->somefield") == 0); - - REQUIRE(std::strcmp(NAMEOF_FULL(othervar.ll.field), "othervar.ll.field") == 0); - - REQUIRE(std::strcmp(NAMEOF_FULL(ptrvar), "ptrvar") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(*ptrvar), "*ptrvar") == 0); - - REQUIRE(std::strcmp(NAMEOF_FULL(ptrptrvar), "ptrptrvar") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(*ptrptrvar), "*ptrptrvar") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(**ptrptrvar), "**ptrptrvar") == 0); - - REQUIRE(std::strcmp(NAMEOF_FULL(+intvar), "+intvar") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(-intvar), "-intvar") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(~intvar), "~intvar") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(!intvar), "!intvar") == 0); + REQUIRE(NAMEOF_RAW(somevar) == "somevar"); + REQUIRE(NAMEOF_RAW(&somevar) == "&somevar"); + REQUIRE(NAMEOF_RAW(::somevar) == "::somevar"); + REQUIRE(NAMEOF_RAW(ptrvar) == "ptrvar"); + REQUIRE(NAMEOF_RAW(*ptrvar) == "*ptrvar"); + REQUIRE(NAMEOF_RAW(+somevar.somefield) == "+somevar.somefield"); + REQUIRE(NAMEOF_RAW(-somevar.somefield) == "-somevar.somefield"); + REQUIRE(NAMEOF_RAW(~somevar.somefield) == "~somevar.somefield"); + REQUIRE(NAMEOF_RAW(!somevar.somefield) == "!somevar.somefield"); + } + SECTION("member") { + REQUIRE(NAMEOF_RAW(somevar.somefield) == "somevar.somefield"); + REQUIRE(NAMEOF_RAW((&somevar)->somefield) == "(&somevar)->somefield"); + REQUIRE(NAMEOF_RAW(othervar.ll.field) == "othervar.ll.field"); } SECTION("type") { - REQUIRE(std::strcmp(NAMEOF_FULL(int[]), "int[]") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(int), "int") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(const volatile int[]), "const volatile int[]") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(std::string), "std::string") == 0); - - REQUIRE(std::strcmp(NAMEOF_FULL(SomeStruct), "SomeStruct") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(Long::LL), "Long::LL") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(Color), "Color") == 0); + REQUIRE(NAMEOF_RAW(int[]) == "int[]"); + REQUIRE(NAMEOF_RAW(int) == "int"); + REQUIRE(NAMEOF_RAW(const volatile int[]) == "const volatile int[]"); + REQUIRE(NAMEOF_RAW(std::string) == "std::string"); + REQUIRE(NAMEOF_RAW(SomeStruct) == "SomeStruct"); + REQUIRE(NAMEOF_RAW(Long::LL) == "Long::LL"); + REQUIRE(NAMEOF_RAW(Color) == "Color"); } SECTION("function") { - REQUIRE(std::strcmp(NAMEOF_FULL(&SomeStruct::SomeMethod2), "&SomeStruct::SomeMethod2") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(SomeMethod3), "SomeMethod3") == 0); + REQUIRE(NAMEOF_RAW(&SomeStruct::SomeMethod1) == "&SomeStruct::SomeMethod1"); + REQUIRE(NAMEOF_RAW(&SomeStruct::SomeMethod2) == "&SomeStruct::SomeMethod2"); + REQUIRE(NAMEOF_RAW(SomeMethod3) == "SomeMethod3"); + REQUIRE(NAMEOF_RAW(SomeMethod4) == "SomeMethod4"); + REQUIRE(NAMEOF_RAW(&SomeClass::SomeMethod5) == "&SomeClass::SomeMethod5"); + REQUIRE(NAMEOF_RAW(&SomeClass::SomeMethod6) == "&SomeClass::SomeMethod6"); } SECTION("enum") { - REQUIRE(std::strcmp(NAMEOF_FULL(Color::RED), "Color::RED") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(Color::BLUE), "Color::BLUE") == 0); + REQUIRE(NAMEOF_RAW(Color::RED) == "Color::RED"); + REQUIRE(NAMEOF_RAW(Color::BLUE) == "Color::BLUE"); } SECTION("macros") { - REQUIRE(std::strcmp(NAMEOF_FULL(__cplusplus), "__cplusplus") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(__LINE__), "__LINE__") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL(__FILE__), "__FILE__") == 0); + REQUIRE(NAMEOF_RAW(__cplusplus) == "__cplusplus"); + REQUIRE(NAMEOF_RAW(__LINE__) == "__LINE__"); + REQUIRE(NAMEOF_RAW(__FILE__) == "__FILE__"); } } TEST_CASE("Spaces and Tabs ignored") { SECTION("Spaces") { // variable - REQUIRE(std::strcmp(NAMEOF_VARIABLE( (&somevar)->somefield ), "somefield") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( (&somevar)->somefield ), "(&somevar)->somefield") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE( (&somevar)->somefield ), "somefield") == 0); - REQUIRE(std::strcmp(NAMEOF_VARIABLE_FULL( (&somevar)->somefield ), "(&somevar)->somefield") == 0); + REQUIRE(NAMEOF( somevar ) == "somevar"); + REQUIRE(NAMEOF_RAW( somevar ) == "somevar"); + // member + REQUIRE(NAMEOF( (&somevar)->somefield ) == "somefield"); + REQUIRE(NAMEOF_RAW( (&somevar)->somefield ) == "(&somevar)->somefield"); // type - REQUIRE(std::strcmp(NAMEOF( std::string ), "string") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( std::string ), "std::string") == 0); + REQUIRE(NAMEOF_RAW( std::string ) == "std::string"); // function - REQUIRE(std::strcmp(NAMEOF( &SomeStruct::SomeMethod2 ), "SomeMethod2") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( &SomeStruct::SomeMethod2 ), "&SomeStruct::SomeMethod2") == 0); + REQUIRE(NAMEOF( &SomeStruct::SomeMethod2 ) == "SomeMethod2"); + REQUIRE(NAMEOF_RAW( &SomeStruct::SomeMethod2 ) == "&SomeStruct::SomeMethod2"); // enum - REQUIRE(std::strcmp(NAMEOF( Color::RED ), "RED") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( Color::RED ), "Color::RED") == 0); + REQUIRE(NAMEOF( Color::RED ) == "RED"); + REQUIRE(NAMEOF_RAW( Color::RED ) == "Color::RED"); // macros - REQUIRE(std::strcmp(NAMEOF( __cplusplus ), "__cplusplus") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( __cplusplus ), "__cplusplus") == 0); + REQUIRE(NAMEOF_RAW( __cplusplus ) == "__cplusplus"); } SECTION("Tabs") { // variable - REQUIRE(std::strcmp(NAMEOF_VARIABLE( (&somevar)->somefield ), "somefield") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( (&somevar)->somefield ), "(&somevar)->somefield") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE( (&somevar)->somefield ), "somefield") == 0); - REQUIRE(std::strcmp(NAMEOF_VARIABLE_FULL( (&somevar)->somefield ), "(&somevar)->somefield") == 0); + REQUIRE(NAMEOF( somevar ) == "somevar"); + REQUIRE(NAMEOF_RAW( somevar ) == "somevar"); + // member + REQUIRE(NAMEOF( (&somevar)->somefield ) == "somefield"); + REQUIRE(NAMEOF_RAW( (&somevar)->somefield ) == "(&somevar)->somefield"); // type - REQUIRE(std::strcmp(NAMEOF( std::string ), "string") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( std::string ), "std::string") == 0); + REQUIRE(NAMEOF_RAW( std::string ) == "std::string"); // function - REQUIRE(std::strcmp(NAMEOF( &SomeStruct::SomeMethod2 ), "SomeMethod2") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( &SomeStruct::SomeMethod2 ), "&SomeStruct::SomeMethod2") == 0); + REQUIRE(NAMEOF( &SomeStruct::SomeMethod2 ) == "SomeMethod2"); + REQUIRE(NAMEOF_RAW( &SomeStruct::SomeMethod2 ) == "&SomeStruct::SomeMethod2"); // enum - REQUIRE(std::strcmp(NAMEOF( Color::RED ), "RED") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( Color::RED ), "Color::RED") == 0); + REQUIRE(NAMEOF( Color::RED ) == "RED"); + REQUIRE(NAMEOF_RAW( Color::RED ) == "Color::RED"); // macros - REQUIRE(std::strcmp(NAMEOF( __cplusplus ), "__cplusplus") == 0); - REQUIRE(std::strcmp(NAMEOF_FULL( __cplusplus ), "__cplusplus") == 0); - } -} - -TEST_CASE("variable name") { - SECTION("simple") { - REQUIRE(std::strcmp(NAMEOF_VARIABLE(somevar), "somevar") == 0); - REQUIRE(std::strcmp(NAMEOF_VARIABLE(::somevar), "somevar") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE(somevar.somefield), "somefield") == 0); - REQUIRE(std::strcmp(NAMEOF_VARIABLE((&somevar)->somefield), "somefield") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE(othervar.ll.field), "field") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE(ptrvar), "ptrvar") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE(ptrptrvar), "ptrptrvar") == 0); - } - - SECTION("full name") { - REQUIRE(std::strcmp(NAMEOF_VARIABLE_FULL(somevar), "somevar") == 0); - REQUIRE(std::strcmp(NAMEOF_VARIABLE_FULL(::somevar), "::somevar") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE_FULL(somevar.somefield), "somevar.somefield") == 0); - REQUIRE(std::strcmp(NAMEOF_VARIABLE_FULL((&somevar)->somefield), "(&somevar)->somefield") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE_FULL(othervar.ll.field), "othervar.ll.field") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE_FULL(ptrvar), "ptrvar") == 0); - - REQUIRE(std::strcmp(NAMEOF_VARIABLE_FULL(ptrptrvar), "ptrptrvar") == 0); + REQUIRE(NAMEOF_RAW( __cplusplus ) == "__cplusplus"); } }