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]]
bool 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.
bool IsEmpty() const
Checks if this relationship is empty.
ThroughRecordT ThroughRecord
The record type of the "through" side of the relationship.
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.