introspection: correct the member name offset calculations

This commit is contained in:
Danny Robson 2021-04-08 13:15:57 +10:00
parent 6cac76e210
commit f5a1105d48

View File

@ -10,6 +10,7 @@
#include "../algo/search.hpp" #include "../algo/search.hpp"
#include "../std.hpp" #include "../std.hpp"
#include "../platform.hpp"
#include <string_view> #include <string_view>
#include <algorithm> #include <algorithm>
@ -106,11 +107,11 @@ namespace cruft::introspection::name {
namespace detail { namespace detail {
template <std::size_t N> template <std::size_t N>
constexpr std::size_t 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); 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) if (str[i] == target)
return i; return i;
@ -141,18 +142,30 @@ namespace cruft::introspection::name {
constexpr std::string_view constexpr std::string_view
member (void) member (void)
{ {
// __PRETTY_FUNCTION__ #if defined(COMPILER_GCC)
// GCC: "constexpr auto name() [with A = int; B = foo_t; A B::* member = &foo_t::abc]" // 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<char>]"
// clang: "auto name() [A = int, B = foo_t, member = &foo_t::abc]" //
// // We find the last semicolon, then count back to the colon.
// 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__; constexpr std::size_t b = detail::rfind (__PRETTY_FUNCTION__, ';');
return std::string_view (name.data () + a, b - a); 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
} }