introspection: add pointer-to-member name query
This commit is contained in:
parent
f67b370cd3
commit
3ec1c9591b
@ -102,6 +102,72 @@ namespace cruft::introspection::name {
|
||||
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>
|
||||
struct type_char;
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user