userver: userver/utils/checked_pointer.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
checked_pointer.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/checked_pointer.hpp
4/// @brief @copybrief utils::CheckedPtr
5
6#include <cstdlib>
7
8#include <userver/utils/assert.hpp>
9
10USERVER_NAMESPACE_BEGIN
11
12namespace utils {
13
14namespace impl {
15[[noreturn]] void ThrowEmptyCheckedPointerException();
16}
17
18/// @ingroup userver_universal userver_containers
19///
20/// @brief Utility template for returning a pointer to an object that
21/// is owned by someone else; throws std::runtime_error if nullptr is stored
22///
23/// Useful for returning cache search result.
24template <typename T>
26public:
27 /* implicit */ constexpr CheckedPtr(std::nullptr_t) noexcept : ptr_{nullptr} {}
28 explicit constexpr CheckedPtr(T* ptr) noexcept : ptr_{ptr} {}
29
30 explicit constexpr operator bool() const noexcept {
31#ifndef NDEBUG
32 checked_ = true;
33#endif
34 return ptr_;
35 }
36
37 T* Get() const& {
38 CheckPointer();
39 return ptr_;
40 }
41
42 T* Get() && { RvalueDisabled(); }
43
44 T* operator->() const& { return Get(); }
45 T* operator->() && { RvalueDisabled(); }
46
47 T& operator*() const& { return *Get(); }
48 T& operator*() && { RvalueDisabled(); }
49
50private:
51 [[noreturn]] void RvalueDisabled() {
52 static_assert(!sizeof(T), "Don't use temporary CheckedPtr, check it first, then dereference");
53 std::abort();
54 }
55 void CheckPointer() const {
56#ifndef NDEBUG
57 UASSERT_MSG(checked_, "CheckedPtr contents were not checked before dereferencing");
58#endif
59 if (!ptr_) impl::ThrowEmptyCheckedPointerException();
60 }
61#ifndef NDEBUG
62 mutable bool checked_{false};
63#endif
64 T* ptr_;
65};
66
67template <typename T>
68class CheckedPtr<T&> {
69 static_assert(!sizeof(T), "Don't use CheckedPointer for references");
70};
71
72template <typename T>
73constexpr CheckedPtr<T> MakeCheckedPtr(T* ptr) noexcept {
74 return CheckedPtr<T>{ptr};
75}
76
77} // namespace utils
78
79USERVER_NAMESPACE_END