#include "introspection/name.hpp" #include "introspection/type.hpp" #include "std.hpp" #include "tap.hpp" #include <iostream> /////////////////////////////////////////////////////////////////////////////// // simple test struct of scalars struct foo { int a; float b; }; //----------------------------------------------------------------------------- namespace bar { struct qux { short c; }; template <typename> struct templated_qux { }; } /////////////////////////////////////////////////////////////////////////////// template <typename ...ValueT> struct templated_with_type { }; template <int ValueV> struct templated_with_value { }; enum enumeration_t { FOO }; template <enumeration_t EnumV> struct templated_with_enum { }; /////////////////////////////////////////////////////////////////////////////// // define introspection data namespace cruft::introspection { template <> struct type<foo> { typedef std::tuple< field<foo,int,&foo::a>, field<foo,float,&foo::b> > fields; }; template <> const std::string field<foo,int,&foo::a>::name = "a"; template <> const std::string field<foo,float,&foo::b>::name = "b"; } //----------------------------------------------------------------------------- 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) ); } ///---------------------------------------------------------------------------- /// Returns true if the two strings are equal except for any embedded /// whitespace. static bool whitespace_equal (std::string_view a, std::string_view b) { auto const a_size = std::ssize (a); auto const b_size = std::ssize (b); int a_cursor = 0; int b_cursor = 0; while (a_cursor < a_size && b_cursor < b_size) { if (a[a_cursor] == ' ') { ++a_cursor; continue; } if (b[b_cursor] == ' ') { ++b_cursor; continue; } if (a[a_cursor] != b[b_cursor]) return false; ++a_cursor; ++b_cursor; } return a_cursor == a_size && b_cursor == b_size; } //----------------------------------------------------------------------------- int main () { cruft::TAP::logger tap; // Ensure tuples are mapped to themselves with type_tuple::type { using src_t = std::tuple<int>; using dst_t = typename cruft::introspection::type_tuple<src_t>::type; tap.expect (std::is_same<src_t, dst_t>::value, "static identity type_tuple"); } // Check member extraction from a simple POD structure. { foo d_foo { 7, 42.0 }; auto f_tuple = cruft::introspection::as_tuple (d_foo); tap.expect (cruft::equal (d_foo.a, std::get<0> (f_tuple)) && cruft::equal (d_foo.b, std::get<1> (f_tuple)), "dynamic member access after conversion to tuple"); } tap.expect_eq (cruft::view (cruft::introspection::name::bare<i08> ()), "i08", "i08 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<i16> ()), "i16", "i16 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<i32> ()), "i32", "i32 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<i64> ()), "i64", "i64 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<u08> ()), "u08", "u08 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<u16> ()), "u16", "u16 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<u32> ()), "u32", "u32 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<u64> ()), "u64", "u64 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<f32> ()), "f32", "f32 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<f64> ()), "f64", "f64 type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<foo> ()), "foo", "struct type_name"); tap.expect_eq (cruft::view (cruft::introspection::name::bare<bar::qux> ()), "qux", "de-namespaced struct type_name"); tap.expect ( equal ( cruft::introspection::name::full<bar::qux> (), std::string_view ("bar::qux") ), "namespaced struct" ); tap.expect ( equal ( cruft::introspection::name::full<bar::templated_qux<int>> (), std::string_view ("bar::templated_qux<int>") ), "namespaced templated struct" ); tap.expect_eq ( cruft::introspection::name::full<templated_with_type<int>> (), std::string_view {"templated_with_type<int>"}, "templated_with_type" ); tap.expect_eq ( cruft::introspection::name::full<templated_with_type<int, int>> (), std::string_view {"templated_with_type<int, int>"}, "templated_with_type" ); // The trailing '>' characters are separated by whitespace in GCC, and // Clang<11, but aren't meaningfully different in user interpretation. tap.expect ( whitespace_equal ( cruft::introspection::name::full<templated_with_type<templated_with_type<int>>> (), std::string_view {"templated_with_type<templated_with_type<int>>"} ), "templated_with_type" ); tap.expect_eq ( cruft::introspection::name::full<templated_with_value<-1>> (), std::string_view {"templated_with_value<-1>"}, "templated_with_value" ); tap.expect_eq ( cruft::introspection::name::full<templated_with_enum<FOO>> (), std::string_view {"templated_with_enum<FOO>"}, "templated_with_enum" ); return tap.status (); }