introspection: add pointer-to-member name query

This commit is contained in:
Danny Robson 2021-03-26 15:24:31 +10:00
parent f67b370cd3
commit 3ec1c9591b
2 changed files with 72 additions and 0 deletions

View File

@ -102,6 +102,72 @@ namespace cruft::introspection::name {
template <> constexpr std::string_view bare<f64> (void) { return "f64"; } template <> constexpr std::string_view bare<f64> (void) { return "f64"; }
///////////////////////////////////////////////////////////////////////////////
namespace detail {
template <std::size_t N>
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 <typename T>
struct pointer_to_member_type { };
template <typename A, typename B>
struct pointer_to_member_type<A B::*> { using type = A; };
template <typename T>
struct pointer_to_member_class { };
template <typename A, typename B>
struct pointer_to_member_class<A B::*> { using type = B; };
///------------------------------------------------------------------------
/// Returns a stringview containing the name of the member pointed to by
/// the pointer-tomember.
template <typename TypeT, typename KlassT, TypeT KlassT::*Ptr>
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 <auto Ptr>
constexpr std::string_view
member (void)
{
return member<
typename pointer_to_member_type <decltype(Ptr)>::type,
typename pointer_to_member_class<decltype(Ptr)>::type,
Ptr
> ();
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
template <typename T> template <typename T>
struct type_char; struct type_char;

View File

@ -195,5 +195,11 @@ int main ()
"templated_with_enum" "templated_with_enum"
); );
tap.expect_eq (
cruft::introspection::name::member<&foo::a> (),
std::string_view ("a"),
"pointer-to-member name"
);
return tap.status (); return tap.status ();
} }