8#include <reflection-cpp/reflection.hpp>
22template <
typename ReferencedRecordT,
typename ThroughRecordT>
38 using iterator = ReferencedRecordList::iterator;
52 [[nodiscard]] std::
size_t Count() const;
55 [[nodiscard]] std::
size_t IsEmpty() const;
95 std::weak_ordering operator<=>(
HasManyThrough const& other) const noexcept = default;
99 std::function<size_t()> count;
107 _loader = std::move(loader);
113 _count = std::nullopt;
114 _records = std::nullopt;
123 template <
typename Callable>
124 void Each(Callable
const& callable)
126 if (!_records && _loader.each)
128 _loader.each(callable);
132 for (
auto const& record:
All())
143 _records = _loader.all();
151 std::optional<size_t> _count;
152 std::optional<ReferencedRecordList> _records;
156constexpr bool IsHasManyThrough = IsSpecializationOf<HasManyThrough, T>;
158template <
typename ReferencedRecordT,
typename ThroughRecordT>
160 ThroughRecordT>::All()
165 return _records.value();
168template <
typename ReferencedRecordT,
typename ThroughRecordT>
170 ThroughRecordT>::All() noexcept
174 return _records.value();
177template <
typename ReferencedRecordT,
typename ThroughRecordT>
181 _records = { std::move(records) };
182 _count = _records->size();
186template <
typename ReferencedRecordT,
typename ThroughRecordT>
190 return _records->size();
195 return _count.value_or(0);
198template <
typename ReferencedRecordT,
typename ThroughRecordT>
204template <
typename ReferencedRecordT,
typename ThroughRecordT>
207 ThroughRecordT>::At(std::size_t index)
const
209 return *All().at(index);
212template <
typename ReferencedRecordT,
typename ThroughRecordT>
216 return *All().at(index);
219template <
typename ReferencedRecordT,
typename ThroughRecordT>
222 ThroughRecordT>::operator[](std::size_t index)
const
224 return *All()[index];
227template <
typename ReferencedRecordT,
typename ThroughRecordT>
231 return *All()[index];
234template <
typename ReferencedRecordT,
typename ThroughRecordT>
236 ThroughRecordT>::begin() noexcept
238 return All().begin();
241template <
typename ReferencedRecordT,
typename ThroughRecordT>
247template <
typename ReferencedRecordT,
typename ThroughRecordT>
251 return All().begin();
254template <
typename ReferencedRecordT,
typename ThroughRecordT>
This API represents a many-to-many relationship between two records through a third record.
void Each(Callable const &callable)
Iterates over all records in this relationship.
std::size_t Count() const
Retrieves the number of records in this relationship.
ReferencedRecordList::iterator iterator
Iterator type for the list of records.
ReferencedRecord const & operator[](std::size_t index) const
Retrieves the record at the given index.
iterator begin() noexcept
Returns an iterator to the beginning of the record list.
std::vector< std::shared_ptr< ReferencedRecord > > ReferencedRecordList
The list of records on the "many" side of the relationship.
ReferencedRecordList const & All() const noexcept
Retrieves the list of loaded records.
void Reload()
Reloads the records from the database.
void SetAutoLoader(Loader loader) noexcept
Used internally to configure on-demand loading of the records.
ReferencedRecord const & At(std::size_t index) const
Retrieves the record at the given index.
ThroughRecordT ThroughRecord
The record type of the "through" side of the relationship.
std::size_t IsEmpty() const
Checks if this relationship is empty.
iterator end() noexcept
Returns an iterator to the end of the record list.
ReferencedRecordList::const_iterator const_iterator
Const iterator type for the list of records.
ReferencedRecordList & Emplace(ReferencedRecordList &&records) noexcept
Emplaces the given list of records into this relationship.
ReferencedRecord value_type
Value type for range-based iteration.
ReferencedRecordT ReferencedRecord
The record type of the "many" side of the relationship.
Represents an error when a record is required to be loaded but is not.