Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
query.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <helios/assert.hpp>
8#include <helios/ecs/query/details/query_args.hpp>
9#include <helios/ecs/query/details/traits.hpp>
13
14#include <algorithm>
15#include <cstddef>
16#include <functional>
17#include <memory>
18#include <memory_resource>
19#include <optional>
20#include <span>
21#include <tuple>
22#include <type_traits>
23#include <unordered_map>
24#include <utility>
25#include <vector>
26
27namespace helios::ecs {
28
29class World;
30
31template <typename WorldT, typename Allocator, QueryArg... Args>
32class BasicQuery;
33
34template <typename WorldT, typename Allocator, QueryArg... Args>
36
37namespace details {
38
39template <typename... Cs>
40[[nodiscard]] inline bool EntityHasComponentsCheck(
41 const ComponentManager& manager, Entity entity,
42 std::tuple<Cs...>* /*components*/) {
43 return ((manager.template Has<std::remove_cvref_t<Cs>>(entity)) && ...);
44}
45
46template <typename... Cs>
47[[nodiscard]] inline auto FetchComponentsMutable(
48 const Archetype& archetype, Entity entity, ComponentManager& manager,
49 std::tuple<Cs...>* /*components*/)
50 -> std::tuple<ComponentAccessType_t<Cs>...> {
51 return std::tuple<ComponentAccessType_t<Cs>...>(
52 FetchComponent<Cs>(archetype, entity, manager)...);
53}
54
55template <typename... Cs>
56[[nodiscard]] inline auto FetchComponentsConst(
57 const Archetype& archetype, Entity entity, const ComponentManager& manager,
58 std::tuple<Cs...>* /*components*/)
59 -> std::tuple<ComponentAccessType_t<Cs>...> {
60 return std::tuple<ComponentAccessType_t<Cs>...>(
61 FetchComponentConst<Cs>(archetype, entity, manager)...);
62}
63
64} // namespace details
65
66/**
67 * @brief Wrapper that provides entity-aware iteration over query results.
68 * @details Each dereferenced value is a tuple starting with the `Entity`,
69 * followed by the requested component access values.
70 *
71 * This wrapper is lightweight and holds a reference to the underlying
72 * `BasicQuery`. It must not outlive the query it wraps.
73 *
74 * @note Not thread-safe.
75 * @tparam WorldT World type (World or const World)
76 * @tparam Allocator Allocator type for internal storage
77 * @tparam Args Component access types and optional With/Without filters
78 */
79template <typename WorldT, typename Allocator, QueryArg... Args>
81private:
82 using Split = details::QueryArgSplit<Args...>;
83 using TypeInfo = details::QueryTypeInfo<WorldT, typename Split::Components>;
84 static constexpr bool kIsConst = TypeInfo::kIsConst;
85
86public:
87 using iterator = typename TypeInfo::template WithEntityIterator<kIsConst>;
88 using const_iterator = typename TypeInfo::template WithEntityIterator<true>;
89 using value_type = std::iter_value_t<iterator>;
90 using difference_type = std::iter_difference_t<iterator>;
91 using pointer = typename iterator::pointer;
92 using reference = std::iter_reference_t<iterator>;
93 using allocator_type = Allocator;
94
95 /**
96 * @brief Constructs entity-aware query wrapper.
97 * @param query Reference to the underlying query
98 */
101 : query_(query) {}
102
105 ~BasicQueryWithEntity() noexcept = default;
106
107 BasicQueryWithEntity& operator=(const BasicQueryWithEntity&) = delete;
109
110 /**
111 * @brief Gets all query components for a specific entity (ignores query
112 * filters).
113 * @param entity The entity to get components for
114 * @return Tuple of component access types for the entity
115 */
116 [[nodiscard]] auto Get(Entity entity) const -> value_type {
117 return query_.Get(entity);
118 }
119
120 /**
121 * @brief Tries to get all query components for a specific entity (ignores
122 * query filters).
123 * @param entity The entity to get components for
124 * @return Optional tuple of component access types for the entity
125 */
126 [[nodiscard]] auto TryGet(Entity entity) const -> std::optional<value_type> {
127 return query_.TryGet(entity);
128 }
129
130 /**
131 * @brief Tries to get all query components for a specific entity while
132 * respecting query filters.
133 * @param entity The entity to get components for
134 * @return Optional tuple of component access types for the entity
135 */
136 [[nodiscard]] auto TryGetFiltered(Entity entity) const
137 -> std::optional<value_type> {
138 return query_.TryGetFiltered(entity);
139 }
140
141 /**
142 * @brief Collects all results into a vector.
143 * @return Vector of tuples containing entity and components
144 */
145 [[nodiscard]] auto Collect() const -> std::vector<
146 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>;
147
148 /**
149 * @brief Collects all results into a vector using a custom allocator.
150 * @tparam ResultAlloc STL-compatible allocator type for `value_type`
151 * @param alloc Allocator instance to use
152 * @return Vector of results using the provided allocator
153 */
154 template <typename ResultAlloc>
155 requires std::same_as<typename ResultAlloc::value_type,
156 typename BasicQueryWithEntity<WorldT, Allocator,
157 Args...>::value_type> &&
158 (!std::derived_from<std::remove_pointer_t<ResultAlloc>,
159 std::pmr::memory_resource>)
160 [[nodiscard]] auto CollectWith(ResultAlloc alloc) const
161 -> std::vector<value_type, ResultAlloc>;
162
163 /**
164 * @brief Collects all results using a memory resource.
165 * @param resource Memory resource
166 * @return Vector of results using provided allocator
167 */
168 [[nodiscard]] auto CollectWith(std::pmr::memory_resource* resource) const
169 -> std::pmr::vector<typename BasicQueryWithEntity<WorldT, Allocator,
170 Args...>::value_type>;
171
172 auto CollectWith(std::nullptr_t) const -> std::pmr::vector<
173 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type> =
174 delete;
175
176 /**
177 * @brief Collects all matching entities into a vector.
178 * @return Vector of `Entity` objects
179 */
180 [[nodiscard]] auto CollectEntities() const -> std::vector<Entity>;
181
182 /**
183 * @brief Collects all matching entities using a custom allocator.
184 * @tparam ResultAlloc STL-compatible allocator type for `Entity`
185 * @param alloc Allocator instance
186 * @return Vector of entities using the provided allocator
187 */
188 template <typename ResultAlloc>
189 requires std::same_as<typename ResultAlloc::value_type, Entity> &&
190 (!std::derived_from<std::remove_pointer_t<ResultAlloc>,
191 std::pmr::memory_resource>)
192 [[nodiscard]] auto CollectEntitiesWith(ResultAlloc alloc) const
193 -> std::vector<Entity, ResultAlloc>;
194
195 /**
196 * @brief Collects all matching entities using a memory resource.
197 * @param resource Memory resource
198 * @return Vector of results using provided allocator
199 */
200 [[nodiscard]] auto CollectEntitiesWith(
201 std::pmr::memory_resource* resource) const -> std::pmr::vector<Entity>;
202
203 auto CollectEntitiesWith(std::nullptr_t) const
204 -> std::pmr::vector<Entity> = delete;
205
206 /**
207 * @brief Writes all query results into an output iterator.
208 * @tparam OutIt Output iterator type
209 * @param out Output iterator
210 */
211 template <typename OutIt>
212 requires std::output_iterator<
213 OutIt,
214 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
215 void Into(OutIt out);
216
217 /**
218 * @brief Executes an action for each matching entity and components.
219 * @tparam Action Function type `(Entity, Components...) -> void`
220 * @param action Function to execute for each result
221 */
222 template <typename Action>
223 requires utils::ActionFor<
224 Action,
225 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
226 void ForEach(const Action& action) const;
227
228 /**
229 * @brief Filters entities based on a predicate.
230 * @tparam Pred Predicate function type
231 * @param predicate Function to test each result
232 * @return Lazy filter view
233 */
234 template <typename Pred>
235 requires utils::PredicateFor<
236 Pred,
237 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
238 [[nodiscard]] auto Filter(Pred predicate) const -> utils::FilterAdapter<
239 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
240 Pred>;
241
242 /**
243 * @brief Transforms each element using a mapping function.
244 * @tparam Func Transformation function type
245 * @param transform Function to transform each result
246 * @return Lazy map view
247 */
248 template <typename Func>
249 requires utils::TransformFor<
250 Func,
251 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
252 [[nodiscard]] auto Map(Func transform) const -> utils::MapAdapter<
253 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
254 Func>;
255
256 /**
257 * @brief Takes only the first N elements.
258 * @param count Maximum number of elements to take
259 * @return Lazy take view
260 */
261 [[nodiscard]] auto Take(size_t count) const -> utils::TakeAdapter<
262 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator>;
263
264 /**
265 * @brief Skips the first N elements.
266 * @param count Number of elements to skip
267 * @return Lazy skip view
268 */
269 [[nodiscard]] auto Skip(size_t count) const -> utils::SkipAdapter<
270 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator>;
271
272 /**
273 * @brief Takes elements while a predicate is true.
274 * @tparam Pred Predicate function type
275 * @param predicate Function to test each result
276 * @return Lazy take-while view
277 */
278 template <typename Pred>
279 requires utils::PredicateFor<
280 Pred,
281 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
282 [[nodiscard]] auto TakeWhile(Pred predicate) const -> utils::TakeWhileAdapter<
283 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
284 Pred>;
285
286 /**
287 * @brief Skips elements while a predicate is true.
288 * @tparam Pred Predicate function type
289 * @param predicate Function to test each result
290 * @return Lazy skip-while view
291 */
292 template <typename Pred>
293 requires utils::PredicateFor<
294 Pred,
295 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
296 [[nodiscard]] auto SkipWhile(Pred predicate) const -> utils::SkipWhileAdapter<
297 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
298 Pred>;
299
300 /**
301 * @brief Adds an index to each element.
302 * @return Lazy enumerate view yielding (index, entity, components...) tuples
303 */
304 [[nodiscard]] auto Enumerate() const -> utils::EnumerateAdapter<
305 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator>;
306
307 /**
308 * @brief Inspects each element without consuming it.
309 * @tparam Func Inspection function type
310 * @param inspector Function to call on each result
311 * @return Lazy inspect view
312 */
313 template <typename Func>
314 requires utils::InspectorFor<
315 Func,
316 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
317 [[nodiscard]] auto Inspect(Func inspector) const -> utils::InspectAdapter<
318 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
319 Func>;
320
321 /**
322 * @brief Yields every Nth element.
323 * @param step Interval between yielded elements (must be > 0)
324 * @return Lazy step-by view
325 */
326 [[nodiscard]] auto StepBy(size_t step) const -> utils::StepByAdapter<
327 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator>;
328
329 /**
330 * @brief Chains this query with another iterator range.
331 * @tparam OtherIter Iterator type of the second range
332 * @param other_begin Begin iterator of the second range
333 * @param other_end End iterator of the second range
334 * @return Lazy chain view
335 */
336 template <typename OtherIter>
337 requires utils::ChainAdapterRequirements<iterator, OtherIter>
338 [[nodiscard]] auto Chain(OtherIter other_begin, OtherIter other_end) const
339 -> utils::ChainAdapter<iterator, OtherIter> {
340 return {begin(), end(), std::move(other_begin), std::move(other_end)};
341 }
342
343 /**
344 * @brief Chains this query with another query of the same type.
345 * @param other Other query to chain after this one
346 * @return Lazy chain view
347 */
348 [[nodiscard]] auto Chain(const BasicQueryWithEntity& other) const
350 return {begin(), end(), other.begin(), other.end()};
351 }
352
353 /**
354 * @brief Chains this query with another range.
355 * @tparam R Range type
356 * @param range Range to chain after this query
357 * @return Lazy chain view
358 */
359 template <std::ranges::input_range R>
361 std::ranges::iterator_t<R>>
362 [[nodiscard]] auto Chain(R& range) const
364 return {begin(), end(), std::ranges::begin(range), std::ranges::end(range)};
365 }
366
367 /**
368 * @brief Chains this query with another const range.
369 * @tparam R Range type
370 * @param range Range to chain after this query
371 * @return Lazy chain view
372 */
373 template <std::ranges::input_range R>
375 std::ranges::iterator_t<const R>>
376 [[nodiscard]] auto Chain(const R& range) const
378 return {begin(), end(), std::ranges::cbegin(range),
379 std::ranges::cend(range)};
380 }
381
382 /**
383 * @brief Reverses the order of iteration.
384 * @return Lazy reverse view
385 */
386 [[nodiscard]] auto Reverse() const -> utils::ReverseAdapter<iterator> {
387 return {begin(), end()};
388 }
389
390 /**
391 * @brief Creates sliding windows over query results.
392 * @param window_size Size of the sliding window
393 * @return Lazy slide view
394 * @warning window_size must be greater than 0
395 */
396 [[nodiscard]] auto Slide(size_t window_size) const
398 return {begin(), end(), window_size};
399 }
400
401 /**
402 * @brief Takes every Nth element with stride.
403 * @param stride Number of elements to skip between yields
404 * @return Lazy stride view
405 * @warning stride must be greater than 0
406 */
407 [[nodiscard]] auto Stride(size_t stride) const
409 return {begin(), end(), stride};
410 }
411
412 /**
413 * @brief Zips this query with another iterator range.
414 * @tparam OtherIter Iterator type to zip with
415 * @param other_begin Begin of other range
416 * @param other_end End of other range
417 * @return Lazy zip view
418 */
419 template <typename OtherIter>
421 [[nodiscard]] auto Zip(OtherIter other_begin, OtherIter other_end) const
423 return {begin(), end(), std::move(other_begin), std::move(other_end)};
424 }
425
426 /**
427 * @brief Zips this query with another query of the same type.
428 * @param other Query to zip with
429 * @return Lazy zip view
430 */
431 [[nodiscard]] auto Zip(const BasicQueryWithEntity& other) const
433 return {begin(), end(), other.begin(), other.end()};
434 }
435
436 /**
437 * @brief Zips this query with another range.
438 * @tparam R Range type
439 * @param range Range to zip with
440 * @return Lazy zip view
441 */
442 template <std::ranges::input_range R>
444 [[nodiscard]] auto Zip(R& range) const
446 return {begin(), end(), std::ranges::begin(range), std::ranges::end(range)};
447 }
448
449 /**
450 * @brief Zips this query with another const range.
451 * @tparam R Range type
452 * @param range Range to zip with
453 * @return Lazy zip view
454 */
455 template <std::ranges::input_range R>
457 std::ranges::iterator_t<const R>>
458 [[nodiscard]] auto Zip(const R& range) const
460 return {begin(), end(), std::ranges::cbegin(range),
461 std::ranges::cend(range)};
462 }
463
464 /**
465 * @brief Folds query results into a single value.
466 * @tparam T Accumulator type
467 * @tparam Func Folder function type
468 * @param init Initial accumulator value
469 * @param folder Function combining accumulator with each result
470 * @return Final accumulated value
471 */
472 template <typename T, typename Func>
473 requires utils::FolderFor<
474 Func, T,
475 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
476 [[nodiscard]] T Fold(T init, const Func& folder) const;
477
478 /**
479 * @brief Finds the first result matching a predicate.
480 * @tparam Pred Predicate type
481 * @param predicate Function to test each result
482 * @return First matching result, or `std::nullopt` if none found
483 */
484 template <typename Pred>
485 requires utils::PredicateFor<
486 Pred,
487 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
488 [[nodiscard]] auto Find(const Pred& predicate) const -> std::optional<
489 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>;
490
491 /**
492 * @brief Counts entities matching a predicate.
493 * @tparam Pred Predicate type
494 * @param predicate Function to test each result
495 * @return Number of matching entities
496 */
497 template <typename Pred>
498 requires utils::PredicateFor<
499 Pred,
500 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
501 [[nodiscard]] size_t CountIf(const Pred& predicate) const;
502
503 /**
504 * @brief Finds the element with the maximum key value.
505 * @tparam KeyFunc Key extraction function type
506 * @param key_func Function to extract comparison key
507 * @return Element with maximum key, or `std::nullopt` if empty
508 */
509 template <typename KeyFunc>
510 requires utils::TransformFor<
511 KeyFunc,
512 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
513 [[nodiscard]] auto MaxBy(const KeyFunc& key_func) const -> std::optional<
514 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>;
515
516 /**
517 * @brief Finds the element with the minimum key value.
518 * @tparam KeyFunc Key extraction function type
519 * @param key_func Function to extract comparison key
520 * @return Element with minimum key, or `std::nullopt` if empty
521 */
522 template <typename KeyFunc>
523 requires utils::TransformFor<
524 KeyFunc,
525 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
526 [[nodiscard]] auto MinBy(const KeyFunc& key_func) const -> std::optional<
527 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>;
528
529 /**
530 * @brief Partitions results into two groups based on a predicate.
531 * @tparam Pred Predicate type
532 * @param predicate Function to test each result
533 * @return Pair of vectors: (matching results, non-matching results)
534 */
535 template <typename Pred>
536 requires utils::PredicateFor<
537 Pred,
538 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
539 [[nodiscard]] auto Partition(const Pred& predicate) const
540 -> std::pair<std::vector<typename BasicQueryWithEntity<
541 WorldT, Allocator, Args...>::value_type>,
542 std::vector<typename BasicQueryWithEntity<
543 WorldT, Allocator, Args...>::value_type>>;
544
545 /**
546 * @brief Groups results by an extracted key.
547 * @tparam KeyExtractor Function type returning a hashable key
548 * @param key_extractor Function that extracts the grouping key
549 * @return Map from keys to vectors of results
550 */
551 template <typename KeyExtractor>
552 requires utils::TransformFor<
553 KeyExtractor,
554 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
555 [[nodiscard]] auto
556 GroupBy(const KeyExtractor& key_extractor) const -> std::unordered_map<
558 const KeyExtractor&, typename BasicQueryWithEntity<
559 WorldT, Allocator, Args...>::value_type>>,
560 std::vector<typename BasicQueryWithEntity<WorldT, Allocator,
561 Args...>::value_type>>;
562
563 /**
564 * @brief Checks if any entity matches the predicate.
565 * @tparam Pred Predicate type
566 * @param predicate Function to test each result
567 * @return True if at least one result matches
568 */
569 template <typename Pred>
570 requires utils::PredicateFor<
571 Pred,
572 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
573 [[nodiscard]] bool Any(const Pred& predicate) const;
574
575 /**
576 * @brief Checks if all entities match the predicate.
577 * @tparam Pred Predicate type
578 * @param predicate Function to test each result
579 * @return True if all results match
580 */
581 template <typename Pred>
582 requires utils::PredicateFor<
583 Pred,
584 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
585 [[nodiscard]] bool All(const Pred& predicate) const;
586
587 /**
588 * @brief Checks if no entities match the predicate.
589 * @tparam Pred Predicate type
590 * @param predicate Function to test each result
591 * @return True if no results match
592 */
593 template <typename Pred>
595 [[nodiscard]] bool None(const Pred& predicate) const {
596 return !Any(predicate);
597 }
598
599 /**
600 * @brief Checks if query matches no entities.
601 * @return True if no entities match
602 */
603 [[nodiscard]] bool Empty() const noexcept { return query_.Empty(); }
604
605 /**
606 * @brief Gets the number of matching entities.
607 * @return Total count of entities matching the query
608 */
609 [[nodiscard]] size_t Count() const noexcept { return query_.Count(); }
610
611 /**
612 * @brief Gets iterator to first matching entity and components.
613 * @return Iterator to the beginning of the query results
614 */
615 [[nodiscard]] iterator begin() const;
616
617 /**
618 * @brief Gets iterator past the last matching entity and components.
619 * @return Iterator to the end of the query results
620 */
621 [[nodiscard]] iterator end() const noexcept;
622
623private:
624 BasicQuery<WorldT, Allocator, Args...>& query_;
625};
626
627/**
628 * @brief Query result object for iterating over matching entities and
629 * components.
630 * @details `BasicQuery` provides iteration and functional operations over
631 * entities matching specified component criteria. Supports const-qualified
632 * component access for read-only operations, optional components via pointer
633 * types, value copy, mutable reference, const reference, and rvalue reference
634 * (move) access patterns.
635 *
636 * @note Not thread-safe.
637 * @tparam WorldT World type (World or const World)
638 * @tparam Allocator Allocator type for internal storage
639 * @tparam Args Component access types and optional With/Without filters
640 *
641 * @code
642 * auto query = world.Query<Transform&, const Velocity&, const Gravity*,
643 * Health, With<Player>, Without<Dead>>();
644 *
645 * for (auto&& [transform, velocity, gravity, health] : query) {
646 * transform.position += velocity.direction * velocity.speed;
647 * if (gravity) {
648 * transform.position.y += gravity->force;
649 * }
650 * }
651 *
652 * query.ForEach([](Transform& transform, const Velocity& velocity,
653 * const Gravity* gravity, Health health) {
654 * // ...
655 * });
656 * @endcode
657 */
658template <typename WorldT, typename Allocator, QueryArg... Args>
660private:
661 using Split = details::QueryArgSplit<Args...>;
662 using TypeInfo = details::QueryTypeInfo<WorldT, typename Split::Components>;
663 static constexpr bool kIsConst = TypeInfo::kIsConst;
664
665 static constexpr auto kWithIndices = Split::kWithIndices;
666 static constexpr auto kWithoutIndices = Split::kWithoutIndices;
667
668public:
669 using ComponentManagerType = typename TypeInfo::ComponentManagerType;
671 typename TypeInfo::template WithEntityIterator<kIsConst>;
672
673 using iterator = typename TypeInfo::template Iterator<kIsConst>;
674 using const_iterator = typename TypeInfo::template Iterator<true>;
675 using value_type = typename TypeInfo::ValueType;
676 using difference_type = std::iter_difference_t<iterator>;
677 using pointer = typename iterator::pointer;
678 using reference = std::iter_reference_t<iterator>;
679 using allocator_type = Allocator;
680
681 /**
682 * @brief Constructs query with the given component manager and allocator.
683 * @details The With/Without component filters are derived at compile time
684 * from the template arguments (via With<> and Without<> filter types).
685 * @param components Component manager reference
686 * @param alloc Allocator instance
687 */
688 explicit BasicQuery(ComponentManagerType& components, Allocator alloc = {});
689
690 /**
691 * @brief Constructs query from a PMR memory resource.
692 * @details Enabled only when `allocator_type` is constructible from
693 * `std::pmr::memory_resource*`.
694 * @param components Component manager reference
695 * @param resource Memory resource used to construct allocator
696 */
698 std::pmr::memory_resource* resource)
699 requires std::constructible_from<Allocator, std::pmr::memory_resource*>
700 : BasicQuery(components, Allocator{resource}) {}
701
702 BasicQuery(ComponentManagerType&, std::nullptr_t) = delete;
703
704 BasicQuery(const BasicQuery&) = delete;
705 BasicQuery(BasicQuery&&) noexcept = default;
706 ~BasicQuery() = default;
707
708 BasicQuery& operator=(const BasicQuery&) = delete;
709 BasicQuery& operator=(BasicQuery&&) noexcept = default;
710
711 /**
712 * @brief Creates wrapper for entity-aware iteration.
713 * @note Only callable on lvalue queries to prevent dangling references.
714 * @return BasicQueryWithEntity wrapper for this query
715 */
716 [[nodiscard]] auto WithEntity() & noexcept
717 -> BasicQueryWithEntity<WorldT, Allocator, Args...> {
718 return BasicQueryWithEntity<WorldT, Allocator, Args...>(*this);
719 }
720
721 /**
722 * @brief Gets all query components for a specific entity (ignores query
723 * filters).
724 * @param entity The entity to get components for
725 * @return Tuple of component access types for the entity
726 */
727 [[nodiscard]] auto Get(Entity entity) const ->
728 typename BasicQuery<WorldT, Allocator, Args...>::value_type;
729
730 /**
731 * @brief Tries to get all query components for a specific entity (ignores
732 * query filters).
733 * @param entity The entity to get components for
734 * @return Optional tuple of component access types for the entity
735 */
736 [[nodiscard]] auto TryGet(Entity entity) const -> std::optional<
737 typename BasicQuery<WorldT, Allocator, Args...>::value_type>;
738
739 /**
740 * @brief Tries to get all query components for a specific entity while
741 * respecting query filters.
742 * @param entity The entity to get components for
743 * @return Optional tuple of component access types for the entity
744 */
745 [[nodiscard]] auto TryGetFiltered(Entity entity) const -> std::optional<
746 typename BasicQuery<WorldT, Allocator, Args...>::value_type>;
747
748 /**
749 * @brief Collects all results into a vector.
750 * @return Vector of tuples containing components
751 */
752 [[nodiscard]] auto Collect() const -> std::vector<
753 typename BasicQuery<WorldT, Allocator, Args...>::value_type>;
754
755 /**
756 * @brief Collects all results using a custom allocator.
757 * @tparam ResultAlloc STL-compatible allocator type for `value_type`
758 * @param alloc Allocator instance
759 * @return Vector of results using provided allocator
760 */
761 template <typename ResultAlloc>
762 requires std::same_as<
763 typename ResultAlloc::value_type,
764 typename BasicQuery<WorldT, Allocator, Args...>::value_type> &&
765 (!std::derived_from<std::remove_pointer_t<ResultAlloc>,
766 std::pmr::memory_resource>)
767 [[nodiscard]] auto CollectWith(ResultAlloc alloc) const -> std::vector<
768 typename BasicQuery<WorldT, Allocator, Args...>::value_type, ResultAlloc>;
769
770 /**
771 * @brief Collects all results using a memory resource.
772 * @param resource Memory resource
773 * @return Vector of results using provided allocator
774 */
775 [[nodiscard]] auto CollectWith(std::pmr::memory_resource* resource) const
776 -> std::pmr::vector<
777 typename BasicQuery<WorldT, Allocator, Args...>::value_type>;
778
779 auto CollectWith(std::nullptr_t) const -> std::pmr::vector<
780 typename BasicQuery<WorldT, Allocator, Args...>::value_type> = delete;
781
782 /**
783 * @brief Writes all query results into an output iterator.
784 * @tparam OutIt Output iterator type
785 * @param out Output iterator
786 */
787 template <typename OutIt>
788 requires std::output_iterator<
789 OutIt, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
790 void Into(OutIt out) const;
791
792 /**
793 * @brief Executes an action for each matching entity's components.
794 * @tparam Action Function type `(Components...) -> void`
795 * @param action Function to execute for each result
796 */
797 template <typename Action>
798 requires utils::ActionFor<
799 Action, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
800 void ForEach(const Action& action) const;
801
802 /**
803 * @brief Executes an action for each entity and its components.
804 * @tparam Action Function type `(Entity, Components...) -> void`
805 * @param action Function to execute for each result
806 */
807 template <typename Action>
808 requires utils::ActionFor<
809 Action,
810 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
811 void ForEachWithEntity(const Action& action) const;
812
813 /**
814 * @brief Filters query results based on a predicate.
815 * @tparam Pred Predicate function type `(Components...) -> bool`
816 * @param predicate Function to test each result
817 * @return Lazy filter view
818 */
819 template <typename Pred>
820 requires utils::PredicateFor<
821 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
822 [[nodiscard]] auto Filter(Pred predicate) const& -> utils::FilterAdapter<
823 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Pred>;
824
825 /**
826 * @brief Transforms each element using a mapping function.
827 * @tparam Func Transformation function type `(Components...) -> U`
828 * @param transform Function to transform each result
829 * @return Lazy map view
830 */
831 template <typename Func>
832 requires utils::TransformFor<
833 Func, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
834 [[nodiscard]] auto Map(Func transform) const& -> utils::MapAdapter<
835 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Func>;
836
837 /**
838 * @brief Takes only the first N elements.
839 * @param count Maximum number of elements to take
840 * @return Lazy take view
841 */
842 [[nodiscard]] auto Take(size_t count) const& -> utils::TakeAdapter<
843 typename BasicQuery<WorldT, Allocator, Args...>::iterator>;
844
845 /**
846 * @brief Skips the first N elements.
847 * @param count Number of elements to skip
848 * @return Lazy skip view
849 */
850 [[nodiscard]] auto Skip(size_t count) const& -> utils::SkipAdapter<
851 typename BasicQuery<WorldT, Allocator, Args...>::iterator>;
852
853 /**
854 * @brief Takes elements while a predicate is true.
855 * @tparam Pred Predicate function type
856 * @param predicate Function to test each result
857 * @return Lazy take-while view
858 */
859 template <typename Pred>
860 requires utils::PredicateFor<
861 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
862 [[nodiscard]] auto TakeWhile(Pred predicate)
863 const& -> utils::TakeWhileAdapter<
864 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Pred>;
865
866 /**
867 * @brief Skips elements while a predicate is true.
868 * @tparam Pred Predicate function type
869 * @param predicate Function to test each result
870 * @return Lazy skip-while view
871 */
872 template <typename Pred>
873 requires utils::PredicateFor<
874 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
875 [[nodiscard]] auto SkipWhile(Pred predicate)
876 const& -> utils::SkipWhileAdapter<
877 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Pred>;
878
879 /**
880 * @brief Adds an index to each element.
881 * @return Lazy enumerate view
882 */
883 [[nodiscard]] auto Enumerate() const& -> utils::EnumerateAdapter<
884 typename BasicQuery<WorldT, Allocator, Args...>::iterator>;
885
886 /**
887 * @brief Inspects each element without consuming it.
888 * @tparam Func Inspection function type
889 * @param inspector Function to call on each result
890 * @return Lazy inspect view
891 */
892 template <typename Func>
893 requires utils::InspectorFor<
894 Func, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
895 [[nodiscard]] auto Inspect(Func inspector) const& -> utils::InspectAdapter<
896 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Func>;
897
898 /**
899 * @brief Yields every Nth element.
900 * @param step Interval between yielded elements (must be > 0)
901 * @return Lazy step-by view
902 */
903 [[nodiscard]] auto StepBy(size_t step) const& -> utils::StepByAdapter<
904 typename BasicQuery<WorldT, Allocator, Args...>::iterator>;
905
906 /**
907 * @brief Chains this query with another iterator range.
908 * @tparam OtherIter Iterator type of the second range
909 * @param other_begin Begin iterator of the second range
910 * @param other_end End iterator of the second range
911 * @return Lazy chain view
912 */
913 template <typename OtherIter>
914 requires utils::ChainAdapterRequirements<iterator, OtherIter>
915 [[nodiscard]] auto Chain(OtherIter other_begin, OtherIter other_end)
916 const& -> utils::ChainAdapter<iterator, OtherIter> {
917 return {begin(), end(), std::move(other_begin), std::move(other_end)};
918 }
919
920 /**
921 * @brief Chains this query with another query of the same type.
922 * @param other Other query to chain after this one
923 * @return Lazy chain view
924 */
925 [[nodiscard]] auto Chain(const BasicQuery& other)
927 return {begin(), end(), other.begin(), other.end()};
928 }
929
930 /**
931 * @brief Chains this query with another range.
932 * @tparam R Range type
933 * @param range Range to chain after this query
934 * @return Lazy chain view
935 */
936 template <std::ranges::input_range R>
938 std::ranges::iterator_t<R>>
939 [[nodiscard]] auto Chain(R& range)
941 return {begin(), end(), std::ranges::begin(range), std::ranges::end(range)};
942 }
943
944 /**
945 * @brief Chains this query with another const range.
946 * @tparam R Range type
947 * @param range Range to chain after this query
948 * @return Lazy chain view
949 */
950 template <std::ranges::input_range R>
952 std::ranges::iterator_t<const R>>
953 [[nodiscard]] auto Chain(const R& range) const& -> utils::ChainAdapter<
954 iterator, std::ranges::iterator_t<const R>> {
955 return {begin(), end(), std::ranges::cbegin(range),
956 std::ranges::cend(range)};
957 }
958
959 /**
960 * @brief Reverses the order of iteration.
961 * @return Lazy reverse view
962 */
963 [[nodiscard]] auto Reverse() const& -> utils::ReverseAdapter<iterator> {
964 return {begin(), end()};
965 }
966
967 /**
968 * @brief Creates sliding windows over query results.
969 * @param window_size Size of the sliding window
970 * @return Lazy slide view
971 * @warning window_size must be greater than 0
972 */
973 [[nodiscard]] auto Slide(
974 size_t window_size) const& -> utils::SlideAdapter<iterator> {
975 return {begin(), end(), window_size};
976 }
977
978 /**
979 * @brief Takes every Nth element with stride.
980 * @param stride Number of elements to skip between yields
981 * @return Lazy stride view
982 * @warning stride must be greater than 0
983 */
984 [[nodiscard]] auto Stride(
985 size_t stride) const& -> utils::StrideAdapter<iterator> {
986 return {begin(), end(), stride};
987 }
988
989 /**
990 * @brief Zips this query with another iterator range.
991 * @tparam OtherIter Iterator type to zip with
992 * @param other_begin Begin of other range
993 * @param other_end End of other range
994 * @return Lazy zip view
995 */
996 template <typename OtherIter>
998 [[nodiscard]] auto Zip(OtherIter other_begin, OtherIter other_end)
1000 return {begin(), end(), std::move(other_begin), std::move(other_end)};
1001 }
1002
1003 /**
1004 * @brief Zips this query with another query of the same type.
1005 * @param other Query to zip with
1006 * @return Lazy zip view
1007 */
1008 [[nodiscard]] auto Zip(
1009 const BasicQuery& other) const& -> utils::ZipAdapter<iterator, iterator> {
1010 return {begin(), end(), other.begin(), other.end()};
1011 }
1012
1013 /**
1014 * @brief Zips this query with another range.
1015 * @tparam R Range type
1016 * @param range Range to zip with
1017 * @return Lazy zip view
1018 */
1019 template <std::ranges::input_range R>
1021 [[nodiscard]] auto Zip(R& range)
1023 return {begin(), end(), std::ranges::begin(range), std::ranges::end(range)};
1024 }
1025
1026 /**
1027 * @brief Zips this query with another const range.
1028 * @tparam R Range type
1029 * @param range Range to zip with
1030 * @return Lazy zip view
1031 */
1032 template <std::ranges::input_range R>
1034 std::ranges::iterator_t<const R>>
1035 [[nodiscard]] auto Zip(const R& range)
1037 return {begin(), end(), std::ranges::cbegin(range),
1038 std::ranges::cend(range)};
1039 }
1040
1041 /**
1042 * @brief Folds query results into a single value.
1043 * @tparam T Accumulator type
1044 * @tparam Func Folder function type `(T, Components...) -> T`
1045 * @param init Initial accumulator value
1046 * @param folder Function combining accumulator with each result
1047 * @return Final accumulated value
1048 */
1049 template <typename T, typename Func>
1050 requires utils::FolderFor<
1051 Func, T, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1052 [[nodiscard]] T Fold(T init, const Func& folder) const;
1053
1054 /**
1055 * @brief Finds the first element matching a predicate.
1056 * @tparam Pred Predicate function type
1057 * @param predicate Function to test each result
1058 * @return First matching element, or `std::nullopt` if none found
1059 */
1060 template <typename Pred>
1062 [[nodiscard]] auto Find(const Pred& predicate) const
1063 -> std::optional<value_type> {
1064 return begin().Find(predicate);
1065 }
1066
1067 /**
1068 * @brief Counts elements matching a predicate.
1069 * @tparam Pred Predicate function type
1070 * @param predicate Function to test each result
1071 * @return Number of matching elements
1072 */
1073 template <typename Pred>
1074 requires utils::PredicateFor<
1075 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1076 [[nodiscard]] size_t CountIf(const Pred& predicate) const;
1077
1078 /**
1079 * @brief Partitions elements into two groups based on a predicate.
1080 * @tparam Pred Predicate function type
1081 * @param predicate Function to test each result
1082 * @return Pair of vectors: (matching, non-matching)
1083 */
1084 template <typename Pred>
1086 [[nodiscard]] auto Partition(const Pred& predicate) const
1087 -> std::pair<std::vector<value_type>, std::vector<value_type>> {
1088 return begin().Partition(predicate);
1089 }
1090
1091 /**
1092 * @brief Finds the element with the maximum key value.
1093 * @tparam KeyFunc Key extraction function type
1094 * @param key_func Function to extract comparison key
1095 * @return Element with maximum key, or `std::nullopt` if empty
1096 */
1097 template <typename KeyFunc>
1099 [[nodiscard]] auto MaxBy(const KeyFunc& key_func) const
1100 -> std::optional<value_type> {
1101 return begin().MaxBy(key_func);
1102 }
1103
1104 /**
1105 * @brief Finds the element with the minimum key value.
1106 * @tparam KeyFunc Key extraction function type
1107 * @param key_func Function to extract comparison key
1108 * @return Element with minimum key, or `std::nullopt` if empty
1109 */
1110 template <typename KeyFunc>
1112 [[nodiscard]] auto MinBy(const KeyFunc& key_func) const
1113 -> std::optional<value_type> {
1114 return begin().MinBy(key_func);
1115 }
1116
1117 /**
1118 * @brief Groups elements by a key extracted from each result.
1119 * @tparam KeyExtractor Key extraction function type
1120 * @param key_extractor Function that extracts the grouping key
1121 * @return Map from keys to vectors of matching elements
1122 */
1123 template <typename KeyExtractor>
1124 requires utils::TransformFor<
1125 KeyExtractor,
1126 typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1127 [[nodiscard]] auto
1128 GroupBy(const KeyExtractor& key_extractor) const -> std::unordered_map<
1130 const KeyExtractor&,
1131 typename BasicQuery<WorldT, Allocator, Args...>::value_type>>,
1132 std::vector<typename BasicQuery<WorldT, Allocator, Args...>::value_type>>;
1133
1134 /**
1135 * @brief Checks if any element matches the predicate.
1136 * @tparam Pred Predicate function type
1137 * @param predicate Function to test each result
1138 * @return True if at least one result matches
1139 */
1140 template <typename Pred>
1142 [[nodiscard]] bool Any(const Pred& predicate) const {
1143 return Find(predicate).has_value();
1144 }
1145
1146 /**
1147 * @brief Checks if all elements match the predicate.
1148 * @tparam Pred Predicate function type
1149 * @param predicate Function to test each result
1150 * @return True if all results match
1151 */
1152 template <typename Pred>
1153 requires utils::PredicateFor<
1154 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1155 [[nodiscard]] bool All(const Pred& predicate) const;
1156
1157 /**
1158 * @brief Checks if no elements match the predicate.
1159 * @tparam Pred Predicate function type
1160 * @param predicate Function to test each result
1161 * @return True if no results match
1162 */
1163 template <typename Pred>
1165 [[nodiscard]] bool None(const Pred& predicate) const {
1166 return !Any(predicate);
1167 }
1168
1169 /**
1170 * @brief Checks if query matches no entities.
1171 * @return True if no entities match
1172 */
1173 [[nodiscard]] bool Empty() const noexcept;
1174
1175 /**
1176 * @brief Gets the number of matching entities.
1177 * @details O(A) where A is number of matching archetypes.
1178 * @return Total count of entities matching the query
1179 */
1180 [[nodiscard]] size_t Count() const noexcept;
1181
1182 /**
1183 * @brief Gets iterator to the first matching entity and components.
1184 * @return Iterator to the beginning of the query results
1185 */
1186 [[nodiscard]] iterator begin() const;
1187
1188 /**
1189 * @brief Gets iterator past the last matching entity and components.
1190 * @return Iterator to the end of the query results
1191 */
1192 [[nodiscard]] iterator end() const {
1193 RefreshArchetypes();
1194 return {matching_archetypes_, GetComponentManager(),
1195 matching_archetypes_.size(), 0, WithoutTypes()};
1196 }
1197
1198 /**
1199 * @brief Gets excluded component type indices for this query.
1200 * @return Span of component type indices that are excluded by this query
1201 */
1202 [[nodiscard]] auto WithoutTypes() const noexcept
1203 -> std::span<const ComponentTypeIndex> {
1204 return {kWithoutIndices.data(), kWithoutIndices.size()};
1205 }
1206
1207 /**
1208 * @brief Gets the allocator used for internal storage.
1209 * @return Allocator instance
1210 */
1211 [[nodiscard]] allocator_type get_allocator() const
1212 noexcept(std::is_nothrow_copy_constructible_v<allocator_type>) {
1213 return alloc_;
1214 }
1215
1216private:
1217 [[nodiscard]] bool EntityHasComponents(Entity entity) const;
1218 [[nodiscard]] bool EntityPassesFilters(Entity entity) const;
1219 [[nodiscard]] bool EntityPassesExclusions(Entity entity) const;
1220
1221 /// @brief Refreshes the cached list of matching archetypes.
1222 void RefreshArchetypes() const;
1223
1224 /// @brief Gets the component manager with correct const qualification.
1225 [[nodiscard]] ComponentManagerType& GetComponentManager() const noexcept {
1226 return components_.get();
1227 }
1228
1229 /// @brief Gets the matching archetypes span.
1230 [[nodiscard]] auto GetMatchingArchetypes() const noexcept
1231 -> std::span<const std::reference_wrapper<const Archetype>> {
1232 return matching_archetypes_;
1233 }
1234
1235 std::reference_wrapper<ComponentManagerType> components_;
1236
1237 /// Rebind allocator for archetype references
1238 using ArchetypeAllocator =
1239 typename std::allocator_traits<allocator_type>::template rebind_alloc<
1240 std::reference_wrapper<const Archetype>>;
1241 mutable std::vector<std::reference_wrapper<const Archetype>,
1242 ArchetypeAllocator>
1243 matching_archetypes_;
1244
1245 [[no_unique_address]] allocator_type alloc_;
1246
1247 friend class BasicQueryWithEntity<WorldT, Allocator, Args...>;
1248};
1249
1250template <typename WorldT, typename Allocator, QueryArg... Args>
1252 ComponentManagerType& components, Allocator alloc)
1253 : components_(components),
1254 matching_archetypes_(ArchetypeAllocator(alloc)),
1255 alloc_(alloc) {
1256 static_assert(
1257 !std::is_const_v<std::remove_reference_t<WorldT>> || TypeInfo::kAllConst,
1258 "Cannot request mutable component access from const World! "
1259 "Use const-qualified components (e.g., 'const Position&') or "
1260 "pass mutable World!");
1261}
1262
1263template <typename WorldT, typename Allocator, QueryArg... Args>
1265 typename BasicQuery<WorldT, Allocator, Args...>::value_type {
1266 HELIOS_ASSERT(entity.Valid(), "Entity '{}' is invalid!", entity);
1267
1268 const auto& manager = GetComponentManager();
1270 manager.Tracked(entity),
1271 "Entity '{}' is not tracked, most likely it does not exist in the world!",
1272 entity);
1273
1274 HELIOS_ASSERT(EntityHasComponents(entity),
1275 "Entity '{}' does not have all requested components!", entity);
1276
1277 const auto& archetype = manager.EntityArchetype(entity);
1278 if constexpr (kIsConst) {
1280 archetype, entity, manager,
1281 static_cast<typename Split::Components*>(nullptr));
1282 } else {
1284 archetype, entity, GetComponentManager(),
1285 static_cast<typename Split::Components*>(nullptr));
1286 }
1287}
1288
1289template <typename WorldT, typename Allocator, QueryArg... Args>
1291 -> std::optional<
1292 typename BasicQuery<WorldT, Allocator, Args...>::value_type> {
1293 HELIOS_ASSERT(entity.Valid(), "Entity '{}' is invalid!", entity);
1294
1295 const auto& manager = GetComponentManager();
1297 manager.Tracked(entity),
1298 "Entity '{}' is not tracked, most likely it does not exist in the world!",
1299 entity);
1300
1301 if (!EntityHasComponents(entity)) {
1302 return std::nullopt;
1303 }
1304
1305 const auto& archetype = manager.EntityArchetype(entity);
1306 if constexpr (kIsConst) {
1308 archetype, entity, manager,
1309 static_cast<typename Split::Components*>(nullptr));
1310 } else {
1312 archetype, entity, GetComponentManager(),
1313 static_cast<typename Split::Components*>(nullptr));
1314 }
1315}
1316
1317template <typename WorldT, typename Allocator, QueryArg... Args>
1319 Entity entity) const
1320 -> std::optional<
1321 typename BasicQuery<WorldT, Allocator, Args...>::value_type> {
1322 HELIOS_ASSERT(entity.Valid(), "Entity '{}' is invalid!", entity);
1323
1324 const auto& manager = GetComponentManager();
1326 manager.Tracked(entity),
1327 "Entity '{}' is not tracked, most likely it does not exist in the world!",
1328 entity);
1329
1330 if (!EntityPassesFilters(entity)) {
1331 return std::nullopt;
1332 }
1333
1334 if (!EntityPassesExclusions(entity)) {
1335 return std::nullopt;
1336 }
1337
1338 const auto& archetype = manager.EntityArchetype(entity);
1339 if constexpr (kIsConst) {
1341 archetype, entity, manager,
1342 static_cast<typename Split::Components*>(nullptr));
1343 } else {
1345 archetype, entity, GetComponentManager(),
1346 static_cast<typename Split::Components*>(nullptr));
1347 }
1348}
1349
1350template <typename WorldT, typename Allocator, QueryArg... Args>
1352 -> std::vector<
1353 typename BasicQuery<WorldT, Allocator, Args...>::value_type> {
1354 std::vector<value_type> result;
1355 result.reserve(Count());
1356 for (auto&& tuple : *this) {
1357 result.push_back(tuple);
1358 }
1359 return result;
1360}
1361
1362template <typename WorldT, typename Allocator, QueryArg... Args>
1363template <typename ResultAlloc>
1364 requires std::same_as<
1365 typename ResultAlloc::value_type,
1366 typename BasicQuery<WorldT, Allocator, Args...>::value_type> &&
1367 (!std::derived_from<std::remove_pointer_t<ResultAlloc>,
1368 std::pmr::memory_resource>)
1370 ResultAlloc alloc) const
1371 -> std::vector<typename BasicQuery<WorldT, Allocator, Args...>::value_type,
1372 ResultAlloc> {
1373 std::vector<value_type, ResultAlloc> result{std::move(alloc)};
1374 result.reserve(Count());
1375 for (auto&& tuple : *this) {
1376 result.push_back(tuple);
1377 }
1378 return result;
1379}
1380
1381template <typename WorldT, typename Allocator, QueryArg... Args>
1383 std::pmr::memory_resource* resource) const
1384 -> std::pmr::vector<
1385 typename BasicQuery<WorldT, Allocator, Args...>::value_type> {
1386 std::pmr::vector<value_type> result{resource};
1387 result.reserve(Count());
1388 for (auto&& tuple : *this) {
1389 result.push_back(tuple);
1390 }
1391 return result;
1392}
1393
1394template <typename WorldT, typename Allocator, QueryArg... Args>
1395template <typename OutIt>
1396 requires std::output_iterator<
1397 OutIt, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1399 for (auto&& result : *this) {
1400 *out++ = std::forward<decltype(result)>(result);
1401 }
1402}
1403
1404template <typename WorldT, typename Allocator, QueryArg... Args>
1405template <typename Action>
1406 requires utils::ActionFor<
1407 Action, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1409 const Action& action) const {
1410 for (auto&& result : *this) {
1411 if constexpr (std::invocable<Action, decltype(result)>) {
1412 action(std::forward<decltype(result)>(result));
1413 } else {
1414 std::apply(action, std::forward<decltype(result)>(result));
1415 }
1416 }
1417}
1418
1419template <typename WorldT, typename Allocator, QueryArg... Args>
1420template <typename Action>
1421 requires utils::ActionFor<Action, typename BasicQueryWithEntity<
1422 WorldT, Allocator, Args...>::value_type>
1424 const Action& action) const {
1425 RefreshArchetypes();
1426 auto begin_iter =
1427 WithEntityIterator(matching_archetypes_, GetComponentManager(), 0, 0);
1428 auto end_iter =
1429 WithEntityIterator(matching_archetypes_, GetComponentManager(),
1430 matching_archetypes_.size(), 0);
1431 for (auto iter = begin_iter; iter != end_iter; ++iter) {
1432 if constexpr (std::invocable<Action, decltype(*iter)>) {
1433 action(*iter);
1434 } else {
1435 std::apply(action, *iter);
1436 }
1437 }
1438}
1439
1440template <typename WorldT, typename Allocator, QueryArg... Args>
1441template <typename Pred>
1442 requires utils::PredicateFor<
1443 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1445 const& -> utils::FilterAdapter<
1446 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Pred> {
1447 RefreshArchetypes();
1448 auto begin_iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0);
1449 auto end_iter = iterator(matching_archetypes_, GetComponentManager(),
1450 matching_archetypes_.size(), 0);
1451 return {begin_iter, end_iter, std::move(predicate)};
1452}
1453
1454template <typename WorldT, typename Allocator, QueryArg... Args>
1455template <typename Func>
1456 requires utils::TransformFor<
1457 Func, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1459 const& -> utils::MapAdapter<
1460 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Func> {
1461 RefreshArchetypes();
1462 auto begin_iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0);
1463 auto end_iter = iterator(matching_archetypes_, GetComponentManager(),
1464 matching_archetypes_.size(), 0);
1465 return {begin_iter, end_iter, std::move(transform)};
1466}
1467
1468template <typename WorldT, typename Allocator, QueryArg... Args>
1470 const& -> utils::TakeAdapter<
1471 typename BasicQuery<WorldT, Allocator, Args...>::iterator> {
1472 RefreshArchetypes();
1473 auto begin_iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0);
1474 auto end_iter = iterator(matching_archetypes_, GetComponentManager(),
1475 matching_archetypes_.size(), 0);
1476 return {begin_iter, end_iter, count};
1477}
1478
1479template <typename WorldT, typename Allocator, QueryArg... Args>
1481 const& -> utils::SkipAdapter<
1482 typename BasicQuery<WorldT, Allocator, Args...>::iterator> {
1483 RefreshArchetypes();
1484 auto begin_iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0);
1485 auto end_iter = iterator(matching_archetypes_, GetComponentManager(),
1486 matching_archetypes_.size(), 0);
1487 return {begin_iter, end_iter, count};
1488}
1489
1490template <typename WorldT, typename Allocator, QueryArg... Args>
1491template <typename Pred>
1492 requires utils::PredicateFor<
1493 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1495 const& -> utils::TakeWhileAdapter<
1496 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Pred> {
1497 RefreshArchetypes();
1498 auto begin_iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0);
1499 auto end_iter = iterator(matching_archetypes_, GetComponentManager(),
1500 matching_archetypes_.size(), 0);
1501 return {begin_iter, end_iter, std::move(predicate)};
1502}
1503
1504template <typename WorldT, typename Allocator, QueryArg... Args>
1505template <typename Pred>
1506 requires utils::PredicateFor<
1507 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1509 const& -> utils::SkipWhileAdapter<
1510 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Pred> {
1511 RefreshArchetypes();
1512 auto begin_iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0);
1513 auto end_iter = iterator(matching_archetypes_, GetComponentManager(),
1514 matching_archetypes_.size(), 0);
1515 return {begin_iter, end_iter, std::move(predicate)};
1516}
1517
1518template <typename WorldT, typename Allocator, QueryArg... Args>
1520 const& -> utils::EnumerateAdapter<
1521 typename BasicQuery<WorldT, Allocator, Args...>::iterator> {
1522 RefreshArchetypes();
1523 auto begin_iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0);
1524 auto end_iter = iterator(matching_archetypes_, GetComponentManager(),
1525 matching_archetypes_.size(), 0);
1526 return {begin_iter, end_iter};
1527}
1528
1529template <typename WorldT, typename Allocator, QueryArg... Args>
1530template <typename Func>
1531 requires utils::InspectorFor<
1532 Func, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1534 const& -> utils::InspectAdapter<
1535 typename BasicQuery<WorldT, Allocator, Args...>::iterator, Func> {
1536 RefreshArchetypes();
1537 auto begin_iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0);
1538 auto end_iter = iterator(matching_archetypes_, GetComponentManager(),
1539 matching_archetypes_.size(), 0);
1540 return {begin_iter, end_iter, std::move(inspector)};
1541}
1542
1543template <typename WorldT, typename Allocator, QueryArg... Args>
1545 const& -> utils::StepByAdapter<
1546 typename BasicQuery<WorldT, Allocator, Args...>::iterator> {
1547 RefreshArchetypes();
1548 auto begin_iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0);
1549 auto end_iter = iterator(matching_archetypes_, GetComponentManager(),
1550 matching_archetypes_.size(), 0);
1551 return {begin_iter, end_iter, step};
1552}
1553
1554template <typename WorldT, typename Allocator, QueryArg... Args>
1555template <typename Pred>
1556 requires utils::PredicateFor<
1557 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1559 const Pred& predicate) const {
1560 for (auto&& result : *this) {
1561 bool matches = false;
1562 if constexpr (std::invocable<Pred, decltype(result)>) {
1563 matches = predicate(std::forward<decltype(result)>(result));
1564 } else {
1565 matches = std::apply(predicate, std::forward<decltype(result)>(result));
1566 }
1567 if (!matches) {
1568 return false;
1569 }
1570 }
1571 return true;
1572}
1573
1574template <typename WorldT, typename Allocator, QueryArg... Args>
1575template <typename Pred>
1576 requires utils::PredicateFor<
1577 Pred, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1579 const Pred& predicate) const {
1580 size_t count = 0;
1581 for (auto&& result : *this) {
1582 bool matches = false;
1583 if constexpr (std::invocable<Pred, decltype(result)>) {
1584 matches = predicate(std::forward<decltype(result)>(result));
1585 } else {
1586 matches = std::apply(predicate, std::forward<decltype(result)>(result));
1587 }
1588 if (matches) {
1589 ++count;
1590 }
1591 }
1592 return count;
1593}
1594
1595template <typename WorldT, typename Allocator, QueryArg... Args>
1596template <typename T, typename Func>
1597 requires utils::FolderFor<
1598 Func, T, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1600 T init, const Func& folder) const {
1601 for (auto&& tuple : *this) {
1602 if constexpr (std::invocable<Func, T, decltype(tuple)>) {
1603 init = folder(std::move(init), std::forward<decltype(tuple)>(tuple));
1604 } else {
1605 init = std::apply(
1606 [&init, &folder](auto&&... components) {
1607 return folder(std::move(init),
1608 std::forward<decltype(components)>(components)...);
1609 },
1610 tuple);
1611 }
1612 }
1613 return init;
1614}
1615
1616template <typename WorldT, typename Allocator, QueryArg... Args>
1617template <typename KeyExtractor>
1618 requires utils::TransformFor<
1619 KeyExtractor, typename BasicQuery<WorldT, Allocator, Args...>::value_type>
1621 const KeyExtractor& key_extractor) const
1622 -> std::unordered_map<
1624 const KeyExtractor&,
1625 typename BasicQuery<WorldT, Allocator, Args...>::value_type>>,
1626 std::vector<
1627 typename BasicQuery<WorldT, Allocator, Args...>::value_type>> {
1628 using KeyType = std::decay_t<
1630 std::unordered_map<KeyType, std::vector<value_type>> groups;
1631
1632 for (auto&& result : *this) {
1633 auto key = [&key_extractor](auto&& value) {
1634 if constexpr (std::invocable<KeyExtractor, decltype(value)>) {
1635 return key_extractor(std::forward<decltype(value)>(value));
1636 } else {
1637 return std::apply(key_extractor, std::forward<decltype(value)>(value));
1638 }
1639 }(std::forward<decltype(result)>(result));
1640 groups[key].push_back(result);
1641 }
1642
1643 return groups;
1644}
1645
1646template <typename WorldT, typename Allocator, QueryArg... Args>
1648 RefreshArchetypes();
1649 return matching_archetypes_.empty() || Count() == 0;
1650}
1651
1652template <typename WorldT, typename Allocator, QueryArg... Args>
1654 RefreshArchetypes();
1655 size_t count = 0;
1656 auto iter = iterator(matching_archetypes_, GetComponentManager(), 0, 0,
1657 WithoutTypes());
1658 const auto end_iter =
1659 iterator(matching_archetypes_, GetComponentManager(),
1660 matching_archetypes_.size(), 0, WithoutTypes());
1661 while (iter != end_iter) {
1662 ++count;
1663 ++iter;
1664 }
1665 return count;
1666}
1667
1668template <typename WorldT, typename Allocator, QueryArg... Args>
1670 typename BasicQuery<WorldT, Allocator, Args...>::iterator {
1671 RefreshArchetypes();
1672 return {matching_archetypes_, GetComponentManager(), 0, 0, WithoutTypes()};
1673}
1674
1675template <typename WorldT, typename Allocator, QueryArg... Args>
1676inline bool BasicQuery<WorldT, Allocator, Args...>::EntityHasComponents(
1677 Entity entity) const {
1678 if constexpr (std::tuple_size_v<typename Split::Components> == 0) {
1679 return true;
1680 } else {
1682 GetComponentManager(), entity,
1683 static_cast<typename Split::Components*>(nullptr));
1684 }
1685}
1686
1687template <typename WorldT, typename Allocator, QueryArg... Args>
1688inline bool BasicQuery<WorldT, Allocator, Args...>::EntityPassesFilters(
1689 Entity entity) const {
1690 const auto& manager = GetComponentManager();
1691
1692 for (const auto type : kWithIndices) {
1693 const auto* meta = manager.MetadataByIndex(type);
1694 if (meta == nullptr) [[unlikely]] {
1695 return false;
1696 }
1697
1698 if (meta->storage_type == ComponentStorageType::kSparseSet) {
1699 const auto* entry = manager.SparseEntry(type);
1700 if (entry == nullptr || !entry->Contains(entity)) {
1701 return false;
1702 }
1703 } else {
1704 const auto& archetype = manager.EntityArchetype(entity);
1705 if (!archetype.Id().Contains(type)) {
1706 return false;
1707 }
1708 }
1709 }
1710
1711 return EntityHasComponents(entity);
1712}
1713
1714template <typename WorldT, typename Allocator, QueryArg... Args>
1715inline bool BasicQuery<WorldT, Allocator, Args...>::EntityPassesExclusions(
1716 Entity entity) const {
1717 const auto& manager = GetComponentManager();
1718 return std::ranges::none_of(kWithoutIndices, [&manager, entity](auto type) {
1719 const auto* meta = manager.MetadataByIndex(type);
1720 if (meta == nullptr) {
1721 return false;
1722 }
1723 if (meta->storage_type == ComponentStorageType::kSparseSet) {
1724 const auto* entry = manager.SparseEntry(type);
1725 return entry != nullptr && entry->Contains(entity);
1726 }
1727 const auto& archetype = manager.EntityArchetype(entity);
1728 return archetype.Id().Contains(type);
1729 });
1730}
1731
1732template <typename WorldT, typename Allocator, QueryArg... Args>
1733inline void BasicQuery<WorldT, Allocator, Args...>::RefreshArchetypes() const {
1734 matching_archetypes_.clear();
1735
1736 auto archetypes = [this]() {
1737 if constexpr (kIsConst) {
1738 return std::as_const(components_.get()).Archetypes();
1739 } else {
1740 return components_.get().Archetypes();
1741 }
1742 }();
1743
1744 for (const auto& arch_ref : archetypes) {
1745 const auto& archetype = arch_ref.get();
1746 if (archetype.Empty()) {
1747 continue;
1748 }
1749
1750 const auto& arch_id = archetype.Id();
1751
1752 auto arch_contains_type = [this,
1753 &arch_id](ComponentTypeIndex type) -> bool {
1754 const auto* meta = components_.get().MetadataByIndex(type);
1755 if (meta == nullptr) {
1756 return false;
1757 }
1758 if (meta->storage_type == ComponentStorageType::kSparseSet) {
1759 return true;
1760 }
1761 return arch_id.Contains(type);
1762 };
1763
1764 bool has_all_with = std::ranges::all_of(kWithIndices, arch_contains_type);
1765 if (!has_all_with) {
1766 continue;
1767 }
1768
1769 bool has_all_comp = [this, &arch_id]<typename... CompTypes>(
1770 std::tuple<CompTypes...>*) {
1771 return (
1772 ([this, &arch_id]() -> bool {
1773 if constexpr (details::kIsPointerAccess<CompTypes>) {
1774 return true;
1775 } else {
1776 using RawType = details::ComponentTypeExtractor_t<CompTypes>;
1777 const auto type_idx = ComponentTypeIndex::From<RawType>();
1778 const auto* meta =
1779 std::as_const(components_.get()).MetadataByIndex(type_idx);
1780 if (meta == nullptr) {
1781 return false;
1782 }
1783 if (meta->storage_type == ComponentStorageType::kSparseSet) {
1784 return true;
1785 }
1786 return arch_id.Contains(type_idx);
1787 }
1788 }()) &&
1789 ...);
1790 }(static_cast<typename Split::Components*>(nullptr));
1791 if (!has_all_comp) {
1792 continue;
1793 }
1794
1795 bool has_any_excluded = std::ranges::any_of(
1796 kWithoutIndices, [this, &arch_id](ComponentTypeIndex type) {
1797 const auto* meta = components_.get().MetadataByIndex(type);
1798 if (meta == nullptr) {
1799 return false;
1800 }
1801 if (meta->storage_type == ComponentStorageType::kSparseSet) {
1802 return false;
1803 }
1804 return arch_id.Contains(type);
1805 });
1806 if (has_any_excluded) {
1807 continue;
1808 }
1809
1810 matching_archetypes_.push_back(std::cref(archetype));
1811 }
1812}
1813
1814// BasicQueryWithEntity out-of-line definitions
1815
1816template <typename WorldT, typename Allocator, QueryArg... Args>
1818 -> std::vector<
1819 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type> {
1820 std::vector<value_type> result;
1821 result.reserve(query_.Count());
1822 for (auto&& tuple : *this) {
1823 result.push_back(tuple);
1824 }
1825 return result;
1826}
1827
1828template <typename WorldT, typename Allocator, QueryArg... Args>
1829template <typename ResultAlloc>
1830 requires std::same_as<typename ResultAlloc::value_type,
1831 typename BasicQueryWithEntity<WorldT, Allocator,
1832 Args...>::value_type> &&
1833 (!std::derived_from<std::remove_pointer_t<ResultAlloc>,
1834 std::pmr::memory_resource>)
1836 ResultAlloc alloc) const
1837 -> std::vector<
1838 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type,
1839 ResultAlloc> {
1840 std::vector<value_type, ResultAlloc> result{std::move(alloc)};
1841 result.reserve(query_.Count());
1842 for (auto&& tuple : *this) {
1843 result.push_back(tuple);
1844 }
1845 return result;
1846}
1847
1848template <typename WorldT, typename Allocator, QueryArg... Args>
1850 std::pmr::memory_resource* resource) const
1851 -> std::pmr::vector<
1852 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type> {
1853 std::pmr::vector<value_type> result{resource};
1854 result.reserve(query_.Count());
1855 for (auto&& tuple : *this) {
1856 result.push_back(tuple);
1857 }
1858 return result;
1859}
1860
1861template <typename WorldT, typename Allocator, QueryArg... Args>
1863 const -> std::vector<Entity> {
1864 std::vector<Entity> result;
1865 result.reserve(query_.Count());
1866 for (auto&& tuple : *this) {
1867 result.push_back(std::get<0>(tuple));
1868 }
1869 return result;
1870}
1871
1872template <typename WorldT, typename Allocator, QueryArg... Args>
1873template <typename ResultAlloc>
1874 requires std::same_as<typename ResultAlloc::value_type, Entity> &&
1875 (!std::derived_from<std::remove_pointer_t<ResultAlloc>,
1876 std::pmr::memory_resource>)
1877inline auto
1879 ResultAlloc alloc) const -> std::vector<Entity, ResultAlloc> {
1880 std::vector<Entity, ResultAlloc> result{std::move(alloc)};
1881 result.reserve(query_.Count());
1882 for (auto&& tuple : *this) {
1883 result.push_back(std::get<0>(tuple));
1884 }
1885 return result;
1886}
1887
1888template <typename WorldT, typename Allocator, QueryArg... Args>
1889inline auto
1891 std::pmr::memory_resource* resource) const -> std::pmr::vector<Entity> {
1892 std::pmr::vector<Entity> result{resource};
1893 result.reserve(query_.Count());
1894 for (auto&& tuple : *this) {
1895 result.push_back(std::get<0>(tuple));
1896 }
1897 return result;
1898}
1899
1900template <typename WorldT, typename Allocator, QueryArg... Args>
1901template <typename OutIt>
1902 requires std::output_iterator<
1903 OutIt,
1904 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
1906 for (auto&& result : *this) {
1907 *out++ = std::forward<decltype(result)>(result);
1908 }
1909}
1910
1911template <typename WorldT, typename Allocator, QueryArg... Args>
1912template <typename Action>
1913 requires utils::ActionFor<Action, typename BasicQueryWithEntity<
1914 WorldT, Allocator, Args...>::value_type>
1916 const Action& action) const {
1917 for (auto&& result : *this) {
1918 if constexpr (std::invocable<Action, decltype(result)>) {
1919 action(std::forward<decltype(result)>(result));
1920 } else {
1921 std::apply(action, std::forward<decltype(result)>(result));
1922 }
1923 }
1924}
1925
1926template <typename WorldT, typename Allocator, QueryArg... Args>
1927template <typename Pred>
1928 requires utils::PredicateFor<
1929 Pred,
1930 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
1932 Pred predicate) const
1934 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
1935 Pred> {
1936 query_.RefreshArchetypes();
1937 auto begin_iter = iterator(query_.GetMatchingArchetypes(),
1938 query_.GetComponentManager(), 0, 0);
1939 auto end_iter =
1940 iterator(query_.GetMatchingArchetypes(), query_.GetComponentManager(),
1941 query_.GetMatchingArchetypes().size(), 0);
1942 return {begin_iter, end_iter, std::move(predicate)};
1943}
1944
1945template <typename WorldT, typename Allocator, QueryArg... Args>
1946template <typename Func>
1947 requires utils::TransformFor<
1948 Func,
1949 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
1951 Func transform) const
1953 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
1954 Func> {
1955 query_.RefreshArchetypes();
1956 auto begin_iter = iterator(query_.GetMatchingArchetypes(),
1957 query_.GetComponentManager(), 0, 0);
1958 auto end_iter =
1959 iterator(query_.GetMatchingArchetypes(), query_.GetComponentManager(),
1960 query_.GetMatchingArchetypes().size(), 0);
1961 return {begin_iter, end_iter, std::move(transform)};
1962}
1963
1964template <typename WorldT, typename Allocator, QueryArg... Args>
1966 const -> utils::TakeAdapter<
1967 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator> {
1968 query_.RefreshArchetypes();
1969 auto begin_iter = iterator(query_.GetMatchingArchetypes(),
1970 query_.GetComponentManager(), 0, 0);
1971 auto end_iter =
1972 iterator(query_.GetMatchingArchetypes(), query_.GetComponentManager(),
1973 query_.GetMatchingArchetypes().size(), 0);
1974 return {begin_iter, end_iter, count};
1975}
1976
1977template <typename WorldT, typename Allocator, QueryArg... Args>
1979 const -> utils::SkipAdapter<
1980 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator> {
1981 query_.RefreshArchetypes();
1982 auto begin_iter = iterator(query_.GetMatchingArchetypes(),
1983 query_.GetComponentManager(), 0, 0);
1984 auto end_iter =
1985 iterator(query_.GetMatchingArchetypes(), query_.GetComponentManager(),
1986 query_.GetMatchingArchetypes().size(), 0);
1987 return {begin_iter, end_iter, count};
1988}
1989
1990template <typename WorldT, typename Allocator, QueryArg... Args>
1991template <typename Pred>
1992 requires utils::PredicateFor<
1993 Pred,
1994 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
1996 Pred predicate) const
1998 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
1999 Pred> {
2000 query_.RefreshArchetypes();
2001 auto begin_iter = iterator(query_.GetMatchingArchetypes(),
2002 query_.GetComponentManager(), 0, 0);
2003 auto end_iter =
2004 iterator(query_.GetMatchingArchetypes(), query_.GetComponentManager(),
2005 query_.GetMatchingArchetypes().size(), 0);
2006 return {begin_iter, end_iter, std::move(predicate)};
2007}
2008
2009template <typename WorldT, typename Allocator, QueryArg... Args>
2010template <typename Pred>
2011 requires utils::PredicateFor<
2012 Pred,
2013 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2015 Pred predicate) const
2017 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
2018 Pred> {
2019 query_.RefreshArchetypes();
2020 auto begin_iter = iterator(query_.GetMatchingArchetypes(),
2021 query_.GetComponentManager(), 0, 0);
2022 auto end_iter =
2023 iterator(query_.GetMatchingArchetypes(), query_.GetComponentManager(),
2024 query_.GetMatchingArchetypes().size(), 0);
2025 return {begin_iter, end_iter, std::move(predicate)};
2026}
2027
2028template <typename WorldT, typename Allocator, QueryArg... Args>
2030 -> utils::EnumerateAdapter<
2031 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator> {
2032 query_.RefreshArchetypes();
2033 auto begin_iter = iterator(query_.GetMatchingArchetypes(),
2034 query_.GetComponentManager(), 0, 0);
2035 auto end_iter =
2036 iterator(query_.GetMatchingArchetypes(), query_.GetComponentManager(),
2037 query_.GetMatchingArchetypes().size(), 0);
2038 return {begin_iter, end_iter};
2039}
2040
2041template <typename WorldT, typename Allocator, QueryArg... Args>
2042template <typename Func>
2043 requires utils::InspectorFor<
2044 Func,
2045 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2047 Func inspector) const
2049 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator,
2050 Func> {
2051 query_.RefreshArchetypes();
2052 auto begin_iter = iterator(query_.GetMatchingArchetypes(),
2053 query_.GetComponentManager(), 0, 0);
2054 auto end_iter =
2055 iterator(query_.GetMatchingArchetypes(), query_.GetComponentManager(),
2056 query_.GetMatchingArchetypes().size(), 0);
2057 return {begin_iter, end_iter, std::move(inspector)};
2058}
2059
2060template <typename WorldT, typename Allocator, QueryArg... Args>
2062 size_t step) const
2064 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::iterator> {
2065 query_.RefreshArchetypes();
2066 auto begin_iter = iterator(query_.GetMatchingArchetypes(),
2067 query_.GetComponentManager(), 0, 0);
2068 auto end_iter =
2069 iterator(query_.GetMatchingArchetypes(), query_.GetComponentManager(),
2070 query_.GetMatchingArchetypes().size(), 0);
2071 return {begin_iter, end_iter, step};
2072}
2073
2074template <typename WorldT, typename Allocator, QueryArg... Args>
2075template <typename Pred>
2076 requires utils::PredicateFor<
2077 Pred,
2078 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2080 const Pred& predicate) const {
2081 return Find(predicate).has_value();
2082}
2083
2084template <typename WorldT, typename Allocator, QueryArg... Args>
2085template <typename Pred>
2086 requires utils::PredicateFor<
2087 Pred,
2088 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2090 const Pred& predicate) const {
2091 for (auto&& result : *this) {
2092 bool matches = false;
2093 if constexpr (std::invocable<Pred, decltype(result)>) {
2094 matches = predicate(std::forward<decltype(result)>(result));
2095 } else {
2096 matches = std::apply(predicate, std::forward<decltype(result)>(result));
2097 }
2098 if (!matches) {
2099 return false;
2100 }
2101 }
2102 return true;
2103}
2104
2105template <typename WorldT, typename Allocator, QueryArg... Args>
2106template <typename Pred>
2107 requires utils::PredicateFor<
2108 Pred,
2109 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2111 const Pred& predicate) const
2112 -> std::optional<
2113 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type> {
2114 return begin().Find(predicate);
2115}
2116
2117template <typename WorldT, typename Allocator, QueryArg... Args>
2118template <typename Pred>
2119 requires utils::PredicateFor<
2120 Pred,
2121 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2123 const Pred& predicate) const {
2124 return begin().CountIf(predicate);
2125}
2126
2127template <typename WorldT, typename Allocator, QueryArg... Args>
2128template <typename T, typename Func>
2129 requires utils::FolderFor<
2130 Func, T,
2131 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2133 T init, const Func& folder) const {
2134 return begin().Fold(std::move(init), folder);
2135}
2136
2137template <typename WorldT, typename Allocator, QueryArg... Args>
2138template <typename KeyFunc>
2139 requires utils::TransformFor<
2140 KeyFunc,
2141 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2143 const KeyFunc& key_func) const
2144 -> std::optional<
2145 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type> {
2146 return begin().MaxBy(key_func);
2147}
2148
2149template <typename WorldT, typename Allocator, QueryArg... Args>
2150template <typename KeyFunc>
2151 requires utils::TransformFor<
2152 KeyFunc,
2153 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2155 const KeyFunc& key_func) const
2156 -> std::optional<
2157 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type> {
2158 return begin().MinBy(key_func);
2159}
2160
2161template <typename WorldT, typename Allocator, QueryArg... Args>
2162template <typename Pred>
2163 requires utils::PredicateFor<
2164 Pred,
2165 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2167 const Pred& predicate) const
2168 -> std::pair<std::vector<typename BasicQueryWithEntity<
2169 WorldT, Allocator, Args...>::value_type>,
2170 std::vector<typename BasicQueryWithEntity<
2171 WorldT, Allocator, Args...>::value_type>> {
2172 return begin().Partition(predicate);
2173}
2174
2175template <typename WorldT, typename Allocator, QueryArg... Args>
2176template <typename KeyExtractor>
2177 requires utils::TransformFor<
2178 KeyExtractor,
2179 typename BasicQueryWithEntity<WorldT, Allocator, Args...>::value_type>
2181 const KeyExtractor& key_extractor) const
2182 -> std::unordered_map<
2184 const KeyExtractor&, typename BasicQueryWithEntity<
2185 WorldT, Allocator, Args...>::value_type>>,
2186 std::vector<typename BasicQueryWithEntity<WorldT, Allocator,
2187 Args...>::value_type>> {
2188 using KeyType = std::decay_t<
2190 std::unordered_map<KeyType, std::vector<value_type>> groups;
2191
2192 for (auto&& result : *this) {
2193 auto key = [&key_extractor](auto&& value) {
2194 if constexpr (std::invocable<KeyExtractor, decltype(value)>) {
2195 return key_extractor(std::forward<decltype(value)>(value));
2196 } else {
2197 return std::apply(key_extractor, std::forward<decltype(value)>(value));
2198 }
2199 }(std::forward<decltype(result)>(result));
2200 groups[key].push_back(result);
2201 }
2202
2203 return groups;
2204}
2205
2206template <typename WorldT, typename Allocator, QueryArg... Args>
2208 -> iterator {
2209 query_.RefreshArchetypes();
2210 return {query_.GetMatchingArchetypes(), query_.GetComponentManager(), 0, 0,
2211 query_.WithoutTypes()};
2212}
2213
2214template <typename WorldT, typename Allocator, QueryArg... Args>
2216 const noexcept -> iterator {
2217 return {query_.GetMatchingArchetypes(), query_.GetComponentManager(),
2218 query_.GetMatchingArchetypes().size(), 0};
2219}
2220
2221template <typename Alloc, QueryArg... Args>
2222using MutBasicQuery = BasicQuery<World, Alloc, Args...>;
2223
2224template <typename Alloc, QueryArg... Args>
2225using ReadOnlyBasicQuery = BasicQuery<const World, Alloc, Args...>;
2226
2227template <typename Alloc, QueryArg... Args>
2229
2230template <typename Alloc, QueryArg... Args>
2232 BasicQueryWithEntity<const World, Alloc, Args...>;
2233
2234template <QueryArg... Args>
2237
2238template <QueryArg... Args>
2241
2242template <QueryArg... Args>
2245
2246template <QueryArg... Args>
2249 Args...>;
2250
2251/**
2252 * @brief Alias for `BasicQuery` bound to `World` with a PMR allocator.
2253 * @details The canonical query type for system parameters. Users who need a
2254 * different world type or allocator can use `BasicQuery` directly.
2255 * @tparam Args Component access types and optional With/Without filters
2256 *
2257 * @code
2258 * void MySystem(Query<Transform&, const Velocity&, With<Player>> query) {
2259 * for (auto&& [transform, velocity] : query) { ... }
2260 * }
2261 * @endcode
2262 */
2263template <QueryArg... Args>
2265
2266} // namespace helios::ecs
#define HELIOS_ASSERT(condition,...)
Assertion macro that aborts execution in debug builds.
Definition assert.hpp:259
Stores entities and their component data in a Structure-of-Arrays layout for a specific archetype.
Definition archetype.hpp:50
Wrapper that provides entity-aware iteration over query results.
Definition query.hpp:80
auto Zip(const BasicQueryWithEntity &other) const -> utils::ZipAdapter< iterator, iterator >
Zips this query with another query of the same type.
Definition query.hpp:431
auto CollectWith(ResultAlloc alloc) const -> std::vector< value_type, ResultAlloc >
auto CollectEntities() const -> std::vector< Entity >
auto Zip(OtherIter other_begin, OtherIter other_end) const -> utils::ZipAdapter< iterator, OtherIter >
Zips this query with another iterator range.
Definition query.hpp:421
typename iterator::pointer pointer
Definition query.hpp:91
auto Partition(const Pred &predicate) const -> std::pair< std::vector< typename BasicQueryWithEntity< WorldT, Allocator, Args... >::value_type >, std::vector< typename BasicQueryWithEntity< WorldT, Allocator, Args... >::value_type > >
Partitions results into two groups based on a predicate.
Definition query.hpp:2166
auto Inspect(Func inspector) const -> utils::InspectAdapter< typename BasicQueryWithEntity< World, Alloc, Args... >::iterator, Func >
iterator begin() const
Gets iterator to first matching entity and components.
Definition query.hpp:2207
size_t CountIf(const Pred &predicate) const
Counts entities matching a predicate.
Definition query.hpp:2122
std::iter_reference_t< iterator > reference
Definition query.hpp:92
bool None(const Pred &predicate) const
Checks if no entities match the predicate.
Definition query.hpp:595
~BasicQueryWithEntity() noexcept=default
auto Stride(size_t stride) const -> utils::StrideAdapter< iterator >
Takes every Nth element with stride.
Definition query.hpp:407
bool Any(const Pred &predicate) const
Checks if any entity matches the predicate.
Definition query.hpp:2079
BasicQueryWithEntity(BasicQuery< WorldT, Allocator, Args... > &query) noexcept
Constructs entity-aware query wrapper.
Definition query.hpp:99
auto Find(const Pred &predicate) const -> std::optional< typename BasicQueryWithEntity< WorldT, Allocator, Args... >::value_type >
Finds the first result matching a predicate.
Definition query.hpp:2110
auto Map(Func transform) const -> utils::MapAdapter< typename BasicQueryWithEntity< World, Alloc, Args... >::iterator, Func >
typename TypeInfo::template WithEntityIterator< kIsConst > iterator
Definition query.hpp:87
auto TakeWhile(Pred predicate) const -> utils::TakeWhileAdapter< typename BasicQueryWithEntity< World, Alloc, Args... >::iterator, Pred >
auto Chain(R &range) const -> utils::ChainAdapter< iterator, std::ranges::iterator_t< R > >
Chains this query with another range.
Definition query.hpp:362
auto Slide(size_t window_size) const -> utils::SlideAdapter< iterator >
Creates sliding windows over query results.
Definition query.hpp:396
auto StepBy(size_t step) const -> utils::StepByAdapter< typename BasicQueryWithEntity< World, Alloc, Args... >::iterator >
BasicQueryWithEntity(const BasicQueryWithEntity &)=delete
std::iter_difference_t< iterator > difference_type
Definition query.hpp:90
auto Chain(const BasicQueryWithEntity &other) const -> utils::ChainAdapter< iterator, iterator >
Chains this query with another query of the same type.
Definition query.hpp:348
auto Enumerate() const -> utils::EnumerateAdapter< typename BasicQueryWithEntity< World, Alloc, Args... >::iterator >
T Fold(T init, const Func &folder) const
Folds query results into a single value.
Definition query.hpp:2132
bool All(const Pred &predicate) const
Checks if all entities match the predicate.
Definition query.hpp:2089
typename TypeInfo::template WithEntityIterator< true > const_iterator
Definition query.hpp:88
auto TryGet(Entity entity) const -> std::optional< value_type >
Tries to get all query components for a specific entity (ignores query filters).
Definition query.hpp:126
size_t Count() const noexcept
Gets the number of matching entities.
Definition query.hpp:609
auto Collect() const -> std::vector< typename BasicQueryWithEntity< WorldT, Allocator, Args... >::value_type >
Collects all results into a vector.
Definition query.hpp:1817
auto Filter(Pred predicate) const -> utils::FilterAdapter< typename BasicQueryWithEntity< World, Alloc, Args... >::iterator, Pred >
bool Empty() const noexcept
Checks if query matches no entities.
Definition query.hpp:603
iterator end() const noexcept
Gets iterator past the last matching entity and components.
Definition query.hpp:2215
auto MaxBy(const KeyFunc &key_func) const -> std::optional< typename BasicQueryWithEntity< WorldT, Allocator, Args... >::value_type >
Finds the element with the maximum key value.
Definition query.hpp:2142
auto Get(Entity entity) const -> value_type
Definition query.hpp:116
auto Take(size_t count) const -> utils::TakeAdapter< typename BasicQueryWithEntity< World, Alloc, Args... >::iterator >
auto Chain(const R &range) const -> utils::ChainAdapter< iterator, std::ranges::iterator_t< const R > >
Chains this query with another const range.
Definition query.hpp:376
auto Zip(const R &range) const -> utils::ZipAdapter< iterator, std::ranges::iterator_t< const R > >
Zips this query with another const range.
Definition query.hpp:458
auto CollectEntitiesWith(ResultAlloc alloc) const -> std::vector< Entity, ResultAlloc >
auto TryGetFiltered(Entity entity) const -> std::optional< value_type >
Tries to get all query components for a specific entity while respecting query filters.
Definition query.hpp:136
auto Zip(R &range) const -> utils::ZipAdapter< iterator, std::ranges::iterator_t< R > >
Zips this query with another range.
Definition query.hpp:444
auto SkipWhile(Pred predicate) const -> utils::SkipWhileAdapter< typename BasicQueryWithEntity< World, Alloc, Args... >::iterator, Pred >
BasicQueryWithEntity(BasicQueryWithEntity &&)=delete
auto GroupBy(const KeyExtractor &key_extractor) const -> std::unordered_map< std::decay_t< utils::details::call_or_apply_result_t< const KeyExtractor &, typename BasicQueryWithEntity< WorldT, Allocator, Args... >::value_type > >, std::vector< typename BasicQueryWithEntity< WorldT, Allocator, Args... >::value_type > >
Groups results by an extracted key.
Definition query.hpp:2180
auto Skip(size_t count) const -> utils::SkipAdapter< typename BasicQueryWithEntity< World, Alloc, Args... >::iterator >
auto Reverse() const -> utils::ReverseAdapter< iterator >
Reverses the order of iteration.
Definition query.hpp:386
auto Chain(OtherIter other_begin, OtherIter other_end) const -> utils::ChainAdapter< iterator, OtherIter >
Definition query.hpp:338
auto MinBy(const KeyFunc &key_func) const -> std::optional< typename BasicQueryWithEntity< WorldT, Allocator, Args... >::value_type >
Finds the element with the minimum key value.
Definition query.hpp:2154
std::iter_value_t< iterator > value_type
Definition query.hpp:89
Query result object for iterating over matching entities and components.
Definition query.hpp:659
auto Get(Entity entity) const -> typename BasicQuery< WorldT, Allocator, Args... >::value_type
Gets all query components for a specific entity (ignores query filters).
Definition query.hpp:1264
auto Chain(const R &range) const &-> utils::ChainAdapter< iterator, std::ranges::iterator_t< const R > >
Chains this query with another const range.
Definition query.hpp:953
auto Inspect(Func inspector) const &-> utils::InspectAdapter< typename BasicQuery< World, Alloc, Args... >::iterator, Func >
auto CollectWith(ResultAlloc alloc) const -> std::vector< typename BasicQuery< World, Alloc, Args... >::value_type, ResultAlloc >
bool Any(const Pred &predicate) const
Checks if any element matches the predicate.
Definition query.hpp:1142
typename iterator::pointer pointer
Definition query.hpp:677
BasicQuery(BasicQuery &&) noexcept=default
auto Take(size_t count) const &-> utils::TakeAdapter< typename BasicQuery< World, Alloc, Args... >::iterator >
auto Chain(R &range) const &-> utils::ChainAdapter< iterator, std::ranges::iterator_t< R > >
Chains this query with another range.
Definition query.hpp:939
auto Zip(R &range) const &-> utils::ZipAdapter< iterator, std::ranges::iterator_t< R > >
Zips this query with another range.
Definition query.hpp:1021
void ForEachWithEntity(const Action &action) const
BasicQuery(const BasicQuery &)=delete
auto MaxBy(const KeyFunc &key_func) const -> std::optional< value_type >
Finds the element with the maximum key value.
Definition query.hpp:1099
std::iter_difference_t< iterator > difference_type
Definition query.hpp:676
auto Chain(const BasicQuery &other) const &-> utils::ChainAdapter< iterator, iterator >
Chains this query with another query of the same type.
Definition query.hpp:925
typename TypeInfo::ComponentManagerType ComponentManagerType
Definition query.hpp:669
auto Zip(const BasicQuery &other) const &-> utils::ZipAdapter< iterator, iterator >
Zips this query with another query of the same type.
Definition query.hpp:1008
auto WithEntity() &noexcept -> BasicQueryWithEntity< World, Alloc, Args... >
Definition query.hpp:716
auto StepBy(size_t step) const &-> utils::StepByAdapter< typename BasicQuery< World, Alloc, Args... >::iterator >
auto GroupBy(const KeyExtractor &key_extractor) const -> std::unordered_map< std::decay_t< utils::details::call_or_apply_result_t< const KeyExtractor &, typename BasicQuery< WorldT, Allocator, Args... >::value_type > >, std::vector< typename BasicQuery< WorldT, Allocator, Args... >::value_type > >
Groups elements by a key extracted from each result.
Definition query.hpp:1620
bool None(const Pred &predicate) const
Checks if no elements match the predicate.
Definition query.hpp:1165
size_t CountIf(const Pred &predicate) const
Counts elements matching a predicate.
Definition query.hpp:1578
auto Skip(size_t count) const &-> utils::SkipAdapter< typename BasicQuery< World, Alloc, Args... >::iterator >
typename TypeInfo::template Iterator< true > const_iterator
Definition query.hpp:674
auto Reverse() const &-> utils::ReverseAdapter< iterator >
Reverses the order of iteration.
Definition query.hpp:963
auto Slide(size_t window_size) const &-> utils::SlideAdapter< iterator >
Creates sliding windows over query results.
Definition query.hpp:973
auto WithoutTypes() const noexcept -> std::span< const ComponentTypeIndex >
Definition query.hpp:1202
auto TryGet(Entity entity) const -> std::optional< typename BasicQuery< WorldT, Allocator, Args... >::value_type >
Tries to get all query components for a specific entity (ignores query filters).
Definition query.hpp:1290
void ForEach(const Action &action) const
auto Find(const Pred &predicate) const -> std::optional< value_type >
Finds the first element matching a predicate.
Definition query.hpp:1062
allocator_type get_allocator() const noexcept(std::is_nothrow_copy_constructible_v< allocator_type >)
Gets the allocator used for internal storage.
Definition query.hpp:1211
auto Enumerate() const &-> utils::EnumerateAdapter< typename BasicQuery< World, Alloc, Args... >::iterator >
BasicQuery(ComponentManagerType &components, Allocator alloc={})
Constructs query with the given component manager and allocator.
Definition query.hpp:1251
auto Collect() const -> std::vector< typename BasicQuery< WorldT, Allocator, Args... >::value_type >
Collects all results into a vector.
Definition query.hpp:1351
T Fold(T init, const Func &folder) const
Folds query results into a single value.
Definition query.hpp:1599
bool Empty() const noexcept
Checks if query matches no entities.
Definition query.hpp:1647
typename TypeInfo::ValueType value_type
Definition query.hpp:675
auto Stride(size_t stride) const &-> utils::StrideAdapter< iterator >
Takes every Nth element with stride.
Definition query.hpp:984
typename TypeInfo::template WithEntityIterator< kIsConst > WithEntityIterator
Definition query.hpp:670
auto Map(Func transform) const &-> utils::MapAdapter< typename BasicQuery< World, Alloc, Args... >::iterator, Func >
BasicQuery(ComponentManagerType &, std::nullptr_t)=delete
auto Zip(OtherIter other_begin, OtherIter other_end) const &-> utils::ZipAdapter< iterator, OtherIter >
Zips this query with another iterator range.
Definition query.hpp:998
std::iter_reference_t< iterator > reference
Definition query.hpp:678
Allocator allocator_type
Definition query.hpp:679
auto Partition(const Pred &predicate) const -> std::pair< std::vector< value_type >, std::vector< value_type > >
Partitions elements into two groups based on a predicate.
Definition query.hpp:1086
auto Zip(const R &range) const &-> utils::ZipAdapter< iterator, std::ranges::iterator_t< const R > >
Zips this query with another const range.
Definition query.hpp:1035
auto MinBy(const KeyFunc &key_func) const -> std::optional< value_type >
Finds the element with the minimum key value.
Definition query.hpp:1112
auto TryGetFiltered(Entity entity) const -> std::optional< typename BasicQuery< WorldT, Allocator, Args... >::value_type >
Tries to get all query components for a specific entity while respecting query filters.
Definition query.hpp:1318
BasicQuery(ComponentManagerType &components, std::pmr::memory_resource *resource)
Constructs query from a PMR memory resource.
Definition query.hpp:697
auto Filter(Pred predicate) const &-> utils::FilterAdapter< typename BasicQuery< World, Alloc, Args... >::iterator, Pred >
typename TypeInfo::template Iterator< kIsConst > iterator
Definition query.hpp:673
bool All(const Pred &predicate) const
Checks if all elements match the predicate.
Definition query.hpp:1558
auto Chain(OtherIter other_begin, OtherIter other_end) const &-> utils::ChainAdapter< iterator, OtherIter >
Definition query.hpp:915
auto SkipWhile(Pred predicate) const &-> utils::SkipWhileAdapter< typename BasicQuery< World, Alloc, Args... >::iterator, Pred >
auto TakeWhile(Pred predicate) const &-> utils::TakeWhileAdapter< typename BasicQuery< World, Alloc, Args... >::iterator, Pred >
Central manager for all component storage (archetype and sparse-set).
Definition manager.hpp:133
Unique identifier for entities with generation counter to handle recycling.
Definition entity.hpp:22
The World class manages entities with their components and systems.
Definition world.hpp:39
Iterator adapter that chains two sequences together.
Iterator adapter that filters elements based on a predicate function.
Iterator adapter that applies a function to each element for observation.
Iterator adapter that transforms each element using a function.
Iterator adapter that skips the first N elements.
Iterator adapter that skips elements while a predicate returns true.
Adapter that yields sliding windows of elements.
Iterator adapter that steps through elements by a specified stride.
Adapter that yields every Nth element from the range.
Iterator adapter that yields only the first N elements.
Iterator adapter that takes elements while a predicate returns true.
static constexpr TypeIndex From() noexcept
Constructs a TypeIndex from a type T.
Adapter that combines two ranges into pairs.
Concept for action functions that process values.
Concept to validate ChainAdapter requirements.
Concept for folder functions that accumulate values.
Concept for inspection functions that observe but don't modify values.
Concept for predicate functions that can be applied to iterator values.
Concept for transformation functions that can be applied to iterator values.
Concept to validate ZipAdapter requirements.
bool EntityHasComponentsCheck(const ComponentManager &manager, Entity entity, std::tuple< Cs... > *)
Definition query.hpp:40
auto FetchComponentsConst(const Archetype &archetype, Entity entity, const ComponentManager &manager, std::tuple< Cs... > *) -> std::tuple< ComponentAccessType_t< Cs >... >
Definition query.hpp:56
auto FetchComponentsMutable(const Archetype &archetype, Entity entity, ComponentManager &manager, std::tuple< Cs... > *) -> std::tuple< ComponentAccessType_t< Cs >... >
Definition query.hpp:47
auto FetchComponent(const Archetype &archetype, Entity entity, ComponentManager &components) -> ComponentAccessType_t< AccessSpec >
Fetches a single component for the current entity from the archetype, returning the appropriate acces...
Definition iterator.hpp:43
auto FetchComponentConst(const Archetype &archetype, Entity entity, const ComponentManager &components) -> ComponentAccessType_t< AccessSpec >
Const-world variant: always returns const access.
Definition iterator.hpp:112
@ kSparseSet
Component is stored in a sparse set.
Definition component.hpp:22
BasicQueryWithEntity< World, Alloc, Args... > MutBasicQueryWithEntity
Definition query.hpp:2228
BasicQueryWithEntity< const World, std::pmr::polymorphic_allocator<>, Args... > PmrReadOnlyBasicQueryWithEntity
Definition query.hpp:2247
BasicQuery< World, std::pmr::polymorphic_allocator<>, Args... > Query
Alias for BasicQuery bound to World with a PMR allocator.
Definition query.hpp:2264
BasicQuery< World, std::pmr::polymorphic_allocator<>, Args... > PmrBasicQuery
Definition query.hpp:2235
BasicQuery< World, Alloc, Args... > MutBasicQuery
Definition query.hpp:2222
BasicQuery< const World, Alloc, Args... > ReadOnlyBasicQuery
Definition query.hpp:2225
utils::TypeIndex ComponentTypeIndex
Type index for components.
Definition component.hpp:14
BasicQuery< const World, std::pmr::polymorphic_allocator<>, Args... > PmrReadOnlyBasicQuery
Definition query.hpp:2239
BasicQueryWithEntity< const World, Alloc, Args... > ReadOnlyBasicQueryWithEntity
Definition query.hpp:2231
BasicQueryWithEntity< World, std::pmr::polymorphic_allocator<>, Args... > PmrBasicQueryWithEntity
Definition query.hpp:2243
typename decltype(GetCallOrApplyResultType< Func, Args... >())::type call_or_apply_result_t
STL namespace.