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(
 
  198                [bIncludeDisabled](
const auto& pair)
 
  200                    return pair.second->template is_derived_from<component_t>()
 
  201                           && (bIncludeDisabled || !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(
 
  217                [bIncludeDisabled](
const auto& pair)
 
  219                    return pair.second->template is_derived_from<component_t>()
 
  220                           && (bIncludeDisabled || !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.
 
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...