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>);
26 constexpr explicit NotNull() =
delete;
28 constexpr explicit NotNull(
const T& u) : ptr_(u) {
UASSERT_MSG(ptr_,
"Trying to construct NotNull from null"); }
30 constexpr explicit NotNull(T&& u) : ptr_(std::move(u)) {
31 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null");
34 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
35 constexpr explicit NotNull(U&& u) : ptr_(std::forward<U>(u)) {
36 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null");
39 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U*, T>>>
40 constexpr NotNull(U& u) : ptr_(std::addressof(u)) {}
42 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
43 constexpr NotNull(
const NotNull<U>& other) : ptr_(other.GetBase()) {
44 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null (moved-from) NotNull");
47 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U, T>>>
48 constexpr NotNull(
NotNull<U>&& other) : ptr_(std::move(other).GetBase()) {
49 UASSERT_MSG(ptr_,
"Trying to construct NotNull from null (moved-from) NotNull");
52 constexpr NotNull(std::nullptr_t) =
delete;
54 NotNull(
const NotNull& other)
noexcept =
default;
55 NotNull(
NotNull&& other)
noexcept =
default;
60 constexpr NotNull& operator=(std::nullptr_t) =
delete;
62 constexpr const T& GetBase()
const& {
63 UASSERT_MSG(ptr_,
"Trying to access a null (moved-from) NotNull");
67 constexpr T&& GetBase() && {
68 UASSERT_MSG(ptr_,
"Trying to access a null (moved-from) NotNull");
69 return std::move(ptr_);
72 constexpr operator
const T&()
const& {
return GetBase(); }
74 constexpr operator
bool() =
delete;
76 constexpr decltype(
auto) operator->()
const& {
return GetBase(); }
78 constexpr decltype(
auto) operator*()
const& {
return *GetBase(); }
81 constexpr bool operator==(
const NotNull<U>& other)
const& {
82 return GetBase() == other.GetBase();
86 constexpr bool operator!=(
const NotNull<U>& other)
const& {
87 return GetBase() != other.GetBase();
99using SharedRef =
NotNull<std::shared_ptr<U>>;
109template <
typename U,
typename... Args>
111 return SharedRef<U>{std::make_shared<U>(std::forward<Args>(args)...)};
115template <
typename U,
typename... Args>
117 return UniqueRef<U>{std::make_unique<U>(std::forward<Args>(args)...)};
126struct std::hash<USERVER_NAMESPACE::
utils::
NotNull<T>> :
public std::hash<T> {
127 using std::hash<T>::hash;
129 auto operator()(
const USERVER_NAMESPACE::
utils::
NotNull<T>& value)
const
130 noexcept(std::is_nothrow_invocable_v<
const std::hash<T>&,
const T&>) {
131 return this->std::hash<T>::operator()(value.GetBase());