userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
not_null.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/utils/not_null.hpp
4
/// @brief @copybrief utils::NotNull
5
6
#
include
<
functional
>
7
#
include
<
memory
>
8
#
include
<
type_traits
>
9
#
include
<
utility
>
10
11
#
include
<
userver
/
compiler
/
impl
/
lifetime
.
hpp
>
12
#
include
<
userver
/
utils
/
assert
.
hpp
>
13
14
USERVER_NAMESPACE_BEGIN
15
16
namespace
utils
{
17
18
namespace
impl {
19
20
template
<
typename
T>
21
struct
IsStdSharedPtr : std::false_type {};
22
23
template
<
typename
T>
24
struct
IsStdSharedPtr<std::shared_ptr<T>> : std::true_type {};
25
26
}
// namespace impl
27
28
/// @ingroup userver_universal userver_containers
29
///
30
/// @brief Restricts a pointer or smart pointer to only hold non-null values.
31
template
<
typename
T>
32
class
NotNull
{
33
static_assert
(!std::is_reference_v<T>,
"NotNull does not work with references"
);
34
static_assert
(!std::is_const_v<T>,
"NotNull does not work with const T"
);
35
36
public
:
37
constexpr
explicit
NotNull() =
delete
;
38
39
constexpr
explicit
NotNull(
const
T& u)
40
: ptr_(u)
41
{
42
UASSERT_MSG
(ptr_,
"Trying to construct NotNull from null"
);
43
}
44
45
constexpr
explicit
NotNull(T&& u)
46
: ptr_(std::move(u))
47
{
48
UASSERT_MSG
(ptr_,
"Trying to construct NotNull from null"
);
49
}
50
51
template
<
typename
U>
52
requires
std::is_convertible_v<U, T>
53
constexpr
explicit
NotNull(U&& u)
54
: ptr_(std::forward<U>(u))
55
{
56
UASSERT_MSG
(ptr_,
"Trying to construct NotNull from null"
);
57
}
58
59
template
<
typename
U>
60
requires
std::is_convertible_v<U*, T>
61
constexpr
/*implicit*/
NotNull(U& u)
62
: ptr_(std::addressof(u))
63
{}
64
65
template
<
typename
U>
66
requires
std::is_convertible_v<U, T>
67
constexpr
NotNull(
const
NotNull
<U>& other)
68
: ptr_(other.GetBase())
69
{
70
UASSERT_MSG
(ptr_,
"Trying to construct NotNull from null (moved-from) NotNull"
);
71
}
72
73
template
<
typename
U>
74
requires
std::is_convertible_v<U, T>
75
constexpr
NotNull(
NotNull
<U>&& other)
76
: ptr_(std::move(other).GetBase())
77
{
78
UASSERT_MSG
(ptr_,
"Trying to construct NotNull from null (moved-from) NotNull"
);
79
}
80
81
constexpr
NotNull(std::nullptr_t) =
delete
;
82
83
NotNull(
const
NotNull
& other)
noexcept
=
default
;
84
NotNull(
NotNull
&& other)
noexcept
=
default
;
85
86
NotNull
& operator=(
const
NotNull
& other)
noexcept
=
default
;
87
NotNull
& operator=(
NotNull
&& other)
noexcept
=
default
;
88
89
constexpr
NotNull
& operator=(std::nullptr_t) =
delete
;
90
91
constexpr
const
T& GetBase()
const
& {
92
UASSERT_MSG
(ptr_,
"Trying to access a null (moved-from) NotNull"
);
93
return
ptr_;
94
}
95
96
constexpr
T&& GetBase() && {
97
UASSERT_MSG
(ptr_,
"Trying to access a null (moved-from) NotNull"
);
98
return
std::move(ptr_);
99
}
100
101
constexpr
/*implicit*/
operator
const
T&()
const
& {
return
GetBase(); }
102
103
constexpr
/*implicit*/
operator
bool
() =
delete
;
104
105
constexpr
decltype
(
auto
) operator->()
const
& {
return
GetBase(); }
106
107
constexpr
decltype
(
auto
) operator*()
const
& {
return
*GetBase(); }
108
109
constexpr
decltype
(
auto
) operator->()
const
& USERVER_IMPL_LIFETIME_BOUND
110
requires
(!std::is_trivially_copyable_v<T>) && (!impl::IsStdSharedPtr<T>::value)
111
{
112
return
GetBase();
113
}
114
115
constexpr
decltype
(
auto
) operator*()
const
& USERVER_IMPL_LIFETIME_BOUND
116
requires
(!std::is_trivially_copyable_v<T>) && (!impl::IsStdSharedPtr<T>::value)
117
{
118
return
*GetBase();
119
}
120
121
template
<
typename
U>
122
constexpr
bool
operator==(
const
NotNull
<U>& other)
const
& {
123
return
GetBase() == other.GetBase();
124
}
125
126
template
<
typename
U>
127
constexpr
bool
operator!=(
const
NotNull
<U>& other)
const
& {
128
return
GetBase() != other.GetBase();
129
}
130
131
private
:
132
T ptr_;
133
};
134
135
/// @ingroup userver_universal
136
///
137
/// @brief A `std::shared_ptr` that is guaranteed to be not-null.
138
/// @see MakeSharedRef
139
template
<
typename
U>
140
using
SharedRef
=
NotNull
<std::shared_ptr<U>>;
141
142
/// @ingroup userver_universal
143
///
144
/// @brief A `std::unique_ptr` that is guaranteed to be not-null.
145
/// @see MakeUniqueRef
146
template
<
typename
U>
147
using
UniqueRef
=
NotNull
<std::unique_ptr<U>>;
148
149
/// @brief An equivalent of `std::make_shared` for SharedRef.
150
template
<
typename
U,
typename
... Args>
151
requires
std::is_constructible_v<U, Args...>
152
SharedRef
<U>
MakeSharedRef
(Args&&... args) {
153
return
SharedRef
<U>{std::make_shared<U>(std::forward<Args>(args)...)};
154
}
155
156
/// @brief An equivalent of `std::make_unique` for UniqueRef.
157
template
<
typename
U,
typename
... Args>
158
requires
std::is_constructible_v<U, Args...>
159
UniqueRef
<U>
MakeUniqueRef
(Args&&... args) {
160
return
UniqueRef
<U>{std::make_unique<U>(std::forward<Args>(args)...)};
161
}
162
163
}
// namespace utils
164
165
USERVER_NAMESPACE_END
166
167
template
<
typename
T>
168
// NOLINTNEXTLINE(cert-dcl58-cpp)
169
struct
std
::
hash
<USERVER_NAMESPACE::
utils
::
NotNull
<T>> :
public
std::hash<T> {
170
using
std::hash<T>::hash;
171
172
auto
operator()(
const
USERVER_NAMESPACE::
utils
::
NotNull
<T>& value
173
)
const
noexcept
(std::is_nothrow_invocable_v<
const
std::hash<T>&,
const
T&>) {
174
return
this
->std::hash<T>::operator()(value.GetBase());
175
}
176
};
userver
utils
not_null.hpp
Generated on
for userver by
Doxygen
1.17.0