userver: userver/utils/result_store.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
result_store.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/result_store.hpp
4/// @brief @copybrief utils::ResultStore
5
6#include <exception>
7#include <optional>
8#include <stdexcept>
9#include <utility>
10
11USERVER_NAMESPACE_BEGIN
12
13namespace utils {
14
15/// @ingroup userver_universal userver_containers
16///
17/// Simple value/exception store
18template <typename T>
19class ResultStore final {
20 public:
21 /// @brief Retrieves the stored value or rethrows the stored exception
22 /// @throws std::logic_error if no value/exception stored
23 /// @note Can be called at most once.
24 T Retrieve();
25
26 /// @brief Returns the stored value or rethrows the stored exception
27 /// @throws std::logic_error if no value/exception stored
28 const T& Get() const&;
29
30 /// Stores a value
31 void SetValue(const T&);
32
33 /// Stores a value
34 void SetValue(T&&);
35
36 /// Stores an exception
37 void SetException(std::exception_ptr&&) noexcept;
38
39 private:
40 // variant here would require a specialization for exception_ptr
41 std::optional<T> value_;
42 std::exception_ptr exception_;
43};
44
45/// @ingroup userver_universal userver_containers
46///
47/// Simple void value/exception store
48template <>
49class ResultStore<void> final {
50 public:
51 /// @brief Checks value availability or rethrows the stored exception
52 /// @throws std::logic_error if no value/exception stored
53 void Retrieve();
54
55 void Get() const&;
56
57 /// Marks the value as available
58 void SetValue() noexcept;
59
60 /// Stores an exception
61 void SetException(std::exception_ptr&&) noexcept;
62
63 private:
64 bool has_value_{false};
65 std::exception_ptr exception_;
66};
67
68template <typename T>
69T ResultStore<T>::Retrieve() {
70 if (value_) return std::move(*value_);
71 if (exception_) std::rethrow_exception(exception_);
72 throw std::logic_error("result store is not ready");
73}
74
75template <typename T>
76const T& ResultStore<T>::Get() const& {
77 if (value_) return *value_;
78 if (exception_) std::rethrow_exception(exception_);
79 throw std::logic_error("result store is not ready");
80}
81
82template <typename T>
83void ResultStore<T>::SetValue(const T& value) {
84 value_ = value;
85}
86
87template <typename T>
88void ResultStore<T>::SetValue(T&& value) {
89 value_.emplace(std::move(value));
90}
91
92template <typename T>
93void ResultStore<T>::SetException(std::exception_ptr&& exception) noexcept {
94 exception_ = std::move(exception);
95}
96
97// NOLINTNEXTLINE(readability-make-member-function-const)
98inline void ResultStore<void>::Retrieve() { Get(); }
99
100inline void ResultStore<void>::Get() const& {
101 if (has_value_) return;
102 if (exception_) std::rethrow_exception(exception_);
103 throw std::logic_error("result store is not ready");
104}
105
106inline void ResultStore<void>::SetValue() noexcept { has_value_ = true; }
107
108inline void ResultStore<void>::SetException(
109 std::exception_ptr&& exception) noexcept {
110 exception_ = std::move(exception);
111}
112
113} // namespace utils
114
115USERVER_NAMESPACE_END