From 5a0b3927a33807cca4c77c40eb873f8a3b51b0b0 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 29 Apr 2023 19:07:11 +0100 Subject: Drop .hpp for header only things Half of them acquired a .cpp part anyway --- lib/collection.h | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 lib/collection.h (limited to 'lib/collection.h') diff --git a/lib/collection.h b/lib/collection.h new file mode 100644 index 0000000..6802bcb --- /dev/null +++ b/lib/collection.h @@ -0,0 +1,131 @@ +#pragma once + +#include +#include +#include +#include +#include + +template class Collection { +public: + virtual ~Collection() = default; + + using Ptr = std::conditional_t, std::unique_ptr>; + using Objects = std::vector; + Objects objects; + + template + auto + create(Params &&... params) + requires std::is_base_of_v + { + if constexpr (shared) { + auto obj = std::make_shared(std::forward(params)...); + objects.emplace_back(obj); + return obj; + } + else { + return static_cast(objects.emplace_back(std::make_unique(std::forward(params)...)).get()); + } + } + + template + T * + find() + { + if (auto i = std::find_if(objects.begin(), objects.end(), + [](auto && o) { + return (dynamic_cast(o.get())); + }); + i != objects.end()) { + return static_cast(i->get()); + } + return nullptr; + } + + template + auto + findOrCreate(Params &&... params) + requires std::is_base_of_v + { + if (auto o = find()) { + return o; + } + return create(std::forward(params)...).get(); + } + + template + auto + apply(const auto & m, Params &&... params) const + { + return apply_internal(objects.begin(), objects.end(), m, std::forward(params)...); + } + + template + auto + rapply(const auto & m, Params &&... params) const + { + return apply_internal(objects.rbegin(), objects.rend(), m, std::forward(params)...); + } + + template + auto + applyOne(const auto & m, Params &&... params) const + { + return applyOne_internal(objects.begin(), objects.end(), m, std::forward(params)...); + } + + template + auto + rapplyOne(const auto & m, Params &&... params) const + { + return applyOne_internal(objects.rbegin(), objects.rend(), m, std::forward(params)...); + } + + template + auto + removeAll() + { + return std::erase_if(objects, [](auto && op) { + return dynamic_cast(op.get()); + }); + } + + auto + end() const + { + return objects.end(); + } + + auto + rend() const + { + return objects.rend(); + } + +protected: + template + auto + apply_internal(const auto begin, const auto end, const auto & m, Params &&... params) const + { + return std::count_if(begin, end, [&m, ¶ms...](auto && op) { + if (auto o = dynamic_cast(op.get())) { + std::invoke(m, o, std::forward(params)...); + return true; + } + return false; + }); + } + + template + auto + applyOne_internal(const auto begin, const auto end, const auto & m, Params &&... params) const + { + return std::find_if(begin, end, [&m, ¶ms...](auto && op) { + if (auto o = dynamic_cast(op.get())) { + return std::invoke(m, o, std::forward(params)...); + } + return false; + }); + } +}; -- cgit v1.2.3