diff --git a/introspection/name.hpp b/introspection/name.hpp index 2be0d128..36b192f2 100644 --- a/introspection/name.hpp +++ b/introspection/name.hpp @@ -102,6 +102,72 @@ namespace cruft::introspection::name { template <> constexpr std::string_view bare (void) { return "f64"; } + /////////////////////////////////////////////////////////////////////////////// + namespace detail { + template + constexpr std::size_t + rfind (char const (&str)[N], char target) + { + static_assert (N > 1); + + for (std::size_t i = N - 1; i; --i) + if (str[i] == target) + return i; + + return 0; + } + } + + + /////////////////////////////////////////////////////////////////////////// + template + struct pointer_to_member_type { }; + + template + struct pointer_to_member_type { using type = A; }; + + template + struct pointer_to_member_class { }; + + template + struct pointer_to_member_class { using type = B; }; + + + + ///------------------------------------------------------------------------ + /// Returns a stringview containing the name of the member pointed to by + /// the pointer-tomember. + template + 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__, ']'); + + constexpr std::string_view name = __PRETTY_FUNCTION__; + return std::string_view (name.data () + a, b - a); + } + + + template + constexpr std::string_view + member (void) + { + return member< + typename pointer_to_member_type ::type, + typename pointer_to_member_class::type, + Ptr + > (); + } + + /////////////////////////////////////////////////////////////////////////// template struct type_char; diff --git a/test/introspection.cpp b/test/introspection.cpp index 13b9ee5c..07e1bb31 100644 --- a/test/introspection.cpp +++ b/test/introspection.cpp @@ -195,5 +195,11 @@ int main () "templated_with_enum" ); + tap.expect_eq ( + cruft::introspection::name::member<&foo::a> (), + std::string_view ("a"), + "pointer-to-member name" + ); + return tap.status (); }