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 "../std.hpp"
#include "../platform.hpp"
#include <string_view>
#include <algorithm>
@ -106,11 +107,11 @@ namespace cruft::introspection::name {
namespace detail {
template <std::size_t N>
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<char>]"
//
// 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
}