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"; }
|
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;
|
||||||
|
@ -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 ();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user