userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
optional_ref.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/utils/optional_ref.hpp
4
/// @brief @copybrief utils::OptionalRef
5
6
#
include
<
memory
>
7
#
include
<
optional
>
8
#
include
<
type_traits
>
9
10
#
include
<
boost
/
optional
/
optional_fwd
.
hpp
>
11
12
#
include
<
userver
/
utils
/
assert
.
hpp
>
13
14
USERVER_NAMESPACE_BEGIN
15
16
namespace
utils
{
17
18
/// @ingroup userver_universal userver_containers
19
///
20
/// @brief Class that behaves as a nullable reference. Main difference from the
21
/// pointer - value comparison of pointed values.
22
///
23
/// Initializes from reference to a T or from optional<T>.
24
///
25
/// Once the reference is constructed it can not be changed to point to
26
/// different address.
27
template
<
class
T>
28
class
OptionalRef
{
29
public
:
30
using
value_type = T;
31
32
static_assert
(!std::is_reference<T>::value,
"Do not use a reference for T"
);
33
34
constexpr
OptionalRef()
noexcept
=
default
;
35
constexpr
OptionalRef(std::nullopt_t)
noexcept
{}
36
constexpr
OptionalRef(
const
OptionalRef
&)
noexcept
=
default
;
37
constexpr
OptionalRef
& operator=(
const
OptionalRef
&)
noexcept
=
delete
;
38
39
constexpr
OptionalRef(T& other)
noexcept
: data_(std::addressof(other)) {}
40
41
// Forming a reference to a temporary is forbidden
42
constexpr
explicit
OptionalRef(
const
T&&) =
delete
;
43
44
template
<
typename
U>
45
constexpr
explicit
OptionalRef(
const
std::optional<U>& other)
noexcept
: data_(GetPointer(other)) {}
46
47
template
<
typename
U>
48
constexpr
explicit
OptionalRef(std::optional<U>& other)
noexcept
: data_(GetPointer(other)) {}
49
50
template
<
typename
U>
51
constexpr
explicit
OptionalRef(
const
std::optional<U>&&)
noexcept
{
52
static_assert
(!
sizeof
(U),
"Forming a reference to a temporary"
);
53
}
54
55
template
<
typename
U>
56
constexpr
explicit
OptionalRef(
const
boost::optional<U>& other)
noexcept
: data_(GetPointer(other)) {}
57
58
template
<
typename
U>
59
constexpr
explicit
OptionalRef(boost::optional<U>& other)
noexcept
: data_(GetPointer(other)) {}
60
61
template
<
typename
U>
62
constexpr
explicit
OptionalRef(
const
boost::optional<U>&&)
noexcept
{
63
static_assert
(!
sizeof
(U),
"Forming a reference to a temporary"
);
64
}
65
66
constexpr
bool
has_value()
const
noexcept
{
return
!!data_; }
67
constexpr
explicit
operator
bool
()
const
noexcept
{
return
has_value(); }
68
69
constexpr
T* operator->()
const
{
70
UASSERT
(data_);
71
return
data_;
72
}
73
74
constexpr
T& operator*()
const
{
75
UASSERT
(data_);
76
return
*data_;
77
}
78
79
constexpr
T& value()
const
{
80
if
(!has_value()) {
81
throw
std::bad_optional_access();
82
}
83
84
return
*data_;
85
}
86
87
template
<
typename
U>
88
constexpr
T value_or(U&& default_value)
const
{
89
if
(!has_value()) {
90
return
std::forward<U>(default_value);
91
}
92
93
return
*data_;
94
}
95
96
private
:
97
template
<
class
Optional>
98
static
T* GetPointer(Optional& other)
noexcept
{
99
using
ValueType =
decltype
(*other);
100
static_assert
(
101
std::is_const<T>::value || !std::is_const<ValueType>::value,
102
"Attempt to initialize non-const T from a const optional value"
103
);
104
105
return
other.has_value() ? std::addressof(*other) :
nullptr
;
106
}
107
108
T*
const
data_ =
nullptr
;
109
};
110
111
template
<
class
T,
class
U>
112
constexpr
bool
operator==(
OptionalRef
<T> lhs,
OptionalRef
<U> rhs)
noexcept
{
113
if
(!lhs || !rhs) {
114
return
!lhs && !rhs;
115
}
116
return
*lhs == *rhs;
117
}
118
119
}
// namespace utils
120
121
USERVER_NAMESPACE_END
userver
utils
optional_ref.hpp
Generated on
for userver by
Doxygen
1.17.0