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>"
|
||||
// Name of enum
|
||||
NAMEOF(SomeEnum::RED) -> "RED"
|
||||
SomeEnum e = SomeEnum::RED;
|
||||
NAMEOF_ENUM(e) -> "RED"
|
||||
// Name of type
|
||||
NAMEOF_TYPE(SomeEnum::RED) -> "SomeEnum"
|
||||
NAMEOF_TYPE_T(int) -> "int"
|
||||
|
|
|
@ -86,10 +86,12 @@ int main() {
|
|||
constexpr auto constexpr_work_fine = NAMEOF(structvar);
|
||||
static_assert("structvar" == constexpr_work_fine, "");
|
||||
|
||||
std::cout << SomeMethod4<int>(structvar) << std::endl; // SomeMethod4<int>(SomeStruct value)
|
||||
|
||||
// Enum name.
|
||||
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.
|
||||
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(&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 {
|
||||
if (y == 0) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -346,6 +346,55 @@ constexpr cstring NameofTypePretty(const char* str, std::size_t size, std::size_
|
|||
}
|
||||
#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>
|
||||
NAMEOF_TYPE_CONSTEXPR cstring NameofType() {
|
||||
#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);
|
||||
}
|
||||
|
||||
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>
|
||||
NAMEOF_TYPE_CONSTEXPR cstring NameofType() {
|
||||
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
|
||||
|
||||
// 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)
|
||||
|
||||
// Used to obtain the full string name of a variable, member, function, macros.
|
||||
// Used to obtain the full string name of a variable, member, function, enum, macros.
|
||||
#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, macros.
|
||||
// Used to obtain the raw string name of a variable, member, function, enum, macros.
|
||||
#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.
|
||||
#define NAMEOF_TYPE(...) ::nameof::NameofType<decltype(__VA_ARGS__)>()
|
||||
#define NAMEOF_TYPE_T(...) ::nameof::NameofType<__VA_ARGS__>()
|
||||
|
|
|
@ -70,6 +70,8 @@ struct Long {
|
|||
|
||||
enum class Color { RED, GREEN, BLUE };
|
||||
|
||||
enum Directions { Up, Down, Right, Left};
|
||||
|
||||
SomeStruct struct_var;
|
||||
Long othervar;
|
||||
SomeStruct * ptr_s = &struct_var;
|
||||
|
@ -78,6 +80,9 @@ SomeStruct & ref_s = struct_var;
|
|||
SomeClass<int> class_var;
|
||||
const SomeClass<int> volatile * ptr_c = nullptr;
|
||||
|
||||
const Color color = Color::RED;
|
||||
const Directions directions = Directions::Right;
|
||||
|
||||
TEST_CASE("constexpr") {
|
||||
SECTION("NAMEOF") {
|
||||
// variable
|
||||
|
@ -140,6 +145,17 @@ TEST_CASE("constexpr") {
|
|||
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)
|
||||
SECTION("NAMEOF_TYPE") {
|
||||
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") {
|
||||
#if defined(__clang__)
|
||||
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_RAW( struct_var ) == "struct_var");
|
||||
|
||||
REQUIRE(NAMEOF_ENUM( color ) == "RED");
|
||||
|
||||
REQUIRE(NAMEOF_TYPE( 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_RAW( struct_var ) == "struct_var");
|
||||
|
||||
REQUIRE(NAMEOF_ENUM( color ) == "RED");
|
||||
|
||||
REQUIRE(NAMEOF_TYPE( struct_var ) == "SomeStruct");
|
||||
REQUIRE(NAMEOF_TYPE_T( decltype(struct_var) ) == "SomeStruct");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue