11#include <userver/utils/assert.hpp>
13USERVER_NAMESPACE_BEGIN
22 static_assert(!std::is_reference_v<T>,
"NotNull does not work with references");
23 static_assert(!std::is_const_v<T>,
"NotNull does not work with const T");
26 constexpr explicit NotNull() =
delete;
28 constexpr explicit NotNull(
const T& u)
31 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null");
34 constexpr explicit NotNull(T&& u)
37 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null");
40 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
41 constexpr explicit NotNull(U&& u)
42 : ptr_(std::forward<U>(u))
44 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null");
47 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U*, T>>>
48 constexpr NotNull(U& u)
49 : ptr_(std::addressof(u))
52 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
53 constexpr NotNull(
const NotNull<U>& other)
54 : ptr_(other.GetBase())
56 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null (moved-from) NotNull");
59 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
60 constexpr NotNull(
NotNull<U>&& other)
61 : ptr_(std::move(other).GetBase())
63 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null (moved-from) NotNull");
66 constexpr NotNull(std::nullptr_t) =
delete;
68 NotNull(
const NotNull& other)
noexcept =
default;
69 NotNull(
NotNull&& other)
noexcept =
default;
74 constexpr NotNull& operator=(std::nullptr_t) =
delete;
76 constexpr const T& GetBase()
const& {
77 UASSERT_MSG(ptr_,
"Trying to access a null (moved-from) NotNull");
81 constexpr T&& GetBase() && {
82 UASSERT_MSG(ptr_,
"Trying to access a null (moved-from) NotNull");
83 return std::move(ptr_);
86 constexpr operator
const T&()
const& {
return GetBase(); }
88 constexpr operator
bool() =
delete;
90 constexpr decltype(
auto) operator->()
const& {
return GetBase(); }
92 constexpr decltype(
auto) operator*()
const& {
return *GetBase(); }
95 constexpr bool operator==(
const NotNull<U>& other)
const& {
96 return GetBase() == other.GetBase();
100 constexpr bool operator!=(
const NotNull<U>& other)
const& {
101 return GetBase() != other.GetBase();
123template <
typename U,
typename... Args,
typename = std::enable_if_t<std::is_constructible_v<U, Args...>>>
125 return SharedRef<U>{std::make_shared<U>(std::forward<Args>(args)...)};
129template <
typename U,
typename... Args,
typename = std::enable_if_t<std::is_constructible_v<U, Args...>>>
131 return UniqueRef<U>{std::make_unique<U>(std::forward<Args>(args)...)};
140struct std::hash<USERVER_NAMESPACE::utils::
NotNull<T>> :
public std::hash<T> {
141 using std::hash<T>::hash;
143 auto operator()(
const USERVER_NAMESPACE::utils::
NotNull<T>& value
144 )
const noexcept(std::is_nothrow_invocable_v<
const std::hash<T>&,
const T&>) {
145 return this->std::hash<T>::operator()(value.GetBase());