11/* A partial result based on std::variant and proposed std::error
2- (C) 2020 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
2+ (C) 2020-2026 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
33File Created: Jan 2020
44
55Licensed under the Apache License, Version 2.0 (the "License");
@@ -116,7 +116,7 @@ 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
121121 void _ub ()
122122 {
@@ -147,25 +147,33 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
147147
148148 // ! Implicit result converting move constructor
149149 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>)
150+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>))
151+ constexpr result (result<U> &&o,
152+ _implicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
151153 : _base(std::move(o))
152154 {
153155 }
154156 // ! Implicit result converting copy constructor
155157 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>)
158+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_convertible_v<U, T>))
159+ constexpr result (const result<U> &o,
160+ _implicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
157161 : _base(o)
158162 {
159163 }
160164 // ! Explicit result converting move constructor
161165 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>)
166+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>))
167+ constexpr explicit result (result<U> &&o,
168+ _explicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
163169 : _base(std::move(o))
164170 {
165171 }
166172 // ! Explicit result converting copy constructor
167173 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>)
174+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(std::is_constructible_v<T, U>))
175+ constexpr explicit result (const result<U> &o,
176+ _explicit_converting_constructor_tag = {}) noexcept (std::is_nothrow_constructible_v<T, U>)
169177 : _base(o)
170178 {
171179 }
@@ -180,31 +188,39 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
180188 }
181189
182190 // ! 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...>) //
191+ SYSTEM_ERROR2_TEMPLATE (class Arg1 , class Arg2 , class ... Args, long = 5 ) //
192+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> &&
193+ std::is_constructible_v<error_type, Arg1, Arg2, Args...>) //
185194 &&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...>)
195+ constexpr result (Arg1 &&arg1, Arg2 &&arg2,
196+ Args &&...args) noexcept (std::is_nothrow_constructible_v<error_type, Arg1, Arg2, Args...>)
187197 : _base(std::in_place_index<0 >, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Args>(args)...)
188198 {
189199 }
190200
191201 // ! 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...>) //
202+ SYSTEM_ERROR2_TEMPLATE (class Arg1 , class Arg2 , class ... Args, int = 5 ) //
203+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(!(std::is_constructible_v<value_type, Arg1, Arg2, Args...> &&
204+ std::is_constructible_v<error_type, Arg1, Arg2, Args...>) //
194205 &&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...>)
206+ constexpr result (Arg1 &&arg1, Arg2 &&arg2,
207+ Args &&...args) noexcept (std::is_nothrow_constructible_v<value_type, Arg1, Arg2, Args...>)
196208 : _base(std::in_place_index<1 >, std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Args>(args)...)
197209 {
198210 }
199211
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
212+ // ! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a
213+ // ! `status_code`.
214+ SYSTEM_ERROR2_TEMPLATE (class U , class ... Args, //
215+ class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<
216+ U, Args...>::type) // Safe ADL lookup of make_status_code(), returns void if not found
217+ SYSTEM_ERROR2_TREQUIRES (SYSTEM_ERROR2_TPRED(
218+ !std::is_same<typename std::decay<U>::type, result>::value // not copy/move of self
219+ && !std::is_same<typename std::decay<U>::type, value_type>::value // not copy/move of value type
220+ && is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
221+ && std::is_constructible<error_type, MakeStatusCodeResult>::value)) // ADLed status code is compatible
222+ constexpr result (U &&v, Args &&...args) noexcept (noexcept (make_status_code(std::declval<U>(),
223+ std::declval<Args>()...))) // NOLINT
208224 : _base(std::in_place_index<0 >, make_status_code(static_cast <U &&>(v), static_cast<Args &&>(args)...))
209225 {
210226 }
@@ -301,7 +317,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
301317 }
302318
303319 // ! Accesses the value, being UB if none exists
304- constexpr value_type_if_enabled &assume_value () &noexcept
320+ constexpr value_type_if_enabled &assume_value () & noexcept
305321 {
306322 if (!has_value ())
307323 {
@@ -310,7 +326,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
310326 return *std::get_if<1 >(this );
311327 }
312328 // ! Accesses the error, being UB if none exists
313- constexpr const value_type_if_enabled &assume_value () const &noexcept
329+ constexpr const value_type_if_enabled &assume_value () const & noexcept
314330 {
315331 if (!has_value ())
316332 {
@@ -319,7 +335,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
319335 return *std::get_if<1 >(this );
320336 }
321337 // ! Accesses the error, being UB if none exists
322- constexpr value_type_if_enabled &&assume_value() &&noexcept
338+ constexpr value_type_if_enabled &&assume_value() && noexcept
323339 {
324340 if (!has_value ())
325341 {
@@ -328,7 +344,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
328344 return std::move (*std::get_if<1 >(this ));
329345 }
330346 // ! Accesses the error, being UB if none exists
331- constexpr const value_type_if_enabled &&assume_value() const &&noexcept
347+ constexpr const value_type_if_enabled &&assume_value() const && noexcept
332348 {
333349 if (!has_value ())
334350 {
@@ -338,7 +354,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
338354 }
339355
340356 // ! Accesses the error, being UB if none exists
341- constexpr error_type &assume_error () &noexcept
357+ constexpr error_type &assume_error () & noexcept
342358 {
343359 if (!has_error ())
344360 {
@@ -347,7 +363,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
347363 return *std::get_if<0 >(this );
348364 }
349365 // ! Accesses the error, being UB if none exists
350- constexpr const error_type &assume_error () const &noexcept
366+ constexpr const error_type &assume_error () const & noexcept
351367 {
352368 if (!has_error ())
353369 {
@@ -356,7 +372,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
356372 return *std::get_if<0 >(this );
357373 }
358374 // ! Accesses the error, being UB if none exists
359- constexpr error_type &&assume_error() &&noexcept
375+ constexpr error_type &&assume_error() && noexcept
360376 {
361377 if (!has_error ())
362378 {
@@ -365,7 +381,7 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
365381 return std::move (*std::get_if<0 >(this ));
366382 }
367383 // ! Accesses the error, being UB if none exists
368- constexpr const error_type &&assume_error() const &&noexcept
384+ constexpr const error_type &&assume_error() const && noexcept
369385 {
370386 if (!has_error ())
371387 {
@@ -376,13 +392,15 @@ template <class T> class result : protected std::variant<SYSTEM_ERROR2_NAMESPACE
376392};
377393
378394// ! 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
395+ template <class T , class U , typename = decltype (std::declval<T>() == std::declval<U>())>
396+ constexpr inline bool operator ==(const result<T> &a, const result<U> &b) noexcept
380397{
381398 const auto &x = a._internal ();
382399 return x == b;
383400}
384401// ! 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
402+ template <class T , class U , typename = decltype (std::declval<T>() != std::declval<U>())>
403+ constexpr inline bool operator !=(const result<T> &a, const result<U> &b) noexcept
386404{
387405 const auto &x = a._internal ();
388406 return x != b;
0 commit comments