diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-03-23 18:46:10 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-03-23 18:46:10 +0000 |
commit | 7b44e4f20b91a64b778bcc8b2f00602d4ba13bd2 (patch) | |
tree | 0c8dc333e6a8ffd34ae5675910029d45483166db | |
parent | Use typed collections for apply/applyOne (diff) | |
download | ilt-7b44e4f20b91a64b778bcc8b2f00602d4ba13bd2.tar.bz2 ilt-7b44e4f20b91a64b778bcc8b2f00602d4ba13bd2.tar.xz ilt-7b44e4f20b91a64b778bcc8b2f00602d4ba13bd2.zip |
Support using typed collections for subclass filtering
-rw-r--r-- | lib/collection.h | 17 | ||||
-rw-r--r-- | test/test-collection.cpp | 42 |
2 files changed, 55 insertions, 4 deletions
diff --git a/lib/collection.h b/lib/collection.h index d32cff1..b786e2f 100644 --- a/lib/collection.h +++ b/lib/collection.h @@ -236,12 +236,21 @@ protected: } template<typename T> + requires((std::is_convertible_v<T *, Others *> || ...)) + [[nodiscard]] consteval static bool + idx() + { + size_t typeIdx = 0; + return ((typeIdx++ && std::is_convertible_v<Others *, T *>) || ...); + } + + template<typename T> [[nodiscard]] - const auto & + constexpr const auto & containerFor() const { if constexpr ((std::is_convertible_v<T *, Others *> || ...)) { - return std::get<OtherObjects<T>>(otherObjects); + return std::get<idx<T>()>(otherObjects); } else { return objects; @@ -260,7 +269,7 @@ protected: } else { return std::count_if(begin, end, [&m, ¶ms...](auto && op) { - if (auto o = dynamic_cast<T *>(op.get())) { + if (auto o = dynamic_cast<T *>(std::to_address(op))) { std::invoke(m, o, std::forward<Params>(params)...); return true; } @@ -280,7 +289,7 @@ protected: } else { return std::find_if(begin, end, [&m, ¶ms...](auto && op) { - if (auto o = dynamic_cast<T *>(op.get())) { + if (auto o = dynamic_cast<T *>(std::to_address(op))) { return std::invoke(m, o, std::forward<Params>(params)...); } return false; diff --git a/test/test-collection.cpp b/test/test-collection.cpp index 5aae9f0..a399845 100644 --- a/test/test-collection.cpp +++ b/test/test-collection.cpp @@ -40,10 +40,15 @@ public: } }; +class Sub1 : public Sub { }; + using TestCollection = SharedCollection<Base, Sub>; +BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::Objects::iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::Objects::const_iterator) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::Objects::const_reverse_iterator) +BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::OtherObjects<Sub>::iterator) +BOOST_TEST_DONT_PRINT_LOG_VALUE(TestCollection::OtherObjects<Sub>::const_iterator) BOOST_FIXTURE_TEST_SUITE(tc, TestCollection) @@ -55,6 +60,7 @@ BOOST_AUTO_TEST_CASE(empty) BOOST_CHECK_EQUAL(i, end()); BOOST_CHECK(!find<Base>()); BOOST_CHECK(!find<Sub>()); + BOOST_CHECK(!find<Sub1>()); } BOOST_AUTO_TEST_CASE(a_base) @@ -68,6 +74,7 @@ BOOST_AUTO_TEST_CASE(a_base) BOOST_CHECK_EQUAL(i, end()); BOOST_CHECK_EQUAL(b.get(), find<Base>()); BOOST_CHECK(!find<Sub>()); + BOOST_CHECK(!find<Sub1>()); } BOOST_AUTO_TEST_CASE(emplace_others) @@ -80,6 +87,7 @@ BOOST_AUTO_TEST_CASE(emplace_others) BOOST_CHECK_EQUAL(std::get<OtherObjects<Sub>>(otherObjects).size(), 1); BOOST_CHECK_EQUAL(b.get(), find<Base>()); BOOST_CHECK_EQUAL(s.get(), find<Sub>()); + BOOST_CHECK(!find<Sub1>()); } BOOST_AUTO_TEST_CASE(a_rbase) @@ -103,6 +111,38 @@ BOOST_AUTO_TEST_CASE(a_sub) BOOST_CHECK_EQUAL(*i, s); } +BOOST_AUTO_TEST_CASE(filter) +{ + create<Base>(); + BOOST_CHECK_EQUAL(1, apply<Base>(&Base::yes)); + BOOST_CHECK_EQUAL(0, apply<Sub>(&Base::yes)); + BOOST_CHECK_EQUAL(0, apply<Sub1>(&Base::yes)); + BOOST_CHECK_EQUAL(objects.begin(), applyOne<Base>(&Base::yes)); + BOOST_CHECK_EQUAL(std::get<0>(otherObjects).end(), applyOne<Sub>(&Base::yes)); + BOOST_CHECK_EQUAL(std::get<0>(otherObjects).end(), applyOne<Sub1>(&Base::yes)); + create<Sub>(); + BOOST_CHECK_EQUAL(2, apply<Base>(&Base::yes)); + BOOST_CHECK_EQUAL(1, apply<Sub>(&Base::yes)); + BOOST_CHECK_EQUAL(0, apply<Sub1>(&Base::yes)); + BOOST_CHECK_EQUAL(objects.begin(), applyOne<Base>(&Base::yes)); + BOOST_CHECK_EQUAL(std::get<0>(otherObjects).begin(), applyOne<Sub>(&Base::yes)); + BOOST_CHECK_EQUAL(std::get<0>(otherObjects).end(), applyOne<Sub1>(&Base::yes)); + create<Sub1>(); + BOOST_CHECK_EQUAL(3, apply<Base>(&Base::yes)); + BOOST_CHECK_EQUAL(2, apply<Sub>(&Base::yes)); + BOOST_CHECK_EQUAL(1, apply<Sub1>(&Base::yes)); + BOOST_CHECK_EQUAL(objects.begin(), applyOne<Base>(&Base::yes)); + BOOST_CHECK_EQUAL(std::get<0>(otherObjects).begin(), applyOne<Sub>(&Base::yes)); + BOOST_CHECK_EQUAL(std::get<0>(otherObjects).begin() + 1, applyOne<Sub1>(&Base::yes)); + + BOOST_CHECK_EQUAL(std::get<idx<Sub>()>(otherObjects).size(), 2); + BOOST_CHECK_EQUAL(std::get<idx<Sub1>()>(otherObjects).size(), 2); + + BOOST_CHECK_EQUAL(&objects, &containerFor<Base>()); + BOOST_CHECK_EQUAL(&std::get<0>(otherObjects), &containerFor<Sub>()); + BOOST_CHECK_EQUAL(&std::get<0>(otherObjects), &containerFor<Sub1>()); +} + BOOST_AUTO_TEST_CASE(begin_end) { BOOST_CHECK_EQUAL(0, std::distance(begin(), end())); @@ -230,6 +270,8 @@ BOOST_AUTO_TEST_CASE(applyOneType) create<Sub>(); BOOST_CHECK_EQUAL(objects.begin() + 1, applyOne<Sub>(&Base::yes)); BOOST_CHECK_EQUAL(objects.begin(), applyOne<Base>(&Base::yes)); + create<Sub1>(); + BOOST_CHECK_EQUAL(objects.begin() + 2, applyOne<Sub1>(&Base::yes)); } BOOST_AUTO_TEST_SUITE_END() |