16 template<
class base_component_t, std::derived_from<base_component_t> component_t>
25 using t1 =
typename component_t::inheritance_tuple_type;
26 using t2 =
typename base_component_t::inheritance_tuple_type;
27 using t3 = tuple_utils::remove_t<t1, t2>;
36 , m_eStatusFlags(eStatusFlags)
42 return m_eStatusFlags;
48 m_eStatusFlags = eStatusFlags;
51 template<std::derived_from<rtti_pure_base> base_component_t>
55 if (
const auto it = derivedClasses.find(
id); it != derivedClasses.end())
56 return *it->second.
get();
58 auto pClassData = std::make_unique<class_data>();
59 auto pRawClassData = pClassData.get();
60 derivedClasses[id] = std::move(pClassData);
61 return *pRawClassData;
64 template<std::derived_from<rtti_pure_base> base_component_t>
65 template<std::derived_from<base_component_t> component_t>
67 std::unique_ptr<component_t> pComponent,
74 auto pRawComponent = pComponent.get();
75 class_data& classData = iterate_class_data(
77 [ePriority, statusFlags, pRawComponent](class_data& classData)
81 classData.components.push_back(std::move(pComponent));
85 template<std::derived_from<rtti_pure_base> base_component_t>
91 class_data& classData = iterate_class_data(
93 [pRawComponent](class_data& classData)
96 classData.priorityCache,
97 [pRawComponent](
const auto& pair)
99 return pair.second == pRawComponent;
103 const auto it = std::ranges::find_if(
104 classData.components,
105 [pRawComponent](
const pointer_type& pointer)
107 return pointer.get() == pRawComponent;
110 if (it == classData.components.end())
113 std::unique_ptr<base_component_t> pComponent = std::move(*it);
114 classData.components.erase(it);
118 template<std::derived_from<rtti_pure_base> base_component_t>
119 template<std::derived_from<base_component_t> component_t>
122 class_data& classData = get_or_add_class_data<component_t>();
123 const auto it = std::ranges::find_if(
124 classData.priorityCache,
125 [bIncludeDisabled](
const auto& pair)
127 return bIncludeDisabled || !pair.first.get_status_flags().contains(component_status::disabled);
130 return it != classData.priorityCache.end() ?
static_cast<component_t*
>(it->second) :
nullptr;
133 template<std::derived_from<rtti_pure_base> base_component_t>
134 template<std::derived_from<base_component_t> component_t>
140 template<std::derived_from<rtti_pure_base> base_component_t>
141 template<std::derived_from<base_component_t> component_t>
146 const auto it = std::ranges::find_if(
147 m_RootClass.priorityCache,
148 [
id, bIncludeDisabled](
const auto& pair)
150 return (bIncludeDisabled || !pair.first.get_status_flags().contains(component_status::disabled))
151 && pair.second->is_derived_from_id(id);
154 return it != m_RootClass.priorityCache.end() ? rtti_cast<component_t>(it->second) :
nullptr;
157 template<std::derived_from<rtti_pure_base> base_component_t>
158 template<std::derived_from<base_component_t> component_t>
164 template<std::derived_from<rtti_pure_base> base_component_t>
165 template<std::derived_from<base_component_t> component_t>
168 return *try_get<component_t>(bIncludeDisabled);
171 template<std::derived_from<rtti_pure_base> base_component_t>
172 template<std::derived_from<base_component_t> component_t>
178 template<std::derived_from<rtti_pure_base> base_component_t>
179 template<std::derived_from<base_component_t> component_t>
182 return *try_get<component_t>(
id, bIncludeDisabled);
185 template<std::derived_from<rtti_pure_base> base_component_t>
186 template<std::derived_from<base_component_t> component_t>
192 template<std::derived_from<rtti_pure_base> base_component_t>
193 template<std::derived_from<base_component_t> component_t>
196 class_data& classData = get_or_add_class_data<component_t>();
197 return classData.priorityCache
198 | std::views::filter(
199 [bIncludeDisabled](
const auto& pair)
201 return pair.second->template is_derived_from<component_t>()
202 && (bIncludeDisabled || !pair.first.get_status_flags().contains(component_status::disabled));
204 | std::views::transform(
205 [](
auto& pair) -> component_t&
207 return *
static_cast<component_t*
>(pair.second);
211 template<std::derived_from<rtti_pure_base> base_component_t>
212 template<std::derived_from<base_component_t> component_t>
215 const class_data& classData = get_or_add_class_data<component_t>();
216 return classData.priorityCache
217 | std::views::filter(
218 [bIncludeDisabled](
const auto& pair)
220 return pair.second->template is_derived_from<component_t>()
221 && (bIncludeDisabled || !pair.first.get_status_flags().contains(component_status::disabled));
223 | std::views::transform(
224 [](
const auto& pair) ->
const component_t&
226 return *
static_cast<const component_t*
>(pair.second);
230 template<std::derived_from<rtti_pure_base> base_component_t>
232 const base_component_t* pRawComponent)
const noexcept
234 std::optional<component_status_key> optComponentStatus = get_status(pRawComponent);
235 return optComponentStatus ? std::optional(optComponentStatus->get_status_flags()) : std::nullopt;
238 template<std::derived_from<rtti_pure_base> base_component_t>
240 const base_component_t* pRawComponent,
243 std::optional<component_status_key> optComponentStatus = get_status(pRawComponent);
244 if (!optComponentStatus)
247 optComponentStatus->set_status_flags(newStatus);
248 return set_status(pRawComponent, *optComponentStatus);
251 template<std::derived_from<rtti_pure_base> base_component_t>
253 const base_component_t* pRawComponent,
256 std::optional<flags<component_status>> optComponentStatus = get_component_status(pRawComponent);
257 if (!optComponentStatus)
260 optComponentStatus->add(newStatuses);
261 return set_component_status(pRawComponent, *optComponentStatus);
264 template<std::derived_from<rtti_pure_base> base_component_t>
266 const base_component_t* pRawComponent,
269 std::optional<flags<component_status>> optComponentStatus = get_component_status(pRawComponent);
270 if (!optComponentStatus)
273 optComponentStatus->remove(statusesToRemove);
274 return set_component_status(pRawComponent, *optComponentStatus);
277 template<std::derived_from<rtti_pure_base> base_component_t>
279 const base_component_t* pRawComponent)
const noexcept
281 std::optional<component_status_key> optComponentStatus = get_status(pRawComponent);
282 return optComponentStatus ? std::optional(optComponentStatus->get_priority()) : std::nullopt;
285 template<std::derived_from<rtti_pure_base> base_component_t>
287 const base_component_t* pRawComponent,
288 priority eNewComponentPriority) noexcept
290 std::optional<component_status_key> optComponentStatus = get_status(pRawComponent);
291 if (!optComponentStatus)
294 optComponentStatus->set_priority(eNewComponentPriority);
295 return set_status(pRawComponent, *optComponentStatus);
298 template<std::derived_from<rtti_pure_base> base_component_t>
301 return m_RootClass.priorityCache.empty();
304 template<std::derived_from<rtti_pure_base> base_component_t>
307 m_RootClass.derivedClasses.clear();
308 m_RootClass.components.clear();
309 m_RootClass.priorityCache.clear();
312 template<std::derived_from<rtti_pure_base> base_component_t>
314 const base_component_t* pRawComponent)
const noexcept
319 auto it = std::ranges::find_if(
320 m_RootClass.priorityCache,
321 [pRawComponent](
const auto& pair)
323 return pair.second == pRawComponent;
326 return it != m_RootClass.priorityCache.end() ? std::optional<component_status_key>(it->first) : std::nullopt;
330 template<std::derived_from<rtti_pure_base> base_component_t>
331 bool components<base_component_t>::set_status(
332 const base_component_t* pRawComponent,
333 component_status_key status) noexcept
338 bool bChanged =
true;
341 [pRawComponent, status, &bChanged](class_data& classData)
343 const auto it = std::ranges::find_if(
344 classData.priorityCache,
345 [pRawComponent](
const auto& pair)
347 return pair.second == pRawComponent;
350 if (it == classData.priorityCache.end())
356 if (it->first != status)
358 classData.priorityCache.emplace(status, it->second);
359 classData.priorityCache.erase(it);
366 template<std::derived_from<rtti_pure_base> base_component_t>
368 std::derived_from<base_component_t> component_t,
369 callable_c<void, typename components<base_component_t>::class_data&> callable_t>
370 typename components<base_component_t>::class_data& components<base_component_t>::iterate_class_data(
371 callable_t iterateClassDataFunction) noexcept
373 class_data* pClassData = &m_RootClass;
374 iterateClassDataFunction(*pClassData);
376 tuple_utils::iterate<typename details::get_inheritance_sequence<base_component_t, component_t>::type>(
377 [&pClassData, &iterateClassDataFunction]<
class T, size_t I>()
379 pClassData = &pClassData->get_or_add_class_data(T::get_class_id_static());
380 iterateClassDataFunction(*pClassData);
386 template<std::derived_from<rtti_pure_base> base_component_t>
388 std::derived_from<base_component_t> component_t,
389 callable_c<void, typename components<base_component_t>::class_data&> callable_t>
390 const typename components<base_component_t>::class_data& components<base_component_t>::iterate_class_data(
391 callable_t iterateClassDataFunction)
const noexcept
393 return QX_CONST_CAST_THIS()->template iterate_class_data<component_t>(std::move(iterateClassDataFunction));
396 template<std::derived_from<rtti_pure_base> base_component_t>
397 template<std::derived_from<base_component_t> component_t>
398 typename components<base_component_t>::class_data& components<base_component_t>::get_or_add_class_data() noexcept
400 class_data* pClassData = &m_RootClass;
402 tuple_utils::iterate<typename details::get_inheritance_sequence<base_component_t, component_t>::type>(
403 [&pClassData]<
class T, size_t I>()
405 pClassData = &pClassData->get_or_add_class_data(T::get_class_id_static());
411 template<std::derived_from<rtti_pure_base> base_component_t>
412 template<std::derived_from<base_component_t> component_t>
413 const typename components<base_component_t>::class_data& components<base_component_t>::get_or_add_class_data()
419 template<std::derived_from<rtti_pure_base> base_component_t>
420 template<callable_c<void, typename components<base_component_t>::class_data&> callable_t>
421 typename components<base_component_t>::class_data& components<base_component_t>::iterate_class_data(
422 const base_component_t* pRawComponent,
423 callable_t iterateClassDataFunction) noexcept
425 class_data* pClassData = &m_RootClass;
426 iterateClassDataFunction(*pClassData);
428 std::span<const class_id> allIds = pRawComponent->get_inheritance_sequence();
429 std::span<const class_id> baseClassIds(
430 std::ranges::find(allIds, base_component_t::get_class_id_static()),
433 for (
auto it = baseClassIds.begin() + 1; it != baseClassIds.end(); ++it)
435 pClassData = &pClassData->get_or_add_class_data(*it);
436 iterateClassDataFunction(*pClassData);
442 template<std::derived_from<rtti_pure_base> base_component_t>
443 template<callable_c<void, typename components<base_component_t>::class_data&> callable_t>
444 const typename components<base_component_t>::class_data& components<base_component_t>::iterate_class_data(
445 const base_component_t* pRawComponent,
446 callable_t iterateClassDataFunction)
const noexcept
448 return QX_CONST_CAST_THIS()->iterate_class_data(pRawComponent, std::move(iterateClassDataFunction));
451 template<std::derived_from<rtti_pure_base> base_component_t>
452 typename components<base_component_t>::class_data& components<base_component_t>::get_or_add_class_data(
453 const base_component_t* pRawComponent) noexcept
455 class_data* pClassData = &m_RootClass;
457 std::span<const class_id> allIds = pRawComponent->get_inheritance_sequence();
458 std::span<const class_id> baseClassIds(
459 std::ranges::find(allIds, base_component_t::get_class_id_static()),
462 for (
auto it = baseClassIds.begin() + 1; it != baseClassIds.end(); ++it)
463 pClassData = &pClassData->get_or_add_class_data(*it);
468 template<std::derived_from<rtti_pure_base> base_component_t>
469 const typename components<base_component_t>::class_data& components<base_component_t>::get_or_add_class_data(
470 const base_component_t* pRawComponent)
const noexcept
Class id, unique for each class using qx rtti system.
A class that acts like time_ordered_priority_key but has a status field.
constexpr void set_status_flags(flags< component_status > eStatusFlags) noexcept
Set object status.
constexpr flags< component_status > get_status_flags() const noexcept
Get object status.
Container for components system.
component_t & get(bool bIncludeDisabled=false) noexcept
Get a component of the given type with the highest priority (no existence checks are performed)
std::unique_ptr< base_component_t > remove(const base_component_t *pRawComponent) noexcept
Remove the component from the container.
bool add_component_status(const base_component_t *pRawComponent, flags< component_status > newStatuses) noexcept
Add new component status flags to the current ones.
bool set_component_priority(const base_component_t *pRawComponent, priority eNewComponentPriority) noexcept
Set component priority.
void clear() noexcept
Clear the container, e.g. remove all the components.
component_t * try_get(bool bIncludeDisabled=false) noexcept
Try to get a component of the given type with the highest priority.
bool set_component_status(const base_component_t *pRawComponent, flags< component_status > newStatus) noexcept
Set (override) a component status.
bool empty() const noexcept
Check if container doesn't have any components.
auto view(bool bIncludeDisabled=false) noexcept
Get a view which may be used in a ranged-based for loop and consists of components of a given type wi...
bool remove_component_status(const base_component_t *pRawComponent, flags< component_status > statusesToRemove) noexcept
Add component status flags from the current ones.
component_t * add(std::unique_ptr< component_t > pComponent, priority ePriority=priority::normal, flags< component_status > statusFlags=component_status::default_value) noexcept
Add a component.
std::optional< flags< component_status > > get_component_status(const base_component_t *pRawComponent) const noexcept
Get component status.
std::optional< priority > get_component_priority(const base_component_t *pRawComponent) const noexcept
Get component priority.
A class that can be used as a key in ordered containers so that items are ordered in descending order...
#define QX_CONST_CAST_THIS()
This macro is made for situations where you have a const method, and you need exactly the same method...
priority
User may use the predefined values or the custom ones, for ex. "normal - 1", this type is supposed to...