add nameof enum
This commit is contained in:
parent
edc3ba588d
commit
ddc79d8d3e
4 changed files with 107 additions and 9 deletions
|
@ -44,6 +44,8 @@ NAMEOF(SomeMethod<int, float>) -> "SomeMethod"
|
||||||
NAMEOF_FULL(SomeMethod<int, float>) -> "SomeMethod4<int, float>"
|
NAMEOF_FULL(SomeMethod<int, float>) -> "SomeMethod4<int, float>"
|
||||||
// Name of enum
|
// Name of enum
|
||||||
NAMEOF(SomeEnum::RED) -> "RED"
|
NAMEOF(SomeEnum::RED) -> "RED"
|
||||||
|
SomeEnum e = SomeEnum::RED;
|
||||||
|
NAMEOF_ENUM(e) -> "RED"
|
||||||
// Name of type
|
// Name of type
|
||||||
NAMEOF_TYPE(SomeEnum::RED) -> "SomeEnum"
|
NAMEOF_TYPE(SomeEnum::RED) -> "SomeEnum"
|
||||||
NAMEOF_TYPE_T(int) -> "int"
|
NAMEOF_TYPE_T(int) -> "int"
|
||||||
|
|
|
@ -86,10 +86,12 @@ int main() {
|
||||||
constexpr auto constexpr_work_fine = NAMEOF(structvar);
|
constexpr auto constexpr_work_fine = NAMEOF(structvar);
|
||||||
static_assert("structvar" == constexpr_work_fine, "");
|
static_assert("structvar" == constexpr_work_fine, "");
|
||||||
|
|
||||||
std::cout << SomeMethod4<int>(structvar) << std::endl; // SomeMethod4<int>(SomeStruct value)
|
|
||||||
|
|
||||||
// Enum name.
|
// Enum name.
|
||||||
std::cout << NAMEOF(Color::RED) << std::endl; // RED
|
std::cout << NAMEOF(Color::RED) << std::endl; // RED
|
||||||
|
std::cout << NAMEOF_ENUM(Color::RED) << std::endl; // RED
|
||||||
|
auto color = Color::RED;
|
||||||
|
std::cout << NAMEOF(color) << std::endl; // color
|
||||||
|
std::cout << NAMEOF_ENUM(color) << std::endl; // RED
|
||||||
|
|
||||||
// Variable name.
|
// Variable name.
|
||||||
std::cout << NAMEOF(structvar) << std::endl; // structvar
|
std::cout << NAMEOF(structvar) << std::endl; // structvar
|
||||||
|
@ -129,6 +131,8 @@ int main() {
|
||||||
std::cout << NAMEOF_RAW(structvar.somefield) << std::endl; // structvar.somefield
|
std::cout << NAMEOF_RAW(structvar.somefield) << std::endl; // structvar.somefield
|
||||||
std::cout << NAMEOF_RAW(&SomeStruct::SomeMethod1) << std::endl; // &SomeStruct::SomeMethod1
|
std::cout << NAMEOF_RAW(&SomeStruct::SomeMethod1) << std::endl; // &SomeStruct::SomeMethod1
|
||||||
|
|
||||||
|
std::cout << SomeMethod4<int>(structvar) << std::endl; // SomeMethod4<int>(SomeStruct value)
|
||||||
|
|
||||||
const auto div = [](int x, int y) -> int {
|
const auto div = [](int x, int y) -> int {
|
||||||
if (y == 0) {
|
if (y == 0) {
|
||||||
throw std::invalid_argument(std::string(NAMEOF(y)).append(" should not be zero!"));
|
throw std::invalid_argument(std::string(NAMEOF(y)).append(" should not be zero!"));
|
||||||
|
|
|
@ -297,12 +297,12 @@ constexpr cstring RemovePrefix(cstring name, const std::size_t p = 0) {
|
||||||
: RemovePrefix(name, p + 1);
|
: RemovePrefix(name, p + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr cstring NameofPrettyImpl_(cstring name, std::size_t s, bool with_suffix) {
|
constexpr cstring NameofPrettyImpl1(cstring name, std::size_t s, bool with_suffix) {
|
||||||
return RemovePrefix(name.remove_suffix(s)).add_suffix(with_suffix ? s : 0);
|
return RemovePrefix(name.remove_suffix(s)).add_suffix(with_suffix ? s : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr cstring NameofPrettyImpl(cstring name, bool with_suffix) {
|
constexpr cstring NameofPrettyImpl(cstring name, bool with_suffix) {
|
||||||
return NameofPrettyImpl_(name, FindSuffix(name), with_suffix);
|
return NameofPrettyImpl1(name, FindSuffix(name), with_suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr cstring NameofPretty(cstring name, bool with_suffix) {
|
constexpr cstring NameofPretty(cstring name, bool with_suffix) {
|
||||||
|
@ -346,6 +346,55 @@ constexpr cstring NameofTypePretty(const char* str, std::size_t size, std::size_
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr int NameofEnumImpl1() {
|
||||||
|
#if defined(__clang__)
|
||||||
|
return sizeof(__PRETTY_FUNCTION__) - sizeof("int nameof::detail::NameofEnumImpl1() [T = ") - sizeof("]") + 1;
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
return sizeof(__PRETTY_FUNCTION__) - sizeof("constexpr int nameof::detail::NameofEnumImpl1() [with T = ") - sizeof("]") + 1;
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
return sizeof(__FUNCSIG__) - sizeof("int __cdecl nameof::detail::NameofEnumImpl1<") - sizeof(">(void)") + 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, T V>
|
||||||
|
constexpr nameof::cstring NameofEnumImpl2() {
|
||||||
|
#if defined(__clang__)
|
||||||
|
return {__PRETTY_FUNCTION__,
|
||||||
|
sizeof(__PRETTY_FUNCTION__) - 1,
|
||||||
|
sizeof("nameof::cstring nameof::detail::NameofEnumImpl2() [T = ") + NameofEnumImpl1<T>() + sizeof("; V = ") - 2,
|
||||||
|
sizeof("]") - 1};
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
return {__PRETTY_FUNCTION__,
|
||||||
|
sizeof(__PRETTY_FUNCTION__) - 1,
|
||||||
|
sizeof("constexpr nameof::cstring nameof::detail::NameofEnumImpl2() [with T = ") + NameofEnumImpl1<T>() + sizeof("; T V = ") - 2,
|
||||||
|
sizeof("]") - 1};
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
return {__FUNCSIG__,
|
||||||
|
sizeof(__FUNCSIG__) - 1,
|
||||||
|
sizeof("class nameof::cstring __cdecl nameof::detail::NameofEnumImpl2<") + NameofEnumImpl1<T>(),
|
||||||
|
sizeof(">(void)") - 1};
|
||||||
|
#else
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int I = 0>
|
||||||
|
struct NameofEnumImpl {
|
||||||
|
constexpr nameof::cstring operator()(T value) const noexcept {
|
||||||
|
return (static_cast<int>(value) - I == 0)
|
||||||
|
? NameofEnumImpl2<T, T(0 + I)>()
|
||||||
|
: NameofEnumImpl<T, I + 1>{}(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct NameofEnumImpl<T, 128> {
|
||||||
|
constexpr nameof::cstring operator()(T) const noexcept { return {}; }
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
NAMEOF_TYPE_CONSTEXPR cstring NameofType() {
|
NAMEOF_TYPE_CONSTEXPR cstring NameofType() {
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
|
@ -383,6 +432,12 @@ constexpr cstring Nameof(const char* name, std::size_t size, bool with_suffix =
|
||||||
return detail::NameofPretty({name, size}, with_suffix);
|
return detail::NameofPretty({name, size}, with_suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
typename = typename std::enable_if<!std::is_reference<T>::value && std::is_enum<T>::value>::type>
|
||||||
|
constexpr cstring NameofEnum(T value) {
|
||||||
|
return detail::NameofPretty(detail::NameofEnumImpl<T>{}(value), false);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
NAMEOF_TYPE_CONSTEXPR cstring NameofType() {
|
NAMEOF_TYPE_CONSTEXPR cstring NameofType() {
|
||||||
return true ? detail::NameofType<detail::nstd::identity<T>>() : detail::NameofType<detail::nstd::identity<T>>();
|
return true ? detail::NameofType<detail::nstd::identity<T>>() : detail::NameofType<detail::nstd::identity<T>>();
|
||||||
|
@ -395,15 +450,16 @@ constexpr cstring NameofRaw(const char* name, std::size_t size) {
|
||||||
|
|
||||||
} // namespace nameof
|
} // namespace nameof
|
||||||
|
|
||||||
// Used to obtain the simple (unqualified) string name of a variable, member, function, macros.
|
// Used to obtain the simple (unqualified) string name of a variable, member, function, enum, macros.
|
||||||
#define NAMEOF(...) ::nameof::Nameof<decltype(__VA_ARGS__)>(#__VA_ARGS__, (sizeof(#__VA_ARGS__) / sizeof(char)) - 1, false)
|
#define NAMEOF(...) ::nameof::Nameof<decltype(__VA_ARGS__)>(#__VA_ARGS__, (sizeof(#__VA_ARGS__) / sizeof(char)) - 1, false)
|
||||||
|
// Used to obtain the full string name of a variable, member, function, enum, macros.
|
||||||
// Used to obtain the full string name of a variable, member, function, macros.
|
|
||||||
#define NAMEOF_FULL(...) ::nameof::Nameof<decltype(__VA_ARGS__)>(#__VA_ARGS__, (sizeof(#__VA_ARGS__) / sizeof(char)) - 1, true)
|
#define NAMEOF_FULL(...) ::nameof::Nameof<decltype(__VA_ARGS__)>(#__VA_ARGS__, (sizeof(#__VA_ARGS__) / sizeof(char)) - 1, true)
|
||||||
|
// Used to obtain the raw string name of a variable, member, function, enum, macros.
|
||||||
// Used to obtain the raw string name of a variable, member, function, macros.
|
|
||||||
#define NAMEOF_RAW(...) ::nameof::NameofRaw<decltype(__VA_ARGS__)>(#__VA_ARGS__, (sizeof(#__VA_ARGS__) / sizeof(char)) - 1)
|
#define NAMEOF_RAW(...) ::nameof::NameofRaw<decltype(__VA_ARGS__)>(#__VA_ARGS__, (sizeof(#__VA_ARGS__) / sizeof(char)) - 1)
|
||||||
|
|
||||||
|
// Used to obtain the simple (unqualified) string name of a enum variable.
|
||||||
|
#define NAMEOF_ENUM(...) ::nameof::NameofEnum<decltype(__VA_ARGS__)>(__VA_ARGS__)
|
||||||
|
|
||||||
// Used to obtain the string name of a type.
|
// Used to obtain the string name of a type.
|
||||||
#define NAMEOF_TYPE(...) ::nameof::NameofType<decltype(__VA_ARGS__)>()
|
#define NAMEOF_TYPE(...) ::nameof::NameofType<decltype(__VA_ARGS__)>()
|
||||||
#define NAMEOF_TYPE_T(...) ::nameof::NameofType<__VA_ARGS__>()
|
#define NAMEOF_TYPE_T(...) ::nameof::NameofType<__VA_ARGS__>()
|
||||||
|
|
|
@ -70,6 +70,8 @@ struct Long {
|
||||||
|
|
||||||
enum class Color { RED, GREEN, BLUE };
|
enum class Color { RED, GREEN, BLUE };
|
||||||
|
|
||||||
|
enum Directions { Up, Down, Right, Left};
|
||||||
|
|
||||||
SomeStruct struct_var;
|
SomeStruct struct_var;
|
||||||
Long othervar;
|
Long othervar;
|
||||||
SomeStruct * ptr_s = &struct_var;
|
SomeStruct * ptr_s = &struct_var;
|
||||||
|
@ -78,6 +80,9 @@ SomeStruct & ref_s = struct_var;
|
||||||
SomeClass<int> class_var;
|
SomeClass<int> class_var;
|
||||||
const SomeClass<int> volatile * ptr_c = nullptr;
|
const SomeClass<int> volatile * ptr_c = nullptr;
|
||||||
|
|
||||||
|
const Color color = Color::RED;
|
||||||
|
const Directions directions = Directions::Right;
|
||||||
|
|
||||||
TEST_CASE("constexpr") {
|
TEST_CASE("constexpr") {
|
||||||
SECTION("NAMEOF") {
|
SECTION("NAMEOF") {
|
||||||
// variable
|
// variable
|
||||||
|
@ -140,6 +145,17 @@ TEST_CASE("constexpr") {
|
||||||
REQUIRE(cx6 == "__cplusplus");
|
REQUIRE(cx6 == "__cplusplus");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("NAMEOF_ENUM") {
|
||||||
|
constexpr auto cx = NAMEOF_ENUM(color);
|
||||||
|
# if defined(__clang__) || defined(_MSC_VER)
|
||||||
|
static_assert(cx == "RED", "");
|
||||||
|
REQUIRE(cx == "RED");
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
//static_assert(cx == "(Color)0", "");
|
||||||
|
REQUIRE(cx == "(Color)0");
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(NAMEOF_TYPE_HAS_CONSTEXPR)
|
#if defined(NAMEOF_TYPE_HAS_CONSTEXPR)
|
||||||
SECTION("NAMEOF_TYPE") {
|
SECTION("NAMEOF_TYPE") {
|
||||||
constexpr auto cx = NAMEOF_TYPE(ptr_c);
|
constexpr auto cx = NAMEOF_TYPE(ptr_c);
|
||||||
|
@ -290,6 +306,22 @@ TEST_CASE("NAMEOF_RAW") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("NAMEOF_ENUM") {
|
||||||
|
# if defined(__clang__) || defined(_MSC_VER)
|
||||||
|
REQUIRE(NAMEOF_ENUM(Color::RED) == "RED");
|
||||||
|
REQUIRE(NAMEOF_ENUM(color) == "RED");
|
||||||
|
|
||||||
|
REQUIRE(NAMEOF_ENUM(Directions::Right) == "Right");
|
||||||
|
REQUIRE(NAMEOF_ENUM(directions) == "Right");
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
REQUIRE(NAMEOF_ENUM(Color::RED) == "(Color)0");
|
||||||
|
REQUIRE(NAMEOF_ENUM(color) == "0");
|
||||||
|
|
||||||
|
REQUIRE(NAMEOF_ENUM(Directions::Right) == "2");
|
||||||
|
REQUIRE(NAMEOF_ENUM(directions) == "2");
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("NAMEOF_TYPE") {
|
TEST_CASE("NAMEOF_TYPE") {
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
REQUIRE(NAMEOF_TYPE(struct_var) == "SomeStruct");
|
REQUIRE(NAMEOF_TYPE(struct_var) == "SomeStruct");
|
||||||
|
@ -397,6 +429,8 @@ TEST_CASE("Spaces and Tabs ignored") {
|
||||||
REQUIRE(NAMEOF_FULL( struct_var ) == "struct_var");
|
REQUIRE(NAMEOF_FULL( struct_var ) == "struct_var");
|
||||||
REQUIRE(NAMEOF_RAW( struct_var ) == "struct_var");
|
REQUIRE(NAMEOF_RAW( struct_var ) == "struct_var");
|
||||||
|
|
||||||
|
REQUIRE(NAMEOF_ENUM( color ) == "RED");
|
||||||
|
|
||||||
REQUIRE(NAMEOF_TYPE( struct_var ) == "SomeStruct");
|
REQUIRE(NAMEOF_TYPE( struct_var ) == "SomeStruct");
|
||||||
REQUIRE(NAMEOF_TYPE_T( decltype(struct_var) ) == "SomeStruct");
|
REQUIRE(NAMEOF_TYPE_T( decltype(struct_var) ) == "SomeStruct");
|
||||||
}
|
}
|
||||||
|
@ -406,6 +440,8 @@ TEST_CASE("Spaces and Tabs ignored") {
|
||||||
REQUIRE(NAMEOF_FULL( struct_var ) == "struct_var");
|
REQUIRE(NAMEOF_FULL( struct_var ) == "struct_var");
|
||||||
REQUIRE(NAMEOF_RAW( struct_var ) == "struct_var");
|
REQUIRE(NAMEOF_RAW( struct_var ) == "struct_var");
|
||||||
|
|
||||||
|
REQUIRE(NAMEOF_ENUM( color ) == "RED");
|
||||||
|
|
||||||
REQUIRE(NAMEOF_TYPE( struct_var ) == "SomeStruct");
|
REQUIRE(NAMEOF_TYPE( struct_var ) == "SomeStruct");
|
||||||
REQUIRE(NAMEOF_TYPE_T( decltype(struct_var) ) == "SomeStruct");
|
REQUIRE(NAMEOF_TYPE_T( decltype(struct_var) ) == "SomeStruct");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue