11#include <userver/utils/assert.hpp>
13USERVER_NAMESPACE_BEGIN
22 static_assert(!std::is_reference_v<T>,
23 "NotNull does not work with references");
24 static_assert(!std::is_const_v<T>);
27 constexpr explicit NotNull() =
delete;
29 constexpr explicit NotNull(
const T& u) : ptr_(u) {
30 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null");
33 constexpr explicit NotNull(T&& u) : ptr_(std::move(u)) {
34 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null");
38 typename = std::enable_if_t<std::is_convertible_v<U, T>>>
39 constexpr explicit NotNull(U&& u) : ptr_(std::forward<U>(u)) {
40 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null");
44 typename = std::enable_if_t<std::is_convertible_v<U*, T>>>
45 constexpr NotNull(U& u) : ptr_(std::addressof(u)) {}
48 typename = std::enable_if_t<std::is_convertible_v<U, T>>>
49 constexpr NotNull(
const NotNull<U>& other) : ptr_(other.GetBase()) {
51 "Trying to construct NotNull from null (moved-from) NotNull");
55 typename = std::enable_if_t<std::is_convertible_v<U, T>>>
56 constexpr NotNull(
NotNull<U>&& other) : ptr_(std::move(other).GetBase()) {
58 "Trying to construct NotNull from null (moved-from) NotNull");
61 constexpr NotNull(std::nullptr_t) =
delete;
63 NotNull(
const NotNull& other)
noexcept =
default;
64 NotNull(
NotNull&& other)
noexcept =
default;
69 constexpr NotNull& operator=(std::nullptr_t) =
delete;
71 constexpr const T& GetBase()
const& {
72 UASSERT_MSG(ptr_,
"Trying to access a null (moved-from) NotNull");
76 constexpr T&& GetBase() && {
77 UASSERT_MSG(ptr_,
"Trying to access a null (moved-from) NotNull");
78 return std::move(ptr_);
81 constexpr operator
const T&()
const& {
return GetBase(); }
83 constexpr operator
bool() =
delete;
85 constexpr decltype(
auto) operator->()
const& {
return GetBase(); }
87 constexpr decltype(
auto) operator*()
const& {
return *GetBase(); }
90 constexpr bool operator==(
const NotNull<U>& other)
const& {
91 return GetBase() == other.GetBase();
95 constexpr bool operator!=(
const NotNull<U>& other)
const& {
96 return GetBase() != other.GetBase();
115using UniqueRef = NotNull<std::unique_ptr<U>>;
118template <
typename U,
typename... Args>
120 return SharedRef<U>{std::make_shared<U>(std::forward<Args>(args)...)};
124template <
typename U,
typename... Args>
126 return UniqueRef<U>{std::make_unique<U>(std::forward<Args>(args)...)};
135struct std::hash<USERVER_NAMESPACE::utils::
NotNull<T>> :
public std::hash<T> {
136 using std::hash<T>::hash;
138 auto operator()(
const USERVER_NAMESPACE::utils::
NotNull<T>& value)
const
139 noexcept(std::is_nothrow_invocable_v<
const std::hash<T>&,
const T&>) {
140 return this->std::hash<T>::operator()(value.GetBase());