|
17 | 17 | namespace Lightweight |
18 | 18 | { |
19 | 19 |
|
| 20 | + |
| 21 | +/// @brief Helper function to use with std::optional<std::reference_wrapper<T>> |
| 22 | +/// like this .transform(Unwrap).value_or({}) |
| 23 | +auto inline Unwrap = [](auto v) { return v.get(); }; |
| 24 | + |
20 | 25 | /// @brief Represents a one-to-one relationship. |
21 | 26 | /// |
22 | 27 | /// The `TheReferencedField` parameter is the field in the other record that references the current record, |
@@ -180,45 +185,86 @@ class BelongsTo |
180 | 185 |
|
181 | 186 | ~BelongsTo() noexcept = default; |
182 | 187 |
|
183 | | - // clang-format off |
184 | | - |
185 | 188 | /// Marks the field as modified or unmodified. |
186 | | - LIGHTWEIGHT_FORCE_INLINE constexpr void SetModified(bool value) noexcept { _modified = value; } |
| 189 | + LIGHTWEIGHT_FORCE_INLINE constexpr void SetModified(bool value) noexcept |
| 190 | + { |
| 191 | + _modified = value; |
| 192 | + } |
187 | 193 |
|
188 | 194 | /// Checks if the field is modified. |
189 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr bool IsModified() const noexcept { return _modified; } |
| 195 | + [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr bool IsModified() const noexcept |
| 196 | + { |
| 197 | + return _modified; |
| 198 | + } |
190 | 199 |
|
191 | 200 | /// Retrieves the reference to the value of the field. |
192 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ValueType const& Value() const noexcept { return _referencedFieldValue; } |
| 201 | + [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ValueType const& Value() const noexcept |
| 202 | + { |
| 203 | + return _referencedFieldValue; |
| 204 | + } |
193 | 205 |
|
194 | 206 | /// Retrieves the mutable reference to the value of the field. |
195 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ValueType& MutableValue() noexcept { return _referencedFieldValue; } |
196 | | - |
197 | | - /// Retrieves a record from the relationship. |
198 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord& Record() { RequireLoaded(); return *_record; } |
199 | | - |
200 | | - /// Retrieves an immutable reference to the record from the relationship. |
201 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord const& Record() const { RequireLoaded(); return *_record; } |
| 207 | + [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ValueType& MutableValue() noexcept |
| 208 | + { |
| 209 | + return _referencedFieldValue; |
| 210 | + } |
202 | 211 |
|
203 | | - /// Retrieves the record from the relationship. |
204 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord& operator*() noexcept { RequireLoaded(); return *_record; } |
| 212 | + /// Retrieves a record from the relationship. When the record is not optional |
| 213 | + template <typename Self> |
| 214 | + [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord const& Record(this Self&& self) |
| 215 | + requires(IsMandatory) |
| 216 | + { |
| 217 | + self.RequireLoaded(); |
| 218 | + return *self._record; |
| 219 | + } |
205 | 220 |
|
206 | | - /// Retrieves the record from the relationship. |
207 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord const& operator*() const noexcept { RequireLoaded(); return *_record; } |
| 221 | + /// Retrieves a record from the relationship. When the record is optional |
| 222 | + /// we return object similar to std::optional<ReferencedRecord&> |
| 223 | + template <typename Self> |
| 224 | + [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr decltype(auto) Record(this Self&& self) |
| 225 | + requires(IsOptional) |
| 226 | + { |
| 227 | + self.RequireLoaded(); |
| 228 | + return [&]() -> std::optional<std::reference_wrapper<ReferencedRecord>> { |
| 229 | + if (self._record) |
| 230 | + return *self._record; |
| 231 | + return std::nullopt; |
| 232 | + }(); |
| 233 | + // .transform([](auto v) { return v.get(); }); |
| 234 | + // requires at least clang-20 |
| 235 | + } |
208 | 236 |
|
209 | 237 | /// Retrieves the record from the relationship. |
210 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord* operator->() { RequireLoaded(); return _record.get(); } |
| 238 | + /// Only available when the relationship is mandatory. |
| 239 | + template <typename Self> |
| 240 | + [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord& operator*(this Self&& self) noexcept |
| 241 | + requires(IsMandatory) |
| 242 | + { |
| 243 | + self.RequireLoaded(); |
| 244 | + return *self._record; |
| 245 | + } |
211 | 246 |
|
212 | 247 | /// Retrieves the record from the relationship. |
213 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord const* operator->() const { RequireLoaded(); return _record.get(); } |
| 248 | + /// Only available when the relationship is mandatory. |
| 249 | + template <typename Self> |
| 250 | + [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord* operator->(this Self&& self) |
| 251 | + requires(IsMandatory) |
| 252 | + { |
| 253 | + self.RequireLoaded(); |
| 254 | + return self._record.get(); |
| 255 | + } |
214 | 256 |
|
215 | 257 | /// Checks if the field value is NULL. |
216 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr bool operator!() const noexcept { return !_referencedFieldValue; } |
| 258 | + [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr bool operator!() const noexcept |
| 259 | + { |
| 260 | + return !_referencedFieldValue; |
| 261 | + } |
217 | 262 |
|
218 | 263 | /// Checks if the field value is not NULL. |
219 | | - [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr explicit operator bool() const noexcept { return static_cast<bool>(_referencedFieldValue); } |
220 | | - |
221 | | - // clang-format on |
| 264 | + [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr explicit operator bool() const noexcept |
| 265 | + { |
| 266 | + return static_cast<bool>(_referencedFieldValue); |
| 267 | + } |
222 | 268 |
|
223 | 269 | /// Emplaces a record into the relationship. This will mark the relationship as loaded. |
224 | 270 | [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr ReferencedRecord& EmplaceRecord() |
@@ -293,8 +339,9 @@ class BelongsTo |
293 | 339 | } |
294 | 340 | } |
295 | 341 |
|
296 | | - if (!_loaded) |
297 | | - throw SqlRequireLoadedError(Reflection::TypeNameOf<std::remove_cvref_t<decltype(*this)>>); |
| 342 | + if constexpr (IsMandatory) |
| 343 | + if (!_loaded) |
| 344 | + throw SqlRequireLoadedError(Reflection::TypeNameOf<std::remove_cvref_t<decltype(*this)>>); |
298 | 345 | } |
299 | 346 |
|
300 | 347 | ValueType _referencedFieldValue {}; |
|
0 commit comments