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;
47 m_eStatusFlags = eStatusFlags;
50 template<std::derived_from<rtti_pure_base> base_component_t>
54 if (
const auto it = derivedClasses.find(
id); it != derivedClasses.end())
55 return *it->second.
get();
57 auto pClassData = std::make_unique<class_data>();
58 auto pRawClassData = pClassData.get();
59 derivedClasses[id] = std::move(pClassData);
60 return *pRawClassData;
63 template<std::derived_from<rtti_pure_base> base_component_t>
64 template<std::derived_from<base_component_t> component_t>
66 std::unique_ptr<component_t> pComponent,
73 auto pRawComponent = pComponent.get();
74 class_data& classData = iterate_class_data(
76 [ePriority, statusFlags, pRawComponent](class_data& classData)
80 classData.components.push_back(std::move(pComponent));
84 template<std::derived_from<rtti_pure_base> base_component_t>
90 class_data& classData = iterate_class_data(
92 [pRawComponent](class_data& classData)
95 classData.priorityCache,
96 [pRawComponent](
const auto& pair)
98 return pair.second == pRawComponent;
102 const auto it = std::ranges::find_if(
103 classData.components,
104 [pRawComponent](
const pointer_type& pointer)
106 return pointer.get() == pRawComponent;
109 if (it == classData.components.end())
112 std::unique_ptr<base_component_t> pComponent = std::move(*it);
113 classData.components.erase(it);
117 template<std::derived_from<rtti_pure_base> base_component_t>
118 template<std::derived_from<base_component_t> component_t>
121 class_data& classData = get_or_add_class_data<component_t>();
122 const auto it = std::ranges::find_if(
123 classData.priorityCache,
124 [bIncludeDisabled](
const auto& pair)
126 return bIncludeDisabled || !pair.first.get_status_flags().contains(component_status::disabled);
129 return it != classData.priorityCache.end() ?
static_cast<component_t*
>(it->second) :
nullptr;
132 template<std::derived_from<rtti_pure_base> base_component_t>
133 template<std::derived_from<base_component_t> component_t>
139 template<std::derived_from<rtti_pure_base> base_component_t>
140 template<std::derived_from<base_component_t> component_t>
145 const auto it = std::ranges::find_if(
146 m_RootClass.priorityCache,
147 [
id, bIncludeDisabled](
const auto& pair)
149 return (bIncludeDisabled || !pair.first.get_status_flags().contains(component_status::disabled))
150 && pair.second->is_derived_from_id(id);
153 return it != m_RootClass.priorityCache.end() ? rtti_cast<component_t>(it->second) :
nullptr;
156 template<std::derived_from<rtti_pure_base> base_component_t>
157 template<std::derived_from<base_component_t> component_t>
163 template<std::derived_from<rtti_pure_base> base_component_t>
164 template<std::derived_from<base_component_t> component_t>
167 return *try_get<component_t>(bIncludeDisabled);
170 template<std::derived_from<rtti_pure_base> base_component_t>
171 template<std::derived_from<base_component_t> component_t>
177 template<std::derived_from<rtti_pure_base> base_component_t>
178 template<std::derived_from<base_component_t> component_t>
181 return *try_get<component_t>(
id, bIncludeDisabled);
184 template<std::derived_from<rtti_pure_base> base_component_t>
185 template<std::derived_from<base_component_t> component_t>
191 template<std::derived_from<rtti_pure_base> base_component_t>
192 template<std::derived_from<base_component_t> component_t>
195 class_data& classData = get_or_add_class_data<component_t>();
196 return classData.priorityCache
197 | std::views::filter(
200 return pair.second->template is_derived_from<component_t>()
201 && !pair.first.get_status_flags().contains(component_status::disabled);
203 | std::views::transform(
204 [](
auto& pair) -> component_t&
206 return *
static_cast<component_t*
>(pair.second);
210 template<std::derived_from<rtti_pure_base> base_component_t>
211 template<std::derived_from<base_component_t> component_t>
214 const class_data& classData = get_or_add_class_data<component_t>();
215 return classData.priorityCache
216 | std::views::filter(
219 return pair.second->template is_derived_from<component_t>()
220 && !pair.first.get_status_flags().contains(component_status::disabled);
222 | std::views::transform(
223 [](
const auto& pair) ->
const component_t&
225 return *
static_cast<const component_t*
>(pair.second);
229 template<std::derived_from<rtti_pure_base> base_component_t>
231 const base_component_t* pRawComponent)
const noexcept
233 std::optional<component_status_key> optComponentStatus = get_status(pRawComponent);
234 return optComponentStatus ? std::optional(optComponentStatus->get_status_flags()) : std::nullopt;
237 template<std::derived_from<rtti_pure_base> base_component_t>
239 const base_component_t* pRawComponent,
242 std::optional<component_status_key> optComponentStatus = get_status(pRawComponent);
243 if (!optComponentStatus)
246 optComponentStatus->set_status_flags(newStatus);
247 return set_status(pRawComponent, *optComponentStatus);
250 template<std::derived_from<rtti_pure_base> base_component_t>
252 const base_component_t* pRawComponent,
255 std::optional<flags<component_status>> optComponentStatus = get_component_status(pRawComponent);
256 if (!optComponentStatus)
259 optComponentStatus->add(newStatuses);
260 return set_component_status(pRawComponent, *optComponentStatus);
263 template<std::derived_from<rtti_pure_base> base_component_t>
265 const base_component_t* pRawComponent,
268 std::optional<flags<component_status>> optComponentStatus = get_component_status(pRawComponent);
269 if (!optComponentStatus)
272 optComponentStatus->remove(statusesToRemove);
273 return set_component_status(pRawComponent, *optComponentStatus);
276 template<std::derived_from<rtti_pure_base> base_component_t>
278 const base_component_t* pRawComponent)
const noexcept
280 std::optional<component_status_key> optComponentStatus = get_status(pRawComponent);
281 return optComponentStatus ? std::optional(optComponentStatus->get_priority()) : std::nullopt;
284 template<std::derived_from<rtti_pure_base> base_component_t>
286 const base_component_t* pRawComponent,
287 priority eNewComponentPriority) noexcept
289 std::optional<component_status_key> optComponentStatus = get_status(pRawComponent);
290 if (!optComponentStatus)
293 optComponentStatus->set_priority(eNewComponentPriority);
294 return set_status(pRawComponent, *optComponentStatus);
297 template<std::derived_from<rtti_pure_base> base_component_t>
300 return m_RootClass.priorityCache.empty();
303 template<std::derived_from<rtti_pure_base> base_component_t>
306 m_RootClass.derivedClasses.clear();
307 m_RootClass.components.clear();
308 m_RootClass.priorityCache.clear();
311 template<std::derived_from<rtti_pure_base> base_component_t>
313 const base_component_t* pRawComponent)
const noexcept
318 auto it = std::ranges::find_if(
319 m_RootClass.priorityCache,
320 [pRawComponent](
const auto& pair)
322 return pair.second == pRawComponent;
325 return it != m_RootClass.priorityCache.end() ? std::optional<component_status_key>(it->first) : std::nullopt;
329 template<std::derived_from<rtti_pure_base> base_component_t>
330 bool components<base_component_t>::set_status(
331 const base_component_t* pRawComponent,
332 component_status_key status) noexcept
337 bool bChanged =
true;
340 [pRawComponent, status, &bChanged](class_data& classData)
342 const auto it = std::ranges::find_if(
343 classData.priorityCache,
344 [pRawComponent](
const auto& pair)
346 return pair.second == pRawComponent;
349 if (it == classData.priorityCache.end())
355 if (it->first != status)
357 classData.priorityCache.emplace(status, it->second);
358 classData.priorityCache.erase(it);
365 template<std::derived_from<rtti_pure_base> base_component_t>
367 std::derived_from<base_component_t> component_t,
368 callable_c<void, typename components<base_component_t>::class_data&> callable_t>
369 typename components<base_component_t>::class_data& components<base_component_t>::iterate_class_data(
370 callable_t iterateClassDataFunction) noexcept
372 class_data* pClassData = &m_RootClass;
373 iterateClassDataFunction(*pClassData);
375 tuple_utils::iterate<typename details::get_inheritance_sequence<base_component_t, component_t>::type>(
376 [&pClassData, &iterateClassDataFunction]<
class T, size_t I>()
378 pClassData = &pClassData->get_or_add_class_data(T::get_class_id_static());
379 iterateClassDataFunction(*pClassData);
385 template<std::derived_from<rtti_pure_base> base_component_t>
387 std::derived_from<base_component_t> component_t,
388 callable_c<void, typename components<base_component_t>::class_data&> callable_t>
389 const typename components<base_component_t>::class_data& components<base_component_t>::iterate_class_data(
390 callable_t iterateClassDataFunction)
const noexcept
392 return QX_CONST_CAST_THIS()->template iterate_class_data<component_t>(std::move(iterateClassDataFunction));
395 template<std::derived_from<rtti_pure_base> base_component_t>
396 template<std::derived_from<base_component_t> component_t>
397 typename components<base_component_t>::class_data& components<base_component_t>::get_or_add_class_data() noexcept
399 class_data* pClassData = &m_RootClass;
401 tuple_utils::iterate<typename details::get_inheritance_sequence<base_component_t, component_t>::type>(
402 [&pClassData]<
class T, size_t I>()
404 pClassData = &pClassData->get_or_add_class_data(T::get_class_id_static());
410 template<std::derived_from<rtti_pure_base> base_component_t>
411 template<std::derived_from<base_component_t> component_t>
412 const typename components<base_component_t>::class_data& components<base_component_t>::get_or_add_class_data()
418 template<std::derived_from<rtti_pure_base> base_component_t>
419 template<callable_c<void, typename components<base_component_t>::class_data&> callable_t>
420 typename components<base_component_t>::class_data& components<base_component_t>::iterate_class_data(
421 const base_component_t* pRawComponent,
422 callable_t iterateClassDataFunction) noexcept
424 class_data* pClassData = &m_RootClass;
425 iterateClassDataFunction(*pClassData);
427 std::span<const class_id> allIds = pRawComponent->get_inheritance_sequence();
428 std::span<const class_id> baseClassIds(
429 std::ranges::find(allIds, base_component_t::get_class_id_static()),
432 for (
auto it = baseClassIds.begin() + 1; it != baseClassIds.end(); ++it)
434 pClassData = &pClassData->get_or_add_class_data(*it);
435 iterateClassDataFunction(*pClassData);
441 template<std::derived_from<rtti_pure_base> base_component_t>
442 template<callable_c<void, typename components<base_component_t>::class_data&> callable_t>
443 const typename components<base_component_t>::class_data& components<base_component_t>::iterate_class_data(
444 const base_component_t* pRawComponent,
445 callable_t iterateClassDataFunction)
const noexcept
447 return QX_CONST_CAST_THIS()->iterate_class_data(pRawComponent, std::move(iterateClassDataFunction));
450 template<std::derived_from<rtti_pure_base> base_component_t>
451 typename components<base_component_t>::class_data& components<base_component_t>::get_or_add_class_data(
452 const base_component_t* pRawComponent) noexcept
454 class_data* pClassData = &m_RootClass;
456 std::span<const class_id> allIds = pRawComponent->get_inheritance_sequence();
457 std::span<const class_id> baseClassIds(
458 std::ranges::find(allIds, base_component_t::get_class_id_static()),
461 for (
auto it = baseClassIds.begin() + 1; it != baseClassIds.end(); ++it)
462 pClassData = &pClassData->get_or_add_class_data(*it);
467 template<std::derived_from<rtti_pure_base> base_component_t>
468 const typename components<base_component_t>::class_data& components<base_component_t>::get_or_add_class_data(
469 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.
auto view() noexcept
Get a view which may be used in a ranged-based for loop and consists of components of a given type wi...
bool empty() const noexcept
Check if container doesn't have any components.
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...