userver: userver/utils/result_store.hpp Source File
Loading...
Searching...
No Matches
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