#include "Test/Test.h" #include "Support/Struct.h" namespace clice::testing { namespace { struct X { int x; int y; friend constexpr bool operator== (const X& lhs, const X& rhs) noexcept = default; }; static_assert(std::is_same_v, type_list>); suite<"Struct"> struct_tests = [] { test("FieldName") = [&] { static struct X { int a; int b; } x; static_assert(refl::impl::member_name<&x.a>() == "a", "Member name mismatch"); static_assert(refl::impl::member_name<&x.b>() == "b", "Member name mismatch"); static_assert(refl::member_names() == std::array{"a", "b"}); static struct Y { X x; } y; static_assert(refl::impl::member_name<&y.x>() == "x", "Member name mismatch"); static_assert(refl::impl::member_name<&y.x.a>() == "a", "Member name mismatch"); static_assert(refl::impl::member_name<&y.x.b>() == "b", "Member name mismatch"); static_assert(refl::member_names() == std::array{"x"}); struct H { X x; Y y; H() = delete; }; static union Z { char dummy; H h; Z() {}; ~Z() {}; } z; static_assert(refl::impl::member_name<&z.h.x>() == "x", "Member name mismatch"); static_assert(refl::impl::member_name<&z.h.y>() == "y", "Member name mismatch"); static_assert(refl::impl::member_name<&z.h.y.x>() == "x", "Member name mismatch"); struct M { X x; Y y; H h; }; static_assert(refl::member_names() == std::array{"x", "y", "h"}); }; test("Foreach") = [&] { bool x = false, y = false; refl::foreach(X{1, 2}, [&](auto name, auto value) { if(name == "x") { x = true; expect(that % value == 1); } else if(name == "y") { y = true; expect(that % value == 2); } else { expect(false); } }); expect(that % x && y); X x1 = {1, 2}; X x2 = {3, 4}; expect(that % refl::foreach(x1, x2, [](auto& lhs, auto& rhs) { return lhs = rhs; })); expect(that % x1.x == 3); expect(that % x1.y == 4); }; test("Inheritance") = [&] { inherited_struct(Y, X) { int z; }; static_assert(std::is_same_v, type_list>); bool x = false, y = false, z = false; refl::foreach(Y{1, 2, 3}, [&](auto name, auto value) { if(name == "x") { x = true; expect(that % value == 1); } else if(name == "y") { y = true; expect(that % value == 2); } else if(name == "z") { z = true; expect(that % value == 3); } else { expect(false); } }); expect(that % x && y && z); Y y1 = {1, 2, 3}; Y y2 = {4, 5, 6}; expect(that % refl::foreach(y1, y2, [](auto& lhs, auto& rhs) { return lhs = rhs; })); expect(that % y1.x == 4); expect(that % y1.y == 5); expect(that % y1.z == 6); }; test("TupleLike") = [&] { std::pair p = {1, 2}; static_assert(refl::member_names() == std::array{"0", "1"}); std::tuple t = {1, 2}; static_assert(refl::member_names() == std::array{"0", "1"}); bool x = false, y = false; refl::foreach(t, [&](auto name, auto value) { if(name == "0") { x = true; expect(that % value == 1); } else if(name == "1") { y = true; expect(that % value == 2); } else { expect(false); } }); expect(that % x && y); std::tuple t1 = {1, 2}; std::tuple t2 = {3, 4}; expect(that % refl::foreach(t1, t2, [](auto& lhs, auto& rhs) { return lhs = rhs; })); expect(that % std::get<0>(t1) == 3); expect(that % std::get<1>(t1) == 4); expect(that % std::get<0>(t2) == 3); }; }; } // namespace } // namespace clice::testing