userver: userver/utils/shared_readable_ptr.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
shared_readable_ptr.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/shared_readable_ptr.hpp
4/// @brief @copybrief utils::SharedReadablePtr
5
6#include <memory>
7#include <type_traits>
8
9USERVER_NAMESPACE_BEGIN
10
11namespace utils {
12
13/// @ingroup userver_universal userver_containers
14///
15/// @brief `std::shared_ptr<const T>` wrapper that makes sure that the pointer
16/// is stored before dereferencing. Protects from dangling references:
17/// @code
18/// // BAD! Result of `cache.Get()` may be destroyed after the invocation.
19/// const auto& snapshot = *cache.Get();
20/// @endcode
21template <typename T>
22class SharedReadablePtr final {
23 static_assert(!std::is_const_v<T>,
24 "SharedReadablePtr already adds `const` to `T`");
25 static_assert(!std::is_reference_v<T>,
26 "SharedReadablePtr does not work with references");
27
28 public:
29 using Base = std::shared_ptr<const T>;
30 using MutableBase = std::shared_ptr<T>;
31 using Weak = typename Base::weak_type;
32 using Unique = std::unique_ptr<const T>;
33 using element_type = T;
34
35 SharedReadablePtr(const SharedReadablePtr& ptr) = default;
36 SharedReadablePtr(SharedReadablePtr&& ptr) noexcept = default;
37
38 constexpr SharedReadablePtr(std::nullptr_t) noexcept : base_(nullptr) {}
39
40 SharedReadablePtr& operator=(const SharedReadablePtr& ptr) = default;
41 SharedReadablePtr& operator=(SharedReadablePtr&& ptr) noexcept = default;
42
43 SharedReadablePtr(const Base& ptr) noexcept : base_(ptr) {}
44
45 SharedReadablePtr(Base&& ptr) noexcept : base_(std::move(ptr)) {}
46
47 SharedReadablePtr(const MutableBase& ptr) noexcept : base_(ptr) {}
48
49 SharedReadablePtr(MutableBase&& ptr) noexcept : base_(std::move(ptr)) {}
50
51 SharedReadablePtr(Unique&& ptr) noexcept : base_(std::move(ptr)) {}
52
53 SharedReadablePtr& operator=(const Base& ptr) {
54 base_ = ptr;
55 return *this;
56 }
57
58 SharedReadablePtr& operator=(Base&& ptr) noexcept {
59 base_ = std::move(ptr);
60 return *this;
61 }
62
63 SharedReadablePtr& operator=(const MutableBase& ptr) noexcept {
64 base_ = ptr;
65 return *this;
66 }
67
68 SharedReadablePtr& operator=(MutableBase&& ptr) noexcept {
69 base_ = std::move(ptr);
70 return *this;
71 }
72
73 SharedReadablePtr& operator=(std::nullptr_t) noexcept {
74 Reset();
75 return *this;
76 }
77
78 const T* Get() const& noexcept { return base_.get(); }
79
80 const T& operator*() const& noexcept { return *base_; }
81
82 const T& operator*() && { ReportMisuse(); }
83
84 const T* operator->() const& noexcept { return base_.get(); }
85
86 const T* operator->() && { ReportMisuse(); }
87
88 operator const Base&() const& noexcept { return base_; }
89
90 operator const Base&() && { ReportMisuse(); }
91
92 operator Weak() const& noexcept { return base_; }
93
94 operator Weak() && { ReportMisuse(); }
95
96 explicit operator bool() const noexcept { return !!base_; }
97
98 bool operator==(const SharedReadablePtr<T>& other) const {
99 return base_ == other.base_;
100 }
101
102 bool operator!=(const SharedReadablePtr<T>& other) const {
103 return !(*this == other);
104 }
105
106 void Reset() noexcept { base_.reset(); }
107
108 private:
109 [[noreturn]] static void ReportMisuse() {
110 static_assert(!sizeof(T), "keep the pointer before using, please");
111 }
112
113 Base base_;
114};
115
116template <typename T>
117bool operator==(const SharedReadablePtr<T>& ptr, std::nullptr_t) {
118 return !ptr;
119}
120
121template <typename T>
122bool operator==(std::nullptr_t, const SharedReadablePtr<T>& ptr) {
123 return !ptr;
124}
125
126template <typename T>
127bool operator!=(const SharedReadablePtr<T>& ptr, std::nullptr_t) {
128 return !(ptr == nullptr);
129}
130
131template <typename T>
132bool operator!=(std::nullptr_t, const SharedReadablePtr<T>& ptr) {
133 return !(nullptr == ptr);
134}
135
136template <typename T, typename... Args>
137SharedReadablePtr<T> MakeSharedReadable(Args&&... args) {
138 return SharedReadablePtr<T>{std::make_shared<T>(std::forward<Args>(args)...)};
139}
140
141} // namespace utils
142
143USERVER_NAMESPACE_END