WIP new version nameof
This commit is contained in:
parent
e155d22c34
commit
fb1299ab02
4 changed files with 404 additions and 228 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 <typename T>
|
||||
class SomeClass {
|
||||
public:
|
||||
void SomeMethod5() const {}
|
||||
|
||||
template <typename C>
|
||||
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<int>) << std::endl; // SomeMethod4
|
||||
std::cout << NAMEOF(&SomeClass<int>::SomeMethod5) << std::endl; // SomeMethod5
|
||||
std::cout << NAMEOF(&SomeClass<int>::SomeMethod6<long int>) << std::endl; // SomeMethod6
|
||||
|
||||
// function with template prefix
|
||||
std::cout << NAMEOF_T(SomeMethod4<int>) << std::endl; // SomeMethod4<int>
|
||||
std::cout << NAMEOF_T(&SomeClass<int>::SomeMethod6<long int>) << std::endl; // SomeMethod6<long int>
|
||||
|
||||
// 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<int>::SomeMethod6<long int>) << 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;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// | |\ | (_| | | | | | | __/ (_) | | | |____|_| |_|
|
||||
// |_| \_|\__,_|_| |_| |_|\___|\___/|_| \_____|
|
||||
// https://github.com/Neargye/nameof
|
||||
// vesion 0.4.0
|
||||
// vesion 0.5.0
|
||||
//
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// Copyright (c) 2016, 2018 Daniil Goncharov <neargye@gmail.com>.
|
||||
|
@ -32,53 +32,276 @@
|
|||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <ostream>
|
||||
|
||||
namespace nameof {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
struct identity {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_all_pointers
|
||||
: std::conditional_t<std::is_pointer<T>::value,
|
||||
remove_all_pointers<typename std::remove_pointer<T>::type>,
|
||||
identity<T>> {};
|
||||
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 <std::size_t N>
|
||||
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<decltype(size_)>::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 <std::size_t N>
|
||||
inline friend constexpr bool operator==(const cstring& lhs, const char(&str)[N]) noexcept;
|
||||
|
||||
template <std::size_t N>
|
||||
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 <std::size_t N>
|
||||
inline constexpr bool operator==(const cstring& lhs, const char(&str)[N]) noexcept {
|
||||
return lhs == cstring{str, N - 1};
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
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 <typename T,
|
||||
typename = typename std::enable_if<!std::is_reference<T>::value &&
|
||||
!std::is_void<T>::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<T>::value || std::is_member_function_pointer<T>::value)
|
||||
return detail::NameofFunction(name, length, with_template_prefix);
|
||||
|
||||
return detail::NameofBase(name, length);
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
typename = typename std::enable_if<
|
||||
!std::is_reference<T>::value &&
|
||||
!std::is_void<T>::value &&
|
||||
typename = typename std::enable_if<!std::is_enum<T>::value &&
|
||||
!std::is_function<T>::value &&
|
||||
!std::is_member_function_pointer<T>::value
|
||||
>::type>
|
||||
inline constexpr const char* NameofVariable(const T&, const char* name, std::size_t length) noexcept {
|
||||
return Nameof(name, length);
|
||||
}
|
||||
!std::is_member_function_pointer<T>::value>::type>
|
||||
inline constexpr detail::cstring Nameof(T&&, const char*, std::size_t) = delete;
|
||||
|
||||
template <typename T>
|
||||
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<typename detail::remove_all_pointers<typename std::remove_reference<T>::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<typename detail::remove_all_pointers<typename std::remove_reference<T>::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<decltype(name)>(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<decltype(name)>(name, #name, 0)
|
||||
// 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, false)
|
||||
|
||||
#define NAMEOF_T(name) ::nameof::Nameof<decltype(name)>(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<decltype(name)>()
|
||||
|
|
287
test/test.cpp
287
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 <typename T>
|
||||
T SomeMethod4() {
|
||||
return T{};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class SomeClass {
|
||||
public:
|
||||
void SomeMethod5() const {}
|
||||
|
||||
template <typename C>
|
||||
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<int>) == "SomeMethod4");
|
||||
REQUIRE(NAMEOF(&SomeClass<int>::SomeMethod5) == "SomeMethod5");
|
||||
REQUIRE(NAMEOF(&SomeClass<int>::SomeMethod6<long int>) == "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<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") {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue