@@ -116,9 +116,10 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
116116#ifdef _MSC_VER
117117 __declspec (noreturn)
118118#elif defined(__GNUC__) || defined(__clang__)
119- __attribute__ ((noreturn))
119+ __attribute__ ((noreturn))
120120#endif
121- void _ub ()
121+ void
122+ _ub ()
122123 {
123124 assert (false ); // NOLINT
124125#if defined(__GNUC__) || defined(__clang__)
@@ -147,25 +148,33 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
147148
148149 // ! Implicit result converting move constructor
149150 SYSTEM_ERROR2_TEMPLATE (class U )
150- SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>)) constexpr result (result<U> &&o, _implicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
151+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>))
152+ constexpr result (result<U> &&o,
153+ _implicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
151154 : _base(std::move(o))
152155 {
153156 }
154157 // ! Implicit result converting copy constructor
155158 SYSTEM_ERROR2_TEMPLATE (class U )
156- SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>)) constexpr result (const result<U> &o, _implicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
159+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>))
160+ constexpr result (const result<U> &o,
161+ _implicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
157162 : _base(o)
158163 {
159164 }
160165 // ! Explicit result converting move constructor
161166 SYSTEM_ERROR2_TEMPLATE (class U )
162- SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>)) constexpr explicit result (result<U> &&o, _explicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
167+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>))
168+ constexpr explicit result (result<U> &&o,
169+ _explicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
163170 : _base(std::move(o))
164171 {
165172 }
166173 // ! Explicit result converting copy constructor
167174 SYSTEM_ERROR2_TEMPLATE (class U )
168- SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>)) constexpr explicit result (const result<U> &o, _explicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
175+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>))
176+ constexpr explicit result (const result<U> &o,
177+ _explicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
169178 : _base(o)
170179 {
171180 }
@@ -180,33 +189,43 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
180189 }
181190
182191 // ! Implicit in-place converting error constructor
183- SYSTEM_ERROR2_TEMPLATE (class Arg1 , class Arg2 , class ... Args, long = 5 ) //
184- SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> && std::is_constructible_v<error_type, Arg1, Arg2, Args...>) //
192+ SYSTEM_ERROR2_TEMPLATE (class Arg1 , class Arg2 , class ... Args, long = 5 ) //
193+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> &&
194+ std::is_constructible_v<error_type, Arg1, Arg2, Args...>) //
185195 &&std::is_constructible_v<error_type, Arg1, Arg2, Args...>))
186- constexpr result (Arg1 &&arg1, Arg2 &&arg2, Args &&...args) noexcept (std::is_nothrow_constructible_v<error_type, Arg1, Arg2, Args...>)
196+ constexpr result (Arg1 &&arg1, Arg2 &&arg2,
197+ Args &&...args) noexcept (std::is_nothrow_constructible_v<error_type, Arg1, Arg2, Args...>)
187198 : _base(std::in_place_index<0 >, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Args>(args)...)
188199 {
189200 }
190201
191202 // ! Implicit in-place converting value constructor
192- SYSTEM_ERROR2_TEMPLATE (class Arg1 , class Arg2 , class ... Args, int = 5 ) //
193- SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> && std::is_constructible_v<error_type, Arg1, Arg2, Args...>) //
203+ SYSTEM_ERROR2_TEMPLATE (class Arg1 , class Arg2 , class ... Args, int = 5 ) //
204+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> &&
205+ std::is_constructible_v<error_type, Arg1, Arg2, Args...>) //
194206 &&std::is_constructible_v<value_type, Arg1, Arg2, Args...>))
195- constexpr result (Arg1 &&arg1, Arg2 &&arg2, Args &&...args) noexcept (std::is_nothrow_constructible_v<value_type, Arg1, Arg2, Args...>)
207+ constexpr result (Arg1 &&arg1, Arg2 &&arg2,
208+ Args &&...args) noexcept (std::is_nothrow_constructible_v<value_type, Arg1, Arg2, Args...>)
196209 : _base(std::in_place_index<1 >, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Args>(args)...)
197210 {
198211 }
199212
200- // ! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
201- SYSTEM_ERROR2_TEMPLATE (class U , class ... Args, //
202- class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<U, Args...>::type) // Safe ADL lookup of make_status_code(), returns void if not found
203- SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(!std::is_same<typename std::decay<U>::type, result>::value // not copy/move of self
204- && !std::is_same<typename std::decay<U>::type, value_type>::value // not copy/move of value type
205- && is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
206- && std::is_constructible<error_type, MakeStatusCodeResult>::value)) // ADLed status code is compatible
207- constexpr result (U &&v, Args &&...args) noexcept (noexcept (make_status_code(std::declval<U>(), std::declval<Args>()...))) // NOLINT
213+ // ! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a
214+ // ! `status_code`. Note that `make_status_code(status_code)` is illegal, hence the static assertion.
215+ SYSTEM_ERROR2_TEMPLATE (class U , class ... Args, //
216+ class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<
217+ U, Args...>::type) // Safe ADL lookup of make_status_code(), returns void if not found
218+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(
219+ !std::is_same<typename std::decay<U>::type, result>::value // not copy/move of self
220+ && !std::is_same<typename std::decay<U>::type, value_type>::value // not copy/move of value type
221+ && is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
222+ && std::is_constructible<error_type, MakeStatusCodeResult>::value)) // ADLed status code is compatible
223+ constexpr result (U &&v, Args &&...args) noexcept (noexcept (make_status_code(std::declval<U>(),
224+ std::declval<Args>()...))) // NOLINT
208225 : _base(std::in_place_index<0 >, make_status_code(static_cast <U &&>(v), static_cast<Args &&>(args)...))
209226 {
227+ static_assert (!is_status_code<typename std::decay<T>::type>::value,
228+ " make_status_code() cannot consume status codes!" );
210229 }
211230
212231 // ! Swap with another result
@@ -301,7 +320,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
301320 }
302321
303322 // ! Accesses the value, being UB if none exists
304- constexpr value_type_if_enabled &assume_value () &noexcept
323+ constexpr value_type_if_enabled &assume_value () & noexcept
305324 {
306325 if (!has_value ())
307326 {
@@ -310,7 +329,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
310329 return *std::get_if<1 >(this );
311330 }
312331 // ! Accesses the error, being UB if none exists
313- constexpr const value_type_if_enabled &assume_value () const &noexcept
332+ constexpr const value_type_if_enabled &assume_value () const & noexcept
314333 {
315334 if (!has_value ())
316335 {
@@ -319,7 +338,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
319338 return *std::get_if<1 >(this );
320339 }
321340 // ! Accesses the error, being UB if none exists
322- constexpr value_type_if_enabled &&assume_value() &&noexcept
341+ constexpr value_type_if_enabled &&assume_value() && noexcept
323342 {
324343 if (!has_value ())
325344 {
@@ -328,7 +347,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
328347 return std::move (*std::get_if<1 >(this ));
329348 }
330349 // ! Accesses the error, being UB if none exists
331- constexpr const value_type_if_enabled &&assume_value() const &&noexcept
350+ constexpr const value_type_if_enabled &&assume_value() const && noexcept
332351 {
333352 if (!has_value ())
334353 {
@@ -338,7 +357,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
338357 }
339358
340359 // ! Accesses the error, being UB if none exists
341- constexpr error_type &assume_error () &noexcept
360+ constexpr error_type &assume_error () & noexcept
342361 {
343362 if (!has_error ())
344363 {
@@ -347,7 +366,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
347366 return *std::get_if<0 >(this );
348367 }
349368 // ! Accesses the error, being UB if none exists
350- constexpr const error_type &assume_error () const &noexcept
369+ constexpr const error_type &assume_error () const & noexcept
351370 {
352371 if (!has_error ())
353372 {
@@ -356,7 +375,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
356375 return *std::get_if<0 >(this );
357376 }
358377 // ! Accesses the error, being UB if none exists
359- constexpr error_type &&assume_error() &&noexcept
378+ constexpr error_type &&assume_error() && noexcept
360379 {
361380 if (!has_error ())
362381 {
@@ -365,7 +384,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
365384 return std::move (*std::get_if<0 >(this ));
366385 }
367386 // ! Accesses the error, being UB if none exists
368- constexpr const error_type &&assume_error() const &&noexcept
387+ constexpr const error_type &&assume_error() const && noexcept
369388 {
370389 if (!has_error ())
371390 {
@@ -376,13 +395,15 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
376395};
377396
378397// ! True if the two results compare equal.
379- template <class T , class U , typename = decltype (std::declval<T>() == std::declval<U>())> constexpr inline bool operator ==(const result<T> &a, const result<U> &b) noexcept
398+ template <class T , class U , typename = decltype (std::declval<T>() == std::declval<U>())>
399+ constexpr inline bool operator ==(const result<T> &a, const result<U> &b) noexcept
380400{
381401 const auto &x = a._internal ();
382402 return x == b;
383403}
384404// ! True if the two results compare unequal.
385- template <class T , class U , typename = decltype (std::declval<T>() != std::declval<U>())> constexpr inline bool operator !=(const result<T> &a, const result<U> &b) noexcept
405+ template <class T , class U , typename = decltype (std::declval<T>() != std::declval<U>())>
406+ constexpr inline bool operator !=(const result<T> &a, const result<U> &b) noexcept
386407{
387408 const auto &x = a._internal ();
388409 return x != b;
0 commit comments