introspection: add type_name_with_namespace
This commit is contained in:
parent
43f5db1cc1
commit
43b8e8f6f2
@ -27,7 +27,7 @@
|
||||
namespace cruft {
|
||||
template <typename T>
|
||||
constexpr
|
||||
std::string_view type_name (void)
|
||||
std::string_view type_name_with_namespace (void)
|
||||
{
|
||||
std::string_view pretty_function (__PRETTY_FUNCTION__);
|
||||
|
||||
@ -43,49 +43,59 @@ namespace cruft {
|
||||
#error "Unsupported compiler"
|
||||
#endif
|
||||
|
||||
// Find the location where the type begins. It will also mark the start of
|
||||
// the type's namespace if the type has one.
|
||||
auto const ns_begin = std::search (
|
||||
// Find the location where the type begins.
|
||||
auto const type_begin = std::search (
|
||||
pretty_function.begin (),
|
||||
pretty_function.end (),
|
||||
prefix.begin (),
|
||||
prefix.end ()
|
||||
);
|
||||
) + prefix.size ();
|
||||
|
||||
// Find the point the type name ends. Both use ']', but gcc lists
|
||||
// std::string_view too and so requires the delimiting ';' as a suffix.
|
||||
// std::string_view in the function signature too and so requires the
|
||||
// delimiting ';' as a suffix.
|
||||
char const suffixes[] = ";]";
|
||||
auto const type_end = std::find_first_of (
|
||||
ns_begin,
|
||||
type_begin,
|
||||
pretty_function.end (),
|
||||
std::begin (suffixes),
|
||||
std::end (suffixes)
|
||||
std::end (suffixes)
|
||||
);
|
||||
|
||||
// Find the start of the first template parameter (or the end of the
|
||||
// string otherwise), and the end of the template parameters for this
|
||||
// type.
|
||||
//
|
||||
// This cursor will be used to limit the scope of the namespace removal
|
||||
// we're about to do.
|
||||
auto const first_template = std::find (ns_begin, type_end, '<');
|
||||
auto const end_first_template = cruft::search::balanced (first_template, type_end, '<', '>');
|
||||
// Find the start of the first template parameter so we can cut it out.
|
||||
// If this isn't present we end up with a pointer to the end of the
|
||||
// type string which is the end of the type anyway.
|
||||
auto const template_start = std::find (type_begin, type_end, '<');
|
||||
auto const template_end = cruft::search::balanced (template_start, type_end, '<', '>');
|
||||
|
||||
// Find the end of any namespace symbols
|
||||
auto const ns_symbol = std::find (
|
||||
std::make_reverse_iterator (first_template),
|
||||
std::make_reverse_iterator (ns_begin),
|
||||
':'
|
||||
return std::string_view (
|
||||
type_begin,
|
||||
std::distance (type_begin, template_end)
|
||||
);
|
||||
|
||||
// Compute the start of the symbol's type and return a view over this.
|
||||
auto const data = ns_symbol != std::make_reverse_iterator (ns_begin)
|
||||
? &*ns_symbol + 1
|
||||
: ns_begin + prefix.size ();
|
||||
auto const size = std::distance (data, end_first_template);
|
||||
return std::string_view (data, size);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
constexpr
|
||||
std::string_view type_name (void)
|
||||
{
|
||||
|
||||
auto const fullname = type_name_with_namespace<T> ();
|
||||
|
||||
constexpr char const namespace_symbol[] = "::";
|
||||
auto const last_namespace_pos = std::search (
|
||||
std::rbegin (fullname),
|
||||
std::rend (fullname),
|
||||
namespace_symbol + 0,
|
||||
namespace_symbol + 2
|
||||
);
|
||||
|
||||
auto const length = std::distance (std::rbegin (fullname), last_namespace_pos);
|
||||
auto const offset = fullname.size () - length;
|
||||
return std::string_view (fullname.data () + offset, length);
|
||||
}
|
||||
|
||||
|
||||
template <> constexpr std::string_view type_name<i08> (void) { return "i08"; }
|
||||
template <> constexpr std::string_view type_name<i16> (void) { return "i16"; }
|
||||
template <> constexpr std::string_view type_name<i32> (void) { return "i32"; }
|
||||
|
@ -19,6 +19,9 @@ namespace bar {
|
||||
struct qux {
|
||||
short c;
|
||||
};
|
||||
|
||||
template <typename>
|
||||
struct templated_qux { };
|
||||
}
|
||||
|
||||
|
||||
@ -55,6 +58,19 @@ namespace cruft
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename A, typename B>
|
||||
static
|
||||
bool
|
||||
equal (A &&a, B &&b)
|
||||
{
|
||||
return std::equal (
|
||||
std::begin (a), std::end (a),
|
||||
std::begin (b), std::end (b)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int main ()
|
||||
{
|
||||
@ -92,7 +108,23 @@ int main ()
|
||||
tap.expect_eq (cruft::view (cruft::type_name<f64> ()), "f64", "f64 type_name");
|
||||
|
||||
tap.expect_eq (cruft::view (cruft::type_name<foo> ()), "foo", "struct type_name");
|
||||
tap.expect_eq (cruft::view (cruft::type_name<bar::qux> ()), "qux", "namespaced struct type_name");
|
||||
tap.expect_eq (cruft::view (cruft::type_name<bar::qux> ()), "qux", "de-namespaced struct type_name");
|
||||
|
||||
tap.expect (
|
||||
equal (
|
||||
cruft::type_name_with_namespace<bar::qux> (),
|
||||
std::string_view ("bar::qux")
|
||||
),
|
||||
"namespaced struct"
|
||||
);
|
||||
|
||||
tap.expect (
|
||||
equal (
|
||||
cruft::type_name_with_namespace<bar::templated_qux<int>> (),
|
||||
std::string_view ("bar::templated_qux<int>")
|
||||
),
|
||||
"namespaced templated struct"
|
||||
);
|
||||
|
||||
tap.expect_eq (
|
||||
cruft::type_name<templated_with_type<int>> (),
|
||||
|
Loading…
Reference in New Issue
Block a user