Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
Throw.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include <typeinfo> // needed for use of typeid()
5
7
8 /*
9 * Forward declared, not included: Exceptions.h includes THIS file, and reaching the activity API from here
10 * would close the loop (Activity.h -> Characters/String.h -> String.inl -> Throw.h). Both helpers take only
11 * an ExceptionStringHelper&, so a forward declaration is enough; they are defined in Exceptions.cpp.
12 */
13 class ExceptionStringHelper;
14 namespace Private_ {
15 bool ShouldImbueActivities_ (const ExceptionStringHelper& e) noexcept;
16 void ImbueCurrentActivities_ (ExceptionStringHelper* e);
17 }
18
19 namespace Private_ {
20// avoid header dependencies on Debug/BackTrace and no Characters/String
21#if qStroika_Foundation_Execution_Throw_TraceThrowpointBacktrace
22 string GetBT_s ();
23 wstring GetBT_ws ();
24#endif
25 string ToString_ (const type_info&);
26 template <typename T>
27 inline string ToString_ (const T& t)
28 {
29 if constexpr (is_convertible_v<T, const exception&>) {
30 return t.what ();
31 }
32 else {
33 return ToString_ (typeid (T)); // exact match preferred over template
34 }
35 }
36
37#if qStroika_Foundation_Debug_DefaultTracingOn
38 void JustDbgTrace_ (const string& msg);
39 void JustDbgTrace_ (const wstring& msg);
40 void ThrowingExceptionDbgTrace_ (const string& msg);
41 void ThrowingExceptionDbgTrace_ (const wstring& msg);
42 void ReThrowingExceptionDbgTrace_ (const string& msg);
43 void ReThrowingExceptionDbgTrace_ (const wstring& msg = {});
44#endif
45
46 }
47
48 /*
49 ********************************************************************************
50 ***************************** Execution::Throw *********************************
51 ********************************************************************************
52 */
53 template <typename T>
54 [[noreturn]] inline void Throw (T&& e2Throw)
55 {
56 static_assert (is_convertible_v<remove_cvref_t<T>*, exception*>);
57 if constexpr (derived_from<remove_cvref_t<T>, ExceptionStringHelper>) {
58 // Use the current Activity stack if not already specified in the e2Throw
59 if (Private_::ShouldImbueActivities_ (e2Throw)) [[unlikely]] {
60 remove_cvref_t<T> tmp = e2Throw;
61 Private_::ImbueCurrentActivities_ (&tmp);
62#if qStroika_Foundation_Debug_DefaultTracingOn
63 Private_::ThrowingExceptionDbgTrace_ (Private_::ToString_ (tmp));
64#endif
65 throw tmp;
66 }
67 }
68#if qStroika_Foundation_Debug_DefaultTracingOn
69 Private_::ThrowingExceptionDbgTrace_ (Private_::ToString_ (forward<T> (e2Throw)));
70#endif
71 throw e2Throw;
72 }
73 template <typename T>
74 [[noreturn]] inline void Throw (T&& e2Throw, [[maybe_unused]] const char* traceMsg)
75 {
76 static_assert (is_convertible_v<remove_cvref_t<T>*, exception*>);
77#if qStroika_Foundation_Debug_DefaultTracingOn
78 Private_::JustDbgTrace_ (traceMsg);
79#endif
80 // deliberately via the 1-arg overload: that is what emits the "Throwing exception" trace (and backtrace);
81 // throwing directly here would lose it. NB: this used to be about a per-type Throw<> specialization
82 // which translated exception types (Platform::Windows::Exception ERROR_OUTOFMEMORY -> bad_alloc, etc);
83 // no such specialization has existed for some time - @see Execution::ThrowError for where translation
84 // actually happens now.
85 Throw (forward<T> (e2Throw));
86 }
87 template <typename T>
88 [[noreturn]] inline void Throw (T&& e2Throw, [[maybe_unused]] const wchar_t* traceMsg)
89 {
90 static_assert (is_convertible_v<remove_cvref_t<T>*, exception*>);
91#if qStroika_Foundation_Debug_DefaultTracingOn
92 Private_::JustDbgTrace_ (traceMsg);
93#endif
94 // deliberately via the 1-arg overload: that is what emits the "Throwing exception" trace (and backtrace);
95 // throwing directly here would lose it. NB: this used to be about a per-type Throw<> specialization
96 // which translated exception types (Platform::Windows::Exception ERROR_OUTOFMEMORY -> bad_alloc, etc);
97 // no such specialization has existed for some time - @see Execution::ThrowError for where translation
98 // actually happens now.
99 Throw (forward<T> (e2Throw));
100 }
101
102 /*
103 ********************************************************************************
104 ***************************** Execution::ReThrow *******************************
105 ********************************************************************************
106 */
107 [[noreturn]] inline void ReThrow ()
108 {
109#if qStroika_Foundation_Debug_DefaultTracingOn
110 Private_::ReThrowingExceptionDbgTrace_ ();
111#endif
112 throw;
113 }
114 [[noreturn]] inline void ReThrow (const exception_ptr& e)
115 {
116#if qStroika_Foundation_Debug_DefaultTracingOn
117 Private_::ReThrowingExceptionDbgTrace_ ();
118#endif
119 rethrow_exception (e);
120 }
121 [[noreturn]] inline void ReThrow ([[maybe_unused]] const char* traceMsg)
122 {
123#if qStroika_Foundation_Debug_DefaultTracingOn
124 Private_::ReThrowingExceptionDbgTrace_ (traceMsg);
125#endif
126 throw;
127 }
128 [[noreturn]] inline void ReThrow (const exception_ptr& e, [[maybe_unused]] const char* traceMsg)
129 {
130#if qStroika_Foundation_Debug_DefaultTracingOn
131 Private_::ReThrowingExceptionDbgTrace_ (traceMsg);
132#endif
133 rethrow_exception (e);
134 }
135 [[noreturn]] inline void ReThrow ([[maybe_unused]] const wchar_t* traceMsg)
136 {
137#if qStroika_Foundation_Debug_DefaultTracingOn
138 Private_::ReThrowingExceptionDbgTrace_ (traceMsg);
139#endif
140 throw;
141 }
142 [[noreturn]] inline void ReThrow (const exception_ptr& e, [[maybe_unused]] const wchar_t* traceMsg)
143 {
144#if qStroika_Foundation_Debug_DefaultTracingOn
145 Private_::ReThrowingExceptionDbgTrace_ (traceMsg);
146#endif
147 rethrow_exception (e);
148 }
149
150 /*
151 ********************************************************************************
152 *************************** Execution::ThrowIfNull *****************************
153 ********************************************************************************
154 */
155 template <equality_comparable_with<nullptr_t> T, typename E>
156 inline void ThrowIfNull (const T& p, const E& e)
157 {
158 if (p == nullptr) [[unlikely]] {
159 Throw (e, "ThrowIfNull (nullptr) - throwing bad_alloc"); // todo fix trace message to depend on 'E'
160 }
161 }
162 template <equality_comparable_with<nullptr_t> T>
163 inline void ThrowIfNull (const T& p)
164 {
165 static const bad_alloc kException_;
166 ThrowIfNull (p, kException_);
167 }
168 template <Common::Weak_Equality_Comparable_With<nullopt_t> T, typename E>
169 inline void ThrowIfNull (const T& p, const E& e)
170 requires (not equality_comparable_with<nullptr_t, T>)
171 {
172 if (p == nullopt) [[unlikely]] {
173 Throw (e, "ThrowIfNull (nullopt) - throwing bad_optional_access"); // todo fix trace message to depend on 'E'
174 }
175 }
176 template <Common::Weak_Equality_Comparable_With<nullopt_t> T>
177 inline void ThrowIfNull (const T& p)
178 requires (not equality_comparable_with<nullptr_t, T>)
179 {
180 static const bad_optional_access kException_;
181 ThrowIfNull (p, kException_);
182 }
183
184 /*
185 ********************************************************************************
186 *************************** Execution::ThrowIfFailed ***************************
187 ********************************************************************************
188 */
189 template <typename EXPECTED>
190 inline auto ThrowIfFailed (const EXPECTED& e) -> typename EXPECTED::value_type
191 {
192 if (e) {
193 return e.value ();
194 }
195 else {
196 Throw (e.error ());
197 }
198 }
199
200}
void Throw(T &&e2Throw)
like the builtin C++ 'throw', but stamps in the current Activity context and does helpful,...
Definition Throw.inl:54
void ThrowIfNull(const Private_::ConstVoidStar &p, const HRESULT &hr)
Template specialization for ThrowIfNull (), for thing being thrown HRESULT - really throw HRESULTErro...
EXPECTED::value_type ThrowIfFailed(const EXPECTED &e)
Definition Throw.inl:190