diff --git a/include/nameof.hpp b/include/nameof.hpp index 3d47bcf..ffee928 100644 --- a/include/nameof.hpp +++ b/include/nameof.hpp @@ -5,7 +5,7 @@ // | |\ | (_| | | | | | | __/ (_) | | | |____|_| |_| // |_| \_|\__,_|_| |_| |_|\___|\___/|_| \_____| // https://github.com/Neargye/nameof -// vesion 0.3.0 +// vesion 0.4.0 // // Licensed under the MIT License . // Copyright (c) 2016, 2018 Daniil Goncharov . @@ -31,6 +31,7 @@ #pragma once #include +#include namespace nameof { @@ -49,16 +50,35 @@ inline constexpr const char* Nameof(const char* name, const std::size_t length) : Nameof(name, length - 1))); } +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); +} + +template +inline constexpr const char* NameofVariable(T&&, const char*, std::size_t) = delete; + } // namespace nameof #if defined(__GNUC__) || defined(__clang__) -// Used to obtain the string name of a variable, type, member, function, macros. +// 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 string full name of a variable, type, member, function, macros. +// 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))))) #elif defined(_MSC_VER) -// Used to obtain the string name of a variable, type, member, function, macros. +// 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 string full name of a variable, type, member, function, macros. +// 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)))) #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) diff --git a/test/test.cpp b/test/test.cpp index cd4eed8..9775a85 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -97,9 +97,19 @@ TEST_CASE("constexpr") { constexpr auto cx5 = NAMEOF_FULL(__cplusplus); REQUIRE(std::strcmp(cx5, "__cplusplus") == 0); } + + 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); + } } -TEST_CASE("NAMEOF") { +TEST_CASE("simple name") { SECTION("variable") { REQUIRE(std::strcmp(NAMEOF(somevar), "somevar") == 0); REQUIRE(std::strcmp(NAMEOF(&somevar), "somevar") == 0); @@ -151,13 +161,14 @@ TEST_CASE("NAMEOF") { } } -TEST_CASE("NAMEOF_FULL") { +TEST_CASE("full 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(::somevar), "::somevar") == 0); REQUIRE(std::strcmp(NAMEOF_FULL(othervar.ll.field), "othervar.ll.field") == 0); @@ -206,8 +217,11 @@ TEST_CASE("NAMEOF_FULL") { TEST_CASE("Spaces and Tabs ignored") { SECTION("Spaces") { // variable - REQUIRE(std::strcmp(NAMEOF( (&somevar)->somefield ), "somefield") == 0); + 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); // type REQUIRE(std::strcmp(NAMEOF( std::string ), "string") == 0); REQUIRE(std::strcmp(NAMEOF_FULL( std::string ), "std::string") == 0); @@ -221,10 +235,14 @@ TEST_CASE("Spaces and Tabs ignored") { REQUIRE(std::strcmp(NAMEOF( __cplusplus ), "__cplusplus") == 0); REQUIRE(std::strcmp(NAMEOF_FULL( __cplusplus ), "__cplusplus") == 0); } + SECTION("Tabs") { // variable - REQUIRE(std::strcmp(NAMEOF( (&somevar)->somefield ), "somefield") == 0); + 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); // type REQUIRE(std::strcmp(NAMEOF( std::string ), "string") == 0); REQUIRE(std::strcmp(NAMEOF_FULL( std::string ), "std::string") == 0); @@ -239,3 +257,33 @@ TEST_CASE("Spaces and Tabs ignored") { 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); + } +}