6#ifndef SL_UTILITY_NULLABLES_ADAPTER_HPP
7#define SL_UTILITY_NULLABLES_ADAPTER_HPP
22 template <
class TAdapted>
28 return *std::forward<TAdapted>(adapted);
31 struct unwrap_adapted_fn
33 template <
class TAdapted>
36 constexpr decltype(
auto)
operator()(
39 noexcept(
noexcept(
unwrap_adapted(std::forward<TAdapted>(adapted))))
88 using adapted_value_t = std::remove_cvref_t<decltype(unwrap_adapted(std::declval<T>()))>;
95 template <
class TAdapted,
class TNull>
97 && std::movable<TAdapted>
101 typename adapted_value_t<TAdapted>;
102 {
unwrap_adapted(std::declval<TAdapted>()) } -> std::convertible_to<adapted_value_t<TAdapted>>;
105 template <
class TNull, adaptable_with<TNull> TAdapted>
106 requires std::same_as<TNull, std::remove_cvref_t<TNull>>
107 && std::same_as<TAdapted, std::remove_cvref_t<TAdapted>>
111namespace sl::nullables::detail
113 template <std::ranges::borrowed_range TRange>
115 constexpr adapter<std::ranges::sentinel_t<TRange>, std::ranges::iterator_t<TRange>> to_nullables_adapter(TRange&& range)
117 return {std::ranges::end(range), std::ranges::begin(range)};
120 struct to_nullables_adapter_fn
122 template <
class TArg>
123 requires requires { adapter{to_nullables_adapter(std::declval<TArg>())}; }
125 constexpr auto operator()(TArg&& arg)
const noexcept(
noexcept(to_nullables_adapter(std::forward<TArg>(arg))))
127 return to_nullables_adapter(std::forward<TArg>(arg));
141 inline constexpr detail::to_nullables_adapter_fn to_nullables_adapter{};
146 concept convertible_to_adapter =
requires
148 adapter{nullables::to_nullables_adapter(std::declval<T>())};
162 template <
class TNull, adaptable_with<TNull> TAdapted>
163 requires std::same_as<TNull, std::remove_cvref_t<TNull>>
164 && std::same_as<TAdapted, std::remove_cvref_t<TAdapted>>
184 ) noexcept(std::is_nothrow_copy_constructible_v<TNull>
185 && std::is_nothrow_copy_constructible_v<TAdapted>)
194 ) noexcept(std::is_nothrow_copy_assignable_v<TNull>
195 && std::is_nothrow_copy_assignable_v<TAdapted>)
205 ) noexcept(std::is_nothrow_move_constructible_v<TNull>
206 && std::is_nothrow_move_constructible_v<TAdapted>)
215 ) noexcept(std::is_nothrow_move_assignable_v<TNull>
216 && std::is_nothrow_move_assignable_v<TAdapted>)
225 template <concepts::initializes<
null_type> TNullArg>
233 noexcept(std::is_nothrow_constructible_v<
null_type, TNullArg>
235 : m_Null{std::forward<TNullArg>(nullArg)},
238 assert(*
this ==
adapter_null &&
"Default constructed adapted_type must comapare equally to the provided null object.");
250 noexcept(std::is_nothrow_default_constructible_v<null_type>
251 && std::is_nothrow_constructible_v<adapted_type, null_type&>)
252 requires std::default_initializable<null_type>
253 && std::constructible_from<adapted_type, null_type&>
261 template <concepts::initializes<null_type> TNullArg>
264 && (!detail::convertible_to_adapter<TNullArg>)
265 && std::constructible_from<adapted_type, const null_type&>
271 noexcept(std::is_nothrow_constructible_v<adapter, std::in_place_t, TNullArg>)
283 template <concepts::initializes<null_type> TNullArg, concepts::initializes<adapted_type> TAdaptedArg>
291 TAdaptedArg&& adaptedArg
293 noexcept(std::is_nothrow_constructible_v<null_type, TNullArg>
294 && std::is_nothrow_constructible_v<adapted_type, TAdaptedArg>)
295 : m_Null{std::forward<TNullArg>(nullArg)},
296 m_Adapted{std::forward<TAdaptedArg>(adaptedArg)}
306 template <detail::convertible_to_adapter TArg>
307 requires concepts::not_same_as<adapter_null_t, std::remove_cvref_t<TArg>>
308 && concepts::not_same_as<in_place_null_t, std::remove_cvref_t<TArg>>
315 && std::is_nothrow_constructible_v<adapter>)
328 noexcept(std::is_nothrow_assignable_v<adapted_type&, null_type&>)
329 requires std::assignable_from<adapted_type&, null_type&>
332 assert(*
this ==
adapter_null &&
"adapted_type must comapare equally to the null object.");
341 template <concepts::assignable_to<adapted_type&> TAdaptedArg>
344 TAdaptedArg&& adaptedArg
346 noexcept(std::is_nothrow_assignable_v<adapted_type&, TAdaptedArg>)
348 m_Adapted = std::forward<TAdaptedArg>(adaptedArg);
360 constexpr decltype(
auto)
operator *()
const &
362 assert(*
this !=
adapter_null &&
"Dereferenced adapted nullable is equally to its null.");
371 constexpr decltype(
auto)
operator *() &
373 assert(*
this !=
adapter_null &&
"Dereferenced adapted nullable is equally to its null.");
382 constexpr decltype(
auto)
operator *() &&
384 assert(*
this !=
adapter_null &&
"Dereferenced adapted nullable is equally to its null.");
399 return m_Adapted == m_Null;
414 template <
class TNull,
class TAdapted>
423 requires requires { to_nullables_adapter(std::declval<T>()); }
427 typename std::remove_cvref_t<decltype(to_nullables_adapter(std::declval<T>()))>::null_type,
428 typename std::remove_cvref_t<decltype(to_nullables_adapter(std::declval<T>()))>::adapted_type
438 template <
class TNull,
class TAdapted>
#define SL_UTILITY_NO_UNIQUE_ADDRESS
Definition: Config.hpp:21
A adapter class, mimic the behaviour of nullable types.
Definition: adapter.hpp:166
constexpr adapter & operator=(const adapter &other) noexcept(std::is_nothrow_copy_assignable_v< TNull > &&std::is_nothrow_copy_assignable_v< TAdapted >)=default
Default copy assignment operator.
constexpr adapter(TNullArg &&nullArg, TAdaptedArg &&adaptedArg) noexcept(std::is_nothrow_constructible_v< null_type, TNullArg > &&std::is_nothrow_constructible_v< adapted_type, TAdaptedArg >)
Constructs the null object and the adapted with the given arguments.
Definition: adapter.hpp:289
TNull null_type
Definition: adapter.hpp:170
constexpr adapter(TArg &&arg) noexcept(noexcept(to_nullables_adapter(std::forward< TArg >(arg))) &&std::is_nothrow_constructible_v< adapter >)
Constructs the adapter with the result of a to_nullables_adapter invocation.
Definition: adapter.hpp:311
constexpr bool operator==(adapter_null_t) const noexcept(concepts::nothrow_weakly_equality_comparable_with< TAdapted, TNull >)
Comparison operator with its adapter_null`object.
Definition: adapter.hpp:394
constexpr ~adapter() noexcept=default
Default destructor.
adapted_value_t< TAdapted > value_type
Definition: adapter.hpp:169
constexpr adapter(TNullArg &&nullArg) noexcept(std::is_nothrow_constructible_v< adapter, std::in_place_t, TNullArg >)
Constructs the null object with the given argument and then constructs the adapted object with the nu...
Definition: adapter.hpp:268
constexpr adapter(adapter_null_t) noexcept(std::is_nothrow_default_constructible_v< null_type > &&std::is_nothrow_constructible_v< adapted_type, null_type & >)
Default constructs the null object and then constructs the adapted object with the null object.
Definition: adapter.hpp:247
TAdapted adapted_type
Definition: adapter.hpp:168
Determines whether a type can be used in unary operator * expressions.
Definition: operators.hpp:725
Checks whether the left-hand-side type is unequal to the right-hand-side type.
Definition: stl_extensions.hpp:69
Checks whether a symmetrical set of operators == and != to compare both types with each other exists ...
Definition: stl_extensions.hpp:140
Checks whether a symmetrical set of operators == and != to compare both types with each other exists.
Definition: stl_extensions.hpp:124
Determines whether the given adapted and null type satisfy the requirements to be used within a adapt...
Definition: adapter.hpp:96
std::remove_cvref_t< decltype(unwrap_adapted(std::declval< T >()))> adapted_value_t
Definition: adapter.hpp:88
adapter(TNull, TAdapted) -> adapter< TNull, TAdapted >
Deduction guide.
adapter(T &&t) -> adapter< typename std::remove_cvref_t< decltype(to_nullables_adapter(std::declval< T >()))>::null_type, typename std::remove_cvref_t< decltype(to_nullables_adapter(std::declval< T >()))>::adapted_type >
Deduction guide, which makes use of to_nullables_adapter customization point.
constexpr in_place_null_t in_place_null
Tag object for adapters, which can be used to disambiguate the construction with just a null-object.
Definition: adapter.hpp:85
constexpr adapter_null_t adapter_null
Dedicated null object for adapters.
Definition: adapter.hpp:69
constexpr detail::to_nullables_adapter_fn to_nullables_adapter
Converts the given argument to a adapter object.
Definition: adapter.hpp:141
Definition: adapter.hpp:19
constexpr detail::unwrap_adapted_fn unwrap_adapted
Definition: adapter.hpp:46
Dedicated null type for adapters.
Definition: adapter.hpp:62
Tag type for adapters, which can be used to disambiguate the construction with just a null-object.
Definition: adapter.hpp:77
adapted_value_t< TAdapted > value_type
Definition: adapter.hpp:441
The main trait, which may be specialized from.
Definition: base.hpp:97