introspection: add type_name_with_namespace
This commit is contained in:
parent
43f5db1cc1
commit
43b8e8f6f2
@ -27,7 +27,7 @@
|
|||||||
namespace cruft {
|
namespace cruft {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr
|
||||||
std::string_view type_name (void)
|
std::string_view type_name_with_namespace (void)
|
||||||
{
|
{
|
||||||
std::string_view pretty_function (__PRETTY_FUNCTION__);
|
std::string_view pretty_function (__PRETTY_FUNCTION__);
|
||||||
|
|
||||||
@ -43,49 +43,59 @@ namespace cruft {
|
|||||||
#error "Unsupported compiler"
|
#error "Unsupported compiler"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Find the location where the type begins. It will also mark the start of
|
// Find the location where the type begins.
|
||||||
// the type's namespace if the type has one.
|
auto const type_begin = std::search (
|
||||||
auto const ns_begin = std::search (
|
|
||||||
pretty_function.begin (),
|
pretty_function.begin (),
|
||||||
pretty_function.end (),
|
pretty_function.end (),
|
||||||
prefix.begin (),
|
prefix.begin (),
|
||||||
prefix.end ()
|
prefix.end ()
|
||||||
);
|
) + prefix.size ();
|
||||||
|
|
||||||
// Find the point the type name ends. Both use ']', but gcc lists
|
// 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[] = ";]";
|
char const suffixes[] = ";]";
|
||||||
auto const type_end = std::find_first_of (
|
auto const type_end = std::find_first_of (
|
||||||
ns_begin,
|
type_begin,
|
||||||
pretty_function.end (),
|
pretty_function.end (),
|
||||||
std::begin (suffixes),
|
std::begin (suffixes),
|
||||||
std::end (suffixes)
|
std::end (suffixes)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Find the start of the first template parameter (or the end of the
|
// Find the start of the first template parameter so we can cut it out.
|
||||||
// string otherwise), and the end of the template parameters for this
|
// If this isn't present we end up with a pointer to the end of the
|
||||||
// type.
|
// type string which is the end of the type anyway.
|
||||||
//
|
auto const template_start = std::find (type_begin, type_end, '<');
|
||||||
// This cursor will be used to limit the scope of the namespace removal
|
auto const template_end = cruft::search::balanced (template_start, type_end, '<', '>');
|
||||||
// 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 end of any namespace symbols
|
return std::string_view (
|
||||||
auto const ns_symbol = std::find (
|
type_begin,
|
||||||
std::make_reverse_iterator (first_template),
|
std::distance (type_begin, template_end)
|
||||||
std::make_reverse_iterator (ns_begin),
|
|
||||||
':'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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<i08> (void) { return "i08"; }
|
||||||
template <> constexpr std::string_view type_name<i16> (void) { return "i16"; }
|
template <> constexpr std::string_view type_name<i16> (void) { return "i16"; }
|
||||||
template <> constexpr std::string_view type_name<i32> (void) { return "i32"; }
|
template <> constexpr std::string_view type_name<i32> (void) { return "i32"; }
|
||||||
|
@ -19,6 +19,9 @@ namespace bar {
|
|||||||
struct qux {
|
struct qux {
|
||||||
short c;
|
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 ()
|
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<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<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 (
|
tap.expect_eq (
|
||||||
cruft::type_name<templated_with_type<int>> (),
|
cruft::type_name<templated_with_type<int>> (),
|
||||||
|
Loading…
Reference in New Issue
Block a user