From f5a1105d489fd36e7948456fc1bbb17d846bb354 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 8 Apr 2021 13:15:57 +1000 Subject: [PATCH] introspection: correct the member name offset calculations --- introspection/name.hpp | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/introspection/name.hpp b/introspection/name.hpp index 024a9bf8..d0c9fcac 100644 --- a/introspection/name.hpp +++ b/introspection/name.hpp @@ -10,6 +10,7 @@ #include "../algo/search.hpp" #include "../std.hpp" +#include "../platform.hpp" #include #include @@ -106,11 +107,11 @@ namespace cruft::introspection::name { namespace detail { template constexpr std::size_t - rfind (char const (&str)[N], char target) + rfind (char const (&str)[N], char target, int offset = N) { static_assert (N > 1); - for (std::size_t i = N - 1; i; --i) + for (std::size_t i = N - 1 - (N - offset); i; --i) if (str[i] == target) return i; @@ -141,18 +142,30 @@ namespace cruft::introspection::name { constexpr std::string_view member (void) { - // __PRETTY_FUNCTION__ - // GCC: "constexpr auto name() [with A = int; B = foo_t; A B::* member = &foo_t::abc]" - // clang: "auto name() [A = int, B = foo_t, member = &foo_t::abc]" - // - // The strategy is to count back from the end of the string to find - // the ampersand and return everything between that and the final - // character (which is always a ']'). - constexpr std::size_t a = detail::rfind (__PRETTY_FUNCTION__, ':') + 1; - constexpr std::size_t b = detail::rfind (__PRETTY_FUNCTION__, ']'); + #if defined(COMPILER_GCC) + // GCC: "constexpr std::string_view cruft::introspection::name::member() [with TypeT = int; KlassT = foo; TypeT KlassT::* Ptr = &foo::a; std::string_view = std::basic_string_view]" + // + // We find the last semicolon, then count back to the colon. - constexpr std::string_view name = __PRETTY_FUNCTION__; - return std::string_view (name.data () + a, b - a); + constexpr std::size_t b = detail::rfind (__PRETTY_FUNCTION__, ';'); + constexpr std::size_t a = detail::rfind (__PRETTY_FUNCTION__, ':', b) + 1; + + constexpr std::string_view name = __PRETTY_FUNCTION__; + return std::string_view (name.data () + a, b - a); + #elif defined(COMPILER_CLANG) + // std::string_view cruft::introspection::name::member() [TypeT = int, KlassT = foo, Ptr = &foo::a] + // + // The strategy is to count back from the end of the string to find + // the ampersand and return everything between that and the final + // character (which is always a ']'). + + constexpr std::size_t a = detail::rfind (__PRETTY_FUNCTION__, ':') + 1; + constexpr std::size_t b = detail::rfind (__PRETTY_FUNCTION__, ']'); + constexpr std::string_view name = __PRETTY_FUNCTION__; + return std::string_view (name.data () + a, b - a); + #else + #error "Unsupported compiler" + #endif }