This commit is contained in:
Neargye 2018-08-28 22:08:53 +05:00
parent 9e2272f109
commit 3ab3c69be8
2 changed files with 25 additions and 21 deletions

View file

@ -158,6 +158,7 @@ int main() {
std::cout << NAMEOF(42 + 42) << std::endl; // ' 42' std::cout << NAMEOF(42 + 42) << std::endl; // ' 42'
std::cout << NAMEOF(NAMEOF(structvar)) << std::endl; // 'NAMEOF' std::cout << NAMEOF(NAMEOF(structvar)) << std::endl; // 'NAMEOF'
std::cout << NAMEOF((SomeMethod4<int, float>)(1.0f)) << std::endl; // '' std::cout << NAMEOF((SomeMethod4<int, float>)(1.0f)) << std::endl; // ''
std::cout << NAMEOF(42, 42, 42) << std::endl; // '42'
#endif #endif
#if 0 #if 0

View file

@ -74,7 +74,7 @@ constexpr bool StrEquals(const char* lhs, const char* rhs, std::size_t size) {
return true; return true;
#else #else
return (size == 0) ? (lhs[0] == rhs[0]) : ((lhs[size - 1] == rhs[size - 1]) && StrEquals(lhs, rhs, size - 1)); return (size == 0) ? (lhs[0] == rhs[0]) : (lhs[size - 1] == rhs[size - 1] && StrEquals(lhs, rhs, size - 1));
#endif #endif
} }
@ -92,7 +92,8 @@ constexpr std::size_t StrLen(const char* str, std::size_t size = 0) {
#endif #endif
} }
// STD like compile-time const char* string. } // namespace detail
class cstring final { class cstring final {
const char* str_; const char* str_;
std::size_t size_; std::size_t size_;
@ -104,7 +105,7 @@ class cstring final {
constexpr cstring() noexcept : cstring{nullptr, 0, 0, 0} {} constexpr cstring() noexcept : cstring{nullptr, 0, 0, 0} {}
constexpr cstring(const char* str) noexcept : cstring{str, StrLen(str), 0, 0} {} constexpr cstring(const char* str) noexcept : cstring{str, detail::StrLen(str), 0, 0} {}
cstring(const std::string& str) noexcept : cstring{str.data(), str.size(), 0, 0} {} cstring(const std::string& str) noexcept : cstring{str.data(), str.size(), 0, 0} {}
@ -163,18 +164,18 @@ class cstring final {
if (const auto result = std::char_traits<char>::compare(str_, other.str_, other.size_ < size_ ? other.size_ : size_)) if (const auto result = std::char_traits<char>::compare(str_, other.str_, other.size_ < size_ ? other.size_ : size_))
return result; return result;
return size_ == other.size_ ? 0 : size_ < other.size_ ? -1 : 1; return (size_ == other.size_) ? 0 : ((size_ < other.size_) ? -1 : 1);
} }
friend constexpr bool operator==(cstring lhs, cstring rhs) noexcept { friend constexpr bool operator==(cstring lhs, cstring rhs) noexcept {
return (lhs.size_ == rhs.size_) && StrEquals(lhs.str_, rhs.str_, lhs.size_); return lhs.size_ == rhs.size_ && detail::StrEquals(lhs.str_, rhs.str_, lhs.size_);
} }
friend constexpr bool operator!=(cstring lhs, cstring rhs) noexcept { friend constexpr bool operator!=(cstring lhs, cstring rhs) noexcept {
return !(lhs == rhs); return !(lhs == rhs);
} }
std::string append(cstring s) { std::string append(cstring s) const {
return std::string(str_, size_).append(s.str_, s.size_); return std::string(str_, size_).append(s.str_, s.size_);
} }
@ -190,6 +191,8 @@ class cstring final {
operator std::string() const { return std::string(str_, size_); } operator std::string() const { return std::string(str_, size_); }
}; };
namespace detail {
constexpr bool IsLexeme(char s) noexcept { constexpr bool IsLexeme(char s) noexcept {
return !((s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || s == '_'); return !((s >= '0' && s <= '9') || (s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || s == '_');
} }
@ -261,7 +264,7 @@ constexpr cstring RemoveSuffix(cstring name, std::size_t h = 0) noexcept {
? RemoveSuffix(name.remove_suffix(1), h + 1) ? RemoveSuffix(name.remove_suffix(1), h + 1)
: (name.back() == '(' || name.back() == '{') : (name.back() == '(' || name.back() == '{')
? RemoveSuffix(name.remove_suffix(1), h - 1) ? RemoveSuffix(name.remove_suffix(1), h - 1)
: h == 0 ? name : RemoveSuffix(name.remove_suffix(1), h); : (h == 0) ? name : RemoveSuffix(name.remove_suffix(1), h);
} }
constexpr std::size_t FindSuffix(cstring name, std::size_t h = 0, std::size_t s = 0) noexcept { constexpr std::size_t FindSuffix(cstring name, std::size_t h = 0, std::size_t s = 0) noexcept {
@ -269,7 +272,7 @@ constexpr std::size_t FindSuffix(cstring name, std::size_t h = 0, std::size_t s
? FindSuffix(name, h + 1, s + 1) ? FindSuffix(name, h + 1, s + 1)
: (name[name.size() - 1 - s] == '<') : (name[name.size() - 1 - s] == '<')
? FindSuffix(name, h - 1, s + 1) ? FindSuffix(name, h - 1, s + 1)
: h == 0 ? s : FindSuffix(name, h, s + 1); : (h == 0) ? s : FindSuffix(name, h, s + 1);
} }
constexpr cstring RemovePrefix(cstring name, const std::size_t p = 0) noexcept { constexpr cstring RemovePrefix(cstring name, const std::size_t p = 0) noexcept {
@ -293,7 +296,7 @@ constexpr cstring NameofPretty(cstring name, bool with_suffix) noexcept {
#if defined(_MSC_VER) #if defined(_MSC_VER)
constexpr cstring RemoveSpaceSuffix(cstring name) noexcept { constexpr cstring RemoveSpaceSuffix(cstring name) noexcept {
return name.back() == ' ' ? RemoveSpaceSuffix(name.remove_suffix(1)) : name; return (name.back() == ' ') ? RemoveSpaceSuffix(name.remove_suffix(1)) : name;
} }
constexpr cstring RemoveClassPrefix(cstring name) noexcept { constexpr cstring RemoveClassPrefix(cstring name) noexcept {
@ -322,7 +325,7 @@ constexpr cstring NameofTypePretty(cstring name) noexcept {
} }
#elif defined(__clang__) || defined(__GNUC__) #elif defined(__clang__) || defined(__GNUC__)
constexpr cstring NameofTypePretty(const char* str, std::size_t size, std::size_t prefix, std::size_t suffix) noexcept { constexpr cstring NameofTypePretty(const char* str, std::size_t size, std::size_t prefix, std::size_t suffix) noexcept {
return {str, size, prefix, suffix + (str[size - suffix - 1] == ' ' ? 1 : 0)}; return {str, size, prefix, suffix + ((str[size - suffix - 1] == ' ') ? 1 : 0)};
} }
#endif #endif
@ -332,33 +335,35 @@ NAMEOF_TYPE_CONSTEXPR cstring NameofType() noexcept {
return NameofTypePretty( return NameofTypePretty(
__PRETTY_FUNCTION__, __PRETTY_FUNCTION__,
sizeof(__PRETTY_FUNCTION__) - 1, sizeof(__PRETTY_FUNCTION__) - 1,
sizeof("nameof::detail::cstring nameof::detail::NameofType() [T = nameof::detail::nstd::identity<") - 1, sizeof("nameof::cstring nameof::detail::NameofType() [T = nameof::detail::nstd::identity<") - 1,
sizeof(">]") - 1); sizeof(">]") - 1);
#elif defined(__GNUC__) #elif defined(__GNUC__)
return NameofTypePretty( return NameofTypePretty(
__PRETTY_FUNCTION__, __PRETTY_FUNCTION__,
sizeof(__PRETTY_FUNCTION__) - 1, sizeof(__PRETTY_FUNCTION__) - 1,
# if defined(NAMEOF_TYPE_HAS_CONSTEXPR) # if defined(NAMEOF_TYPE_HAS_CONSTEXPR)
sizeof("constexpr nameof::detail::cstring nameof::detail::NameofType() [with T = nameof::detail::nstd::identity<") - 1, sizeof("constexpr nameof::cstring nameof::detail::NameofType() [with T = nameof::detail::nstd::identity<") - 1,
# else # else
sizeof("nameof::detail::cstring nameof::detail::NameofType() [with T = nameof::detail::nstd::identity<") - 1, sizeof("nameof::cstring nameof::detail::NameofType() [with T = nameof::detail::nstd::identity<") - 1,
# endif # endif
sizeof(">]") - 1); sizeof(">]") - 1);
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
return NameofTypePretty( return NameofTypePretty(
{__FUNCSIG__, {__FUNCSIG__,
sizeof(__FUNCSIG__) - 1, sizeof(__FUNCSIG__) - 1,
sizeof("class nameof::detail::cstring __cdecl nameof::detail::NameofType<struct nameof::detail::nstd::identity<") - 1, sizeof("class nameof::cstring __cdecl nameof::detail::NameofType<struct nameof::detail::nstd::identity<") - 1,
sizeof(">>(void) noexcept") - 1}); sizeof(">>(void) noexcept") - 1});
#else #else
return {}; return {};
#endif #endif
} }
} // namespace detail
template <typename T, template <typename T,
typename = typename std::enable_if<!std::is_reference<T>::value>::type> typename = typename std::enable_if<!std::is_reference<T>::value>::type>
constexpr cstring Nameof(const char* name, std::size_t size, bool with_suffix) noexcept { constexpr cstring Nameof(const char* name, std::size_t size, bool with_suffix) noexcept {
return NameofPretty({name, size}, with_suffix); return detail::NameofPretty({name, size}, with_suffix);
} }
template <typename T> template <typename T>
@ -366,23 +371,21 @@ constexpr cstring NameofRaw(const char* name, std::size_t size) noexcept {
return {name, size}; return {name, size};
} }
} // namespace detail
template <typename T, typename H = detail::nstd::identity<T>> template <typename T, typename H = detail::nstd::identity<T>>
NAMEOF_TYPE_CONSTEXPR detail::cstring NameofType() noexcept { NAMEOF_TYPE_CONSTEXPR cstring NameofType() noexcept {
return true ? detail::NameofType<H>() : detail::NameofType<H>(); return true ? detail::NameofType<H>() : detail::NameofType<H>();
} }
} // 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, macros.
#define NAMEOF(...) ::nameof::detail::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, macros. // Used to obtain the full string name of a variable, member, function, macros.
#define NAMEOF_FULL(...) ::nameof::detail::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, macros. // Used to obtain the raw string name of a variable, member, function, macros.
#define NAMEOF_RAW(...) ::nameof::detail::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 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__)>()