diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-19 18:31:08 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-19 18:31:08 +0100 |
commit | cb665e2f6a829285f37abc72d03e434707f5af0d (patch) | |
tree | 3bebbdcc60ee26f15c2f9637e17f4e99e56b4f82 | |
parent | b0841e820860d09e0498554a43c01055e99baa57 (diff) |
entity: get field data indirectly via a specialization
so now classes will be able to #ifdef including `entity/metadata.hpp`
and specifying the fields without incurring an ODR violation.
-rw-r--r-- | entity/metadata.hpp | 10 | ||||
-rw-r--r-- | test/entity.cpp | 42 |
2 files changed, 33 insertions, 19 deletions
diff --git a/entity/metadata.hpp b/entity/metadata.hpp index 935f1792..0014f63c 100644 --- a/entity/metadata.hpp +++ b/entity/metadata.hpp @@ -15,6 +15,12 @@ #include <compat/function2.hpp> #include <Corrade/Containers/StringView.h> +namespace floormat::entities { + +template<typename T> struct entity_accessors; + +} // namespace floormat::entities + namespace floormat::entities::detail { template<typename F, typename Tuple, std::size_t N> @@ -46,7 +52,7 @@ constexpr CORRADE_ALWAYS_INLINE bool find_in_tuple(F&& fun, Tuple&& tuple) template<typename T> struct decay_tuple_; template<typename... Ts> struct decay_tuple_<std::tuple<Ts...>> { using type = std::tuple<std::decay_t<Ts>...>; }; template<typename T> using decay_tuple = typename decay_tuple_<T>::type; -template<typename T> struct accessors_for_ { using type = decay_tuple<std::decay_t<decltype(T::accessors())>>; }; +template<typename T> struct accessors_for_ { using type = decay_tuple<std::decay_t<decltype(entity_accessors<T>::accessors())>>; }; template<typename T> using accessors_for = typename accessors_for_<T>::type; template<typename Obj, typename Type, typename Default, std::size_t I, typename... Fs> struct find_reader; @@ -269,7 +275,7 @@ class entity_metadata final { public: static constexpr StringView class_name = name_of<T>; static constexpr std::size_t size = std::tuple_size_v<entities::detail::accessors_for<T>>; - static constexpr entities::detail::accessors_for<T> accessors = T::accessors(); + static constexpr entities::detail::accessors_for<T> accessors = entities::entity_accessors<T>::accessors(); static constexpr auto erased_accessors = erased_helper(accessors); }; diff --git a/test/entity.cpp b/test/entity.cpp index a10cbb98..ce7af58b 100644 --- a/test/entity.cpp +++ b/test/entity.cpp @@ -15,23 +15,31 @@ struct TestAccessors { int foo; int _bar; int _baz; +}; + +} // namespace - static constexpr auto accessors() noexcept; +namespace floormat::entities { + +template<> struct entity_accessors<TestAccessors> { + static constexpr auto accessors() + { + using entity = Entity<TestAccessors>; + constexpr auto r_baz = [](const TestAccessors& x) { return x._baz; }; + constexpr auto w_baz = [](TestAccessors& x, int v) { x._baz = v; }; + + constexpr auto tuple = std::make_tuple( + entity::type<int>::field{"foo"_s, &TestAccessors::foo, &TestAccessors::foo}, + entity::type<int>::field{"bar"_s, &TestAccessors::bar, &TestAccessors::set_bar}, + entity::type<int>::field("baz"_s, r_baz, w_baz) + ); + return tuple; + } }; -constexpr auto TestAccessors::accessors() noexcept -{ - using entity = Entity<TestAccessors>; - constexpr auto r_baz = [](const TestAccessors& x) { return x._baz; }; - constexpr auto w_baz = [](TestAccessors& x, int v) { x._baz = v; }; - - constexpr auto tuple = std::make_tuple( - entity::type<int>::field{"foo"_s, &TestAccessors::foo, &TestAccessors::foo}, - entity::type<int>::field{"bar"_s, &TestAccessors::bar, &TestAccessors::set_bar}, - entity::type<int>::field("baz"_s, r_baz, w_baz) - ); - return tuple; -} +} // namespace floormat::entities + +namespace { using entity = Entity<TestAccessors>; constexpr auto m_foo = entity::type<int>::field{"foo"_s, &TestAccessors::foo, &TestAccessors::foo}; @@ -151,7 +159,7 @@ void test_type_name() constexpr auto foo = entity::type<int>::field{"foo"_s, &TestAccessors::foo, nullptr}; static_assert(foo.writer == nullptr); static_assert(!foo.can_write); - static_assert(std::get<0>(TestAccessors::accessors()).can_write); + static_assert(std::get<0>(entity_accessors<TestAccessors>::accessors()).can_write); } void test_predicate() @@ -189,7 +197,7 @@ constexpr bool test_names() constexpr void test_constraints() { constexpr auto x = TestAccessors{}; - constexpr auto foo = entity::type<int>::field{ + constexpr auto foo = entity::type<int>::field { "foo"_s, &TestAccessors::foo, &TestAccessors::foo, constantly(constraints::max_length{42}), constantly(constraints::range<int>{37, 42}), @@ -221,8 +229,8 @@ void test_erased_constraints() constantly(constraints::range<int>{37, 42}), constantly(constraints::group{"foo"_s}) }; + static constexpr auto erased = foo.erased(); const auto x = TestAccessors{}; - const auto erased = foo.erased(); fm_assert(erased.get_range(x) == constraints::range<int>{37, 42}); fm_assert(erased.get_max_length(x) == 42); |