Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
result.hpp
Go to the documentation of this file.
1// Copyright 2026, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5///
6/// @file result.hpp
7/// @brief Provides @c arene::base::result, a value/error sum-type suitable for use as a return value, similar to
8/// @c std::expected
9///
10#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_RESULT_RESULT_HPP_
11#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_RESULT_RESULT_HPP_
12
13// IWYU pragma: private, include "arene/base/result.hpp"
14
15// parasoft-begin-suppress AUTOSAR-A7_1_5-a-2 "Trailing return syntax permitted by A7-1-5 Permit #1 v1.0.0"
16
17// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
18
19#include "arene/base/compiler_support/attributes.hpp"
20#include "arene/base/constraints/constraints.hpp"
21#include "arene/base/contracts/contract.hpp"
22#include "arene/base/functional/invoke.hpp"
23#include "arene/base/memory/construct_at.hpp"
24#include "arene/base/monostate/monostate.hpp"
25#include "arene/base/result/detail/in_place_error.hpp" // IWYU pragma: export
26#include "arene/base/result/detail/in_place_value.hpp" // IWYU pragma: export
27#include "arene/base/result/detail/result_base.hpp"
28#include "arene/base/stdlib_choice/addressof.hpp"
29#include "arene/base/stdlib_choice/cstddef.hpp"
30#include "arene/base/stdlib_choice/declval.hpp"
31#include "arene/base/stdlib_choice/enable_if.hpp"
32#include "arene/base/stdlib_choice/forward.hpp"
33#include "arene/base/stdlib_choice/hash.hpp"
34#include "arene/base/stdlib_choice/ignore.hpp"
35#include "arene/base/stdlib_choice/is_constructible.hpp"
36#include "arene/base/stdlib_choice/is_convertible.hpp"
37#include "arene/base/stdlib_choice/is_copy_assignable.hpp"
38#include "arene/base/stdlib_choice/is_copy_constructible.hpp"
39#include "arene/base/stdlib_choice/is_move_assignable.hpp"
40#include "arene/base/stdlib_choice/is_move_constructible.hpp"
41#include "arene/base/stdlib_choice/is_object.hpp"
42#include "arene/base/stdlib_choice/is_same.hpp"
43#include "arene/base/stdlib_choice/is_void.hpp"
44#include "arene/base/stdlib_choice/move.hpp"
45#include "arene/base/stdlib_choice/remove_const.hpp"
46#include "arene/base/stdlib_choice/remove_cv.hpp"
47#include "arene/base/stdlib_choice/remove_reference.hpp"
48#include "arene/base/type_manipulation/non_constructible_dummy.hpp"
49#include "arene/base/type_traits/all_of.hpp"
50#include "arene/base/type_traits/comparison_traits.hpp"
51#include "arene/base/type_traits/conditional.hpp"
52#include "arene/base/type_traits/decays_to.hpp"
53#include "arene/base/type_traits/has_overloaded_address_operator.hpp"
54#include "arene/base/type_traits/is_instantiation_of.hpp"
55#include "arene/base/type_traits/is_invocable.hpp"
56#include "arene/base/type_traits/is_swappable.hpp"
57#include "arene/base/type_traits/remove_cvref.hpp"
58#include "arene/base/utility/forward_like.hpp"
59#include "arene/base/utility/swap.hpp"
60// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
61
62namespace arene {
63namespace base {
64
65// parasoft-begin-suppress AUTOSAR-A10_2_1-b-2 "False Positive: Base class function made visible with 'using'"
66// parasoft-begin-suppress AUTOSAR-A1_1_1-b-2 "False Positive: Copy constructor is defined or deleted as appropriate"
67// parasoft-begin-suppress AUTOSAR-M14_5_3-a-2 "False Positive: Copy assignment is defined or deleted as appropriate"
68// parasoft-begin-suppress AUTOSAR-A12_0_1-a-2 "False Positive: Copy assignment is defined or deleted as appropriate"
69/// @brief A sum type which can hold either a _value_ or an _error_. Similar to
70/// [std::expected](https://en.cppreference.com/w/cpp/utility/expected).
71///
72/// @tparam T the type of the value channel. May be @c void , otherwise must satisfy @c std::is_object and must not have
73/// const or volatile qualification.
74/// @tparam E the type of the error channel. May not be @c void , must satisfy @c std::is_object and must not have
75/// const or volatile qualification.
76///
77/// @c result<T,E> can be used as a return type from an API to express the possibility that API being _failable_ without
78/// the need for outparams or exceptions. Its design is non-allocating, and it its memory usage is similar to that of a
79/// @c union : it requires the amount of memory needed to store the larger of @c T or @c E , plus the space for the
80/// discriminator.
81///
82/// Semantically, @c result<T,E> contains two _channels_, the _value channel_ and the _error channel_, and at any point
83/// during program execution exactly **one** of these channels is populated. A default constructed @c result<T,E> has
84/// its @c value_channel default constructed.
85///
86/// The following major operations are supported:
87/// * Querying whether the value or error channel is populated (optionally with a specific value/error).
88/// * Accessing the value/error channel's content. This is a _checked_ operation, meaning that an @c ARENE_PRECONDITION
89/// violation will occur if the specified channel is not populated.
90/// * Equality Comparison if both @c T and @c E are equality comparable. @c results with different channels populated
91/// always compare unequal.
92/// * Assignment if both @c T and @c E are assignable.
93/// * @c swap if both @c T and @c E swappable and move-assignable.
94/// * @c std::hash if both @c T and @c E support @c std::hash .
95/// * Conversion to @c bool , which is equivalent to @c result<T,E>::has_value() .
96/// * Dereferencing the @c result , which is equivalent to accessing @c result::value() .
97///
98/// Some basic example usages:
99/// @snippet docs/examples/result_examples.cpp basic_example
100///
101/// Please see the detailed [user manual](result) for usage examples and best practices.
102template <class T, class E>
103// NOLINTNEXTLINE(hicpp-special-member-functions) false-positive, it can't see through the non-constructible-dummy trick
105 /// @brief The type of the base class holding the storage
107
108 static_assert(
110 "The value type stored in result must not have an overloaded address-of operator"
111 );
112
113 public:
114 // parasoft-begin-suppress AUTOSAR-A2_10_1-d-2 "False Positive: This identifier does not hide anything"
115 /// @brief The type when the @c result contains a value.
116 using value_type = T;
117 // parasoft-end-suppress AUTOSAR-A2_10_1-d-2
118
119 /// @brief The type when the @c result contains an error.
120 using error_type = E;
121
122 private:
123 static_assert(
125 "value_type must be an unqualified type, non-reference type."
126 );
127 static_assert(
129 "error_type must be an unqualified type, non-reference type."
130 );
131
132 static_assert(!std::is_same<error_type, void>::value, "void as an error_type is not supported");
133 static_assert(
135 "monostate as an error_type is not supported"
136 );
137
138 static_assert(std::is_object<value_type>::value, "value_type must be an object type (it must not be a reference).");
139 static_assert(std::is_object<error_type>::value, "error_type must be an object type (it must not be a reference).");
140
141 public:
142 ///
143 /// @brief Constructs a @c result with a default-constructed @c value_type . Does not participate in overload
144 /// resolution if @c value_type is not default constructible.
145 /// @post @c has_value() returns @c true
146 /// @post @c value() returns reference to an object equivalent to default-constructing @c value_type .
147 constexpr result() = default;
148
149 ///
150 /// @brief Constructs a @c result containing the @c value_type by way of direct-non-list-initialization.
151 ///
152 /// @tparam P The type of the initializers. Must satisfy @c std::is_constructible<value_type,P&&...> .
153 /// @param args The arguments to initialize the value channel with.
154 /// @post @c has_value() returns @c true
155 /// @post @c value() returns reference to an object equivalent to constructing @c value_type with @c args .
156 ///
157 /// Example Usage:
158 /// @snippet docs/examples/result_examples.cpp in_place_value
159 template <class... P, constraints<std::enable_if_t<std::is_constructible<value_type, P&&...>::value>> = nullptr>
160 // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
161 constexpr result(in_place_value_t, P&&... args) noexcept(noexcept(base_type(in_place_value, std::forward<P>(args)...))
162 )
164
165 ///
166 /// @brief Constructs a @c result containing the @c error_type by way of direct-non-list-initialization.
167 ///
168 /// @tparam P The type of the initializers. Must satisfy @c std::is_constructible<error_type,P&&...> .
169 /// @param args The arguments to initialize the value channel with.
170 /// @post @c has_error() returns @c true
171 /// @post @c error() returns reference to an object equivalent to constructing @c error_type with @c args .
172 ///
173 /// Example Usage:
174 /// @snippet docs/examples/result_examples.cpp in_place_error
175 template <class... P, constraints<std::enable_if_t<std::is_constructible<error_type, P&&...>::value>> = nullptr>
176 // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
177 constexpr result(in_place_error_t, P&&... args) noexcept(noexcept(base_type(in_place_error, std::forward<P>(args)...))
178 )
180
181 /// @brief Default copy constructor
182 constexpr result(result const& copy) noexcept(noexcept(base_type(std::declval<result const&>()))) = default;
183 /// @brief Default move constructor
184 // NOLINTNEXTLINE(hicpp-noexcept-move) We want to exactly mimic the noexcept properties of ValueType and ErrorType.
185 constexpr result(result&& move) noexcept(noexcept(base_type(std::declval<result&&>()))) = default;
186 /// @brief Destroy the stored value or error
187 ~result() = default;
188
189 private:
190 /// @brief trait which detects if the result should be copy-assignable
191 static constexpr bool is_copy_assignable{
194 };
195
196 /// @brief The argument for the "copy assign" operator: @c result if the assignment is possible, @c
197 /// non_constructible_dummy if not
199 /// @brief The argument for the *deleted* "copy assign" operator: @c non_constructible_dummy if the assignment is
200 /// possible, @c result if not (so the copy assignment is deleted)
202
203 public:
204 /// @brief Copy-assignment for the case that @c value_type and @c error_type satisfy
205 /// @c std::is_nothrow_copy_constructible and @c std::is_nothrow_copy_assignable, otherwise a dummy assignment
206 /// operator that can never be called
207 /// @param other The value to copy from
208 /// @return *this
209 constexpr auto operator=(copy_assign_arg const& other) noexcept -> result& {
210 if (&other != this) {
211 std::ignore = assign(other);
212 }
213 return *this;
214 }
215 /// @brief Deleted Copy-assignment if @c value_type or @c error_type do not satisfy
216 /// @c std::is_nothrow_copy_constructible and @c std::is_nothrow_copy_assignable, otherwise a deleted dummy assignment
217 /// operator
218 /// @param other The value to copy from
219 /// @return *this
220 constexpr auto operator=(deleted_copy_assign_arg const& other) noexcept -> result& = delete;
221
222 private:
223 /// @brief trait to detect if the result should be move-assignable
224 static constexpr bool is_move_assignable{
227 };
228
229 /// @brief The argument for the "move assign" operator: @c result if the assignment is possible, @c
230 /// non_constructible_dummy if not
232 /// @brief The argument for the *deleted* "move assign" operator: @c non_constructible_dummy if the assignment is
233 /// possible, @c result if not (so the move assignment is deleted)
235
236 public:
237 /// @brief Move-assignment for the case that @c value_type and @c error_type satisfy
238 /// @c std::is_nothrow_move_constructible and @c std::is_nothrow_move_assignable, otherwise a dummy assignment
239 /// operator that can never be called
240 /// @param other The value to move from
241 /// @return *this
242 constexpr auto operator=(move_assign_arg&& other) noexcept -> result& {
243 std::ignore = assign(std::move(other));
244 return *this;
245 }
246 /// @brief Deleted Move-assignment if @c value_type or @c error_type do not satisfy
247 /// @c std::is_nothrow_move_constructible and @c std::is_nothrow_move_assignable, otherwise a deleted dummy assignment
248 /// operator
249 /// @param other The value to move from
250 /// @return *this
251 constexpr auto operator=(deleted_move_assign_arg&& other) noexcept -> result& = delete;
252
253 // @brief Expose @c has_value from base type
254 using base_type::has_value;
255
256 /// @brief Checks if the value channel contains a specific value
257 ///
258 /// @param val The value to check for.
259 /// @return true If @c has_value() and @c value()==val .
260 /// @return false Otherwise.
261 template <typename U = value_type, constraints<std::enable_if_t<is_equality_comparable_v<U>>> = nullptr>
262 ARENE_NODISCARD constexpr auto has_value(value_type const& val) const
263 noexcept(noexcept(val == std::declval<value_type>())) -> bool {
264 if (this->has_value()) {
265 return val == this->storage().unsafe_value();
266 }
267 return false;
268 }
269
270 // @brief Expose @c has_error from base type
271 using base_type::has_error;
272
273 // @brief Expose boolean conversion from base type
274 using base_type::operator bool;
275
276 /// @brief Accesses a pointer to the content of the value channel.
277 ///
278 /// @pre has_value(), else ARENE_PRECONDITION violation.
279 /// @return A pointer to the contained value
280 ARENE_NODISCARD constexpr auto operator->() noexcept -> value_type* { return &value(); }
281
282 /// @brief Accesses a pointer to the content of the value channel.
283 ///
284 /// @pre has_value(), else ARENE_PRECONDITION violation.
285 /// @return A pointer to the contained value
286 ARENE_NODISCARD constexpr auto operator->() const noexcept -> value_type const* { return &value(); }
287
288 /// @brief Accesses a reference to the content of the value channel.
289 ///
290 /// @pre has_value(), else ARENE_PRECONDITION violation.
291 /// @return A reference to the contained value
292 ARENE_NODISCARD constexpr auto operator*() & noexcept -> value_type& { return value(); }
293
294 /// @brief Accesses a reference to the content of the value channel.
295 ///
296 /// @pre has_value(), else ARENE_PRECONDITION violation.
297 /// @return A const reference to the contained value
298 ARENE_NODISCARD constexpr auto operator*() const& noexcept -> value_type const& { return value(); }
299
300 /// @brief Accesses a reference to the content of the value channel.
301 ///
302 /// @pre has_value(), else ARENE_PRECONDITION violation.
303 /// @return An rvalue reference to the contained value
304 ARENE_NODISCARD constexpr auto operator*() && noexcept -> value_type&& { return std::move(value()); }
305
306 // parasoft-begin-suppress AUTOSAR-A18_9_3-a-2 "We want to ensure the qualifier is preserved"
307 /// @brief Accesses a reference to the content of the value channel.
308 ///
309 /// @pre has_value(), else ARENE_PRECONDITION violation.
310 /// @return A const rvalue reference to the contained value
311 ARENE_NODISCARD constexpr auto operator*() const&& noexcept -> value_type const&& { return std::move(value()); }
312 // parasoft-end-suppress AUTOSAR-A18_9_3-a-2
313
314 // parasoft-begin-suppress AUTOSAR-A9_3_1-a-2 "False positive: This class is a container of the value"
315 /// @brief Accesses a reference to the content of the value channel.
316 ///
317 /// @pre has_value(), else ARENE_PRECONDITION violation.
318 /// @return A reference to the contained value
319 ARENE_NODISCARD constexpr auto value() & noexcept -> value_type& {
320 ARENE_PRECONDITION(this->has_value());
321 return this->storage().unsafe_value();
322 }
323 // parasoft-end-suppress AUTOSAR-A9_3_1-a-2
324
325 /// @brief Accesses a reference to the content of the value channel.
326 ///
327 /// @pre has_value(), else ARENE_PRECONDITION violation.
328 /// @return A const reference to the contained value
329 ARENE_NODISCARD constexpr auto value() const& noexcept -> value_type const& {
330 ARENE_PRECONDITION(this->has_value());
331 return this->storage().unsafe_value();
332 }
333
334 // parasoft-begin-suppress AUTOSAR-A9_3_1-a-2 "False positive: This class is a container of the value"
335 /// @brief Accesses a reference to the content of the value channel.
336 ///
337 /// @pre has_value(), else ARENE_PRECONDITION violation.
338 /// @return An rvalue reference to the contained value
339 ARENE_NODISCARD constexpr auto value() && noexcept -> value_type&& {
340 ARENE_PRECONDITION(this->has_value());
341 return std::move(this->storage().unsafe_value());
342 }
343 // parasoft-end-suppress AUTOSAR-A9_3_1-a-2
344
345 // parasoft-begin-suppress AUTOSAR-A18_9_3-a-2 "We want to ensure the qualifier is preserved"
346 /// @brief Accesses a reference to the content of the value channel.
347 ///
348 /// @pre has_value(), else ARENE_PRECONDITION violation.
349 /// @return A const rvalue reference to the contained value
350 ARENE_NODISCARD constexpr auto value() const&& noexcept -> value_type const&& {
351 ARENE_PRECONDITION(this->has_value());
352 return std::move(this->storage().unsafe_value());
353 }
354 // parasoft-end-suppress AUTOSAR-A18_9_3-a-2
355
356 /// @brief Returns the value if the value channel is populated, else another value. Not declared if @c T is @c void .
357 /// @tparam U The type of the default value. Must satisfy @c std::is_convertible<U,value_type> .
358 /// @param default_value The default value to use if the value channel is not populated.
359 /// @return value_type If @c has_value() is true, equivalent to @c value() . Otherwise, @c default_value converted to
360 /// @c value_type .
361 template <typename U = T, constraints<std::enable_if_t<std::is_convertible<U, value_type>::value>> = nullptr>
362 ARENE_NODISCARD constexpr auto value_or(U&& default_value) const& noexcept -> value_type {
363 return this->has_value() ? this->storage().unsafe_value() : static_cast<value_type>(std::forward<U>(default_value));
364 }
365
366 /// @brief Returns the value if the value channel is populated, else another value. Not declared if @c T is @c void .
367 /// @tparam U The type of the default value. Must satisfy @c std::is_convertible<U,value_type> .
368 /// @param default_value The default value to use if the value channel is not populated.
369 /// @return value_type If @c has_value() is true, equivalent to @c value() . Otherwise, @c default_value converted to
370 /// @c value_type .
371 template <typename U = T, constraints<std::enable_if_t<std::is_convertible<U, value_type>::value>> = nullptr>
372 ARENE_NODISCARD constexpr auto value_or(U&& default_value) && noexcept -> value_type {
373 return this->has_value() ? std::move(this->storage().unsafe_value())
374 : static_cast<value_type>(std::forward<U>(default_value));
375 }
376
377 // parasoft-begin-suppress AUTOSAR-A9_3_1-a-2 "False positive: This class is a container of the value"
378 /// @brief Accesses a reference to the content of the error channel.
379 ///
380 /// @pre has_error(), else ARENE_PRECONDITION violation
381 /// @return A reference to the contained error
382 ARENE_NODISCARD constexpr auto error() & noexcept -> error_type& {
384 return this->storage().unsafe_error();
385 }
386 // parasoft-end-suppress AUTOSAR-A9_3_1-a-2
387
388 /// @brief Accesses a reference to the content of the error channel.
389 ///
390 /// @pre has_error(), else ARENE_PRECONDITION violation
391 /// @return A const reference to the contained error
392 ARENE_NODISCARD constexpr auto error() const& noexcept -> error_type const& {
394 return this->storage().unsafe_error();
395 }
396 // parasoft-begin-suppress AUTOSAR-A9_3_1-a-2 "False positive: This class is a container of the value"
397 /// @brief Accesses a reference to the content of the error channel.
398 ///
399 /// @pre has_error(), else ARENE_PRECONDITION violation
400 /// @return An rvalue reference to the contained error
401 ARENE_NODISCARD constexpr auto error() && noexcept -> error_type&& {
403 return std::move(this->storage().unsafe_error());
404 }
405 // parasoft-end-suppress AUTOSAR-A9_3_1-a-2
406 // parasoft-begin-suppress AUTOSAR-A18_9_3-a-2 "We want to ensure the qualifier is preserved"
407 /// @brief Accesses a reference to the content of the error channel.
408 ///
409 /// @pre has_error(), else ARENE_PRECONDITION violation
410 /// @return A const rvalue reference to the contained error
411 ARENE_NODISCARD constexpr auto error() const&& noexcept -> error_type const&& {
413 return std::move(this->storage().unsafe_error());
414 }
415 // parasoft-end-suppress AUTOSAR-A18_9_3-a-2
416
417 /// @brief Swaps the state of two results.
418 ///
419 /// @tparam SourceValueType Must satisfy @c is_swappable_v<SourceValueType> and @c
420 /// std::is_nothrow_move_constructible<SourceValueType>
421 /// @tparam SourceErrorType Must satisfy @c is_swappable_v<SourceErrorType> and @c
422 /// std::is_nothrow_move_constructible<SourceErrorType>
423 /// @param other The result to swap with
424 /// @post If both @c this and @c other have matching channels populated, the content of those channels are swapped as
425 /// if via @c arene::base::swap . Otherwise, it is equivalent to emplacing @c this with the active channel
426 /// from @c other , and vice-versa.
427 ///
428 template <
429 typename SourceValueType = T,
430 typename SourceErrorType = E,
436 constexpr void swap(result& other
438 if (this->has_value()) {
439 if (other.has_value()) {
441 } else {
443 static_cast<void>(other.emplace(in_place_value, std::move(this->storage().unsafe_value())));
444 static_cast<void>(this->emplace(in_place_error, std::move(tmp)));
445 }
446 } else if (this->has_error()) {
447 if (other.has_error()) {
449 } else {
451 static_cast<void>(other.emplace(in_place_error, std::move(this->storage().unsafe_error())));
452 static_cast<void>(this->emplace(in_place_value, std::move(tmp)));
453 }
454 } else {
455 // do nothing
456 }
457 }
458
459 // parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "Hidden friends permitted by A11-3-1 Permit #2"
460 /// @brief Swaps the state of two results.
461 ///
462 /// @tparam SourceValueType Must satisfy @c is_swappable_v<SourceValueType> , @c
463 /// std::is_nothrow_move_constructible<SourceValueType>
464 /// @tparam SourceErrorType Must satisfy @c is_swappable_v<SourceErrorType> , @c
465 /// std::is_nothrow_move_constructible<SourceErrorType>
466 /// @param lhs The left hand result to swap
467 /// @param rhs The right hand result to swap
468 /// @post If both @c lhs and @c rhs have matching channels populated, the content of those channels are swapped as
469 /// if via @c arene::base::swap . Otherwise, it is equivalent to emplacing @c lhs with the active channel
470 /// from @c rhs , and vise-versa.
471 ///
472 template <
473 typename SourceValueType = T,
474 typename SourceErrorType = E,
480 friend constexpr void swap(result& lhs, result& rhs) noexcept(noexcept(lhs.swap(rhs))) {
481 lhs.swap(rhs);
482 }
483 // parasoft-end-suppress AUTOSAR-A11_3_1-a-2
484
485 // imports emplace from result_base.
486 using base_type::emplace;
487
488 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
489 // parasoft-begin-suppress AUTOSAR-A9_3_1-a-2 "False positive: This class is a container of the value"
490 /// @brief Emplaces a value into the result
491 ///
492 /// @tparam ArgTypes the types of the arguments to construct the value with
493 /// @param args The arguments to construct the value with
494 /// @return A reference to the newly emplaced value
495 /// @post @c has_value() returns @c true
496 /// @post The content of @c value() will be equivalent to a @c value_type direct-initialized from @c args .
497 ///
498 template <
499 typename... ArgTypes,
502 this->reset();
504 return *::arene::base::construct_at(
505 std::addressof(this->storage().unsafe_value()),
507 );
508 }
509 // parasoft-end-suppress AUTOSAR-A9_3_1-a-2
510 // parasoft-end-suppress CERT_C-EXP37-a-3
511
512 // parasoft-begin-suppress AUTOSAR-A2_7_3-a-2 "False positive: All overloads are fully are documented"
513 // parasoft-begin-suppress AUTOSAR-A2_7_3-b-2 "False positive: All overloads are fully are documented"
514 /// @brief Monadic API which invokes a functor with the contents of @c value() if the value channel is populated.
515 ///
516 /// @tparam F Type of the visiting functor. Must be invocable with @c value_type matching the const/ref qualification
517 /// of @c SelfType, and return @c result<U,error_type> , where @c U may be any valid @c value_type .
518 /// @param handle_value the functor to invoke if @c self.has_value() is @c true .
519 /// @return result<U, error_type> which will be either the result of invoking @c handle_value with the contents of
520 /// @c self.value() , or it will contain a copy of @c self.error() .
521 ///
522 /// Basic usage example for opening a file:
523 /// @snippet docs/examples/result_examples.cpp and_then
524 ///
525 /// After this statement, @c maybe_file will contain either a valid instance of @c arene::base::file_handle in the
526 /// value channel, or it will contain an instance of @c arene::base::error_code representing either the failure to
527 /// open the file or the failure to open the directory.
528 ///
529 /// @{
530 template <typename F>
531 constexpr auto and_then(F&& handle_value) & {
532 return result::and_then(*this, std::forward<F>(handle_value));
533 }
534 template <typename F>
535 constexpr auto and_then(F&& handle_value) const& {
536 return result::and_then(*this, std::forward<F>(handle_value));
537 }
538 template <typename F>
539 constexpr auto and_then(F&& handle_value) && {
540 return result::and_then(std::move(*this), std::forward<F>(handle_value));
541 }
542 // parasoft-begin-suppress AUTOSAR-A18_9_3-a-2 "We want to ensure the qualifier is preserved"
543 template <typename F>
544 constexpr auto and_then(F&& handle_value) const&& {
545 return result::and_then(std::move(*this), std::forward<F>(handle_value));
546 }
547 // parasoft-end-suppress AUTOSAR-A18_9_3-a-2
548 /// @}
549 // parasoft-end-suppress AUTOSAR-A2_7_3-b-2
550 // parasoft-end-suppress AUTOSAR-A2_7_3-a-2
551
552 // parasoft-begin-suppress AUTOSAR-A2_7_3-a-2 "False positive: All overloads are fully are documented"
553 // parasoft-begin-suppress AUTOSAR-A2_7_3-b-2 "False positive: All overloads are fully are documented"
554 /// @brief Monadic API which invokes a functor with the contents of @c error() if the error channel is populated.
555 ///
556 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
557 /// of @c SelfType and return @c result<value_type,E> , where @c E may be any valid @c error_type .
558 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
559 /// @return result<value_type, E> which will be either the result of invoking @c handle_error with the contents of
560 /// @c self.error() , or it will contain a copy of @c self.value() .
561 ///
562 /// Basic usage example for opening a directory:
563 /// @snippet docs/examples/result_examples.cpp or_else
564 ///
565 /// @{
566 template <typename F>
567 constexpr auto or_else(F&& handle_error) & {
568 return result::or_else(*this, std::forward<F>(handle_error));
569 }
570 template <typename F>
571 constexpr auto or_else(F&& handle_error) const& {
572 return result::or_else(*this, std::forward<F>(handle_error));
573 }
574 template <typename F>
575 constexpr auto or_else(F&& handle_error) && {
576 return result::or_else(std::move(*this), std::forward<F>(handle_error));
577 }
578 // parasoft-begin-suppress AUTOSAR-A18_9_3-a-2 "We want to ensure the qualifier is preserved"
579 template <typename F>
580 constexpr auto or_else(F&& handle_error) const&& {
581 return result::or_else(std::move(*this), std::forward<F>(handle_error));
582 }
583 // parasoft-end-suppress AUTOSAR-A18_9_3-a-2
584 /// @}
585 // parasoft-end-suppress AUTOSAR-A2_7_3-b-2
586 // parasoft-end-suppress AUTOSAR-A2_7_3-a-2
587
588 // parasoft-begin-suppress AUTOSAR-A2_7_3-a-2 "False positive: All overloads are fully are documented"
589 // parasoft-begin-suppress AUTOSAR-A2_7_3-b-2 "False positive: All overloads are fully are documented"
590 // parasoft-begin-suppress AUTOSAR-A2_10_1-d "False positive: it is not hiding anything"
591 /// @brief Calls a provided functor with the value channel if it is populated, and produces a new result with the
592 /// return from it.
593 /// @tparam F Type of the visiting functor. Must be invocable with @c value_type matching the const/ref qualification
594 /// of @c this . May return any valid @c value_type
595 /// @param handle_value the functor to invoke if @c has_value() is @c true .
596 /// @return result<U, error_type> which will be one of:
597 /// * A @c result<U,error_type> constructed from the result of invoking @c handle_value with the contents of
598 /// @c value() if @c value_type is not @c void and the return from @c F is not @c void
599 /// * A @c result<void,error_type> constructed from the result of invoking @c handle_value with the contents
600 /// of @c value() if @c value_type is not @c void and the return from @c F is @c void
601 /// * A @c result<U,error_type> where @c U is the return type of @c F constructed from a copy of @c error() .
602 /// @{
603 template <typename F>
604 constexpr auto transform(F&& handle_value) & {
605 return result::transform(*this, std::forward<F>(handle_value));
606 }
607 template <typename F>
608 constexpr auto transform(F&& handle_value) const& {
609 return result::transform(*this, std::forward<F>(handle_value));
610 }
611 template <typename F>
612 constexpr auto transform(F&& handle_value) && {
613 return result::transform(std::move(*this), std::forward<F>(handle_value));
614 }
615 // parasoft-begin-suppress AUTOSAR-A18_9_3-a-2 "We want to ensure the qualifier is preserved"
616 template <typename F>
617 constexpr auto transform(F&& handle_value) const&& {
618 return result::transform(std::move(*this), std::forward<F>(handle_value));
619 }
620 // parasoft-end-suppress AUTOSAR-A18_9_3-a-2
621 /// @}
622 // parasoft-end-suppress AUTOSAR-A2_10_1-d
623 // parasoft-end-suppress AUTOSAR-A2_7_3-b-2
624 // parasoft-end-suppress AUTOSAR-A2_7_3-a-2
625
626 // parasoft-begin-suppress AUTOSAR-A2_7_3-a-2 "False positive: All overloads are fully are documented"
627 // parasoft-begin-suppress AUTOSAR-A2_7_3-b-2 "False positive: All overloads are fully are documented"
628 /// @brief Calls a provided functor with the error channel if it is populated, and produces a new result with the
629 /// return from it.
630 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
631 /// of @c this. May return any valid @c error_type .
632 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
633 /// @return result<value_type, E> which will be either:
634 /// * A result constructed from the result of invoking @c handle_error with the contents of @c self.error() ,
635 /// * A result constructed from a copy of @c self.value() .
636 /// @{
637 template <typename F>
638 constexpr auto transform_error(F&& handle_error) & {
639 return result::transform_error(*this, std::forward<F>(handle_error));
640 }
641 template <typename F>
642 constexpr auto transform_error(F&& handle_error) const& {
643 return result::transform_error(*this, std::forward<F>(handle_error));
644 }
645 template <typename F>
646 constexpr auto transform_error(F&& handle_error) && {
647 return result::transform_error(std::move(*this), std::forward<F>(handle_error));
648 }
649 // parasoft-begin-suppress AUTOSAR-A18_9_3-a-2 "We want to ensure the qualifier is preserved"
650 template <typename F>
651 constexpr auto transform_error(F&& handle_error) const&& {
652 return result::transform_error(std::move(*this), std::forward<F>(handle_error));
653 }
654 // parasoft-end-suppress AUTOSAR-A18_9_3-a-2
655 /// @}
656 // parasoft-end-suppress AUTOSAR-A2_7_3-b-2
657 // parasoft-end-suppress AUTOSAR-A2_7_3-a-2
658
659 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function used in other TUs"
660 // parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Conditionally noexcept based on underlying comparison"
661 // parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "False positive: comparison operators are permitted"
662 /// @brief Compare two results for equality.
663 /// @param lhs The first result
664 /// @param rhs The second result
665 /// @return bool @c true if the both @c lhs and @c rhs hold values that are equal, or both hold errors that are
666 /// equal, @c false otherwise
667 ARENE_NODISCARD friend constexpr auto operator==(result const& lhs, result const& rhs) noexcept(
668 noexcept(lhs.has_value(rhs.value())) && noexcept(lhs.has_error(rhs.error()))
669 ) -> bool {
670 static_assert(is_equality_comparable_v<value_type>, "Value type must be equality comparable");
671 static_assert(is_equality_comparable_v<error_type>, "Error type must be equality comparable");
672 if (lhs.has_value()) {
674 }
676 }
677 // parasoft-end-suppress AUTOSAR-A11_3_1-a-2
678 // parasoft-end-suppress AUTOSAR-A13_5_5-b-2
679 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
680
681 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function used in other TUs"
682 // parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Conditionally noexcept based on underlying comparison"
683 // parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "False positive: comparison operators are permitted"
684 /// @brief Compare two results for inequality.
685 /// @param lhs The first result
686 /// @param rhs The second result
687 /// @return bool @c true if the both @c lhs and @c rhs hold values that are not equal, or both hold errors that are
688 /// not equal, or one holds a value and the other holds an error, @c false otherwise
689 ARENE_NODISCARD friend constexpr auto operator!=(result const& lhs, result const& rhs) noexcept(noexcept(lhs == rhs))
690 -> bool {
691 return !(lhs == rhs);
692 }
693 // parasoft-end-suppress AUTOSAR-A11_3_1-a-2
694 // parasoft-end-suppress AUTOSAR-A13_5_5-b-2
695 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
696
697 private:
698 /// @brief Helper for implementing assignment which handles copy/move.
699 /// @tparam OtherType the result type to assign from. @c OtherType::value_type and @c OtherType::error_type must be
700 /// nothrow constructible and nothrow assignable to @c value_type and @c error_type respectably.
701 /// @param other the result to assign from.
702 /// @post The state of @c this will be as follows:
703 /// * If both @c this and @c other 's value channels are populated, then @c this will have its value channel's
704 /// state set as if via assignment from @c other 's value channel.
705 /// * If both @c this and @c other 's error channels are populated, then @c this will have its error channel's
706 /// state set as if via assignment from @c other 's error channel.
707 /// * Otherwise, @c this will have its state set as if @c emplace 'd with the active channel of @c other .
708 /// @return result& A reference to @c this post assignment.
709 template <typename OtherType, constraints<std::enable_if_t<decays_to_v<OtherType, result>>> = nullptr>
710 constexpr auto assign(OtherType&& other) noexcept -> result& {
711 if (this->has_value()) {
712 if (other.has_value()) {
713 this->storage().unsafe_value() =
715 return *this;
716 }
717 std::ignore = this->emplace(
720 );
721 return *this;
722 }
723 if (other.has_error()) {
725 return *this;
726 }
727 std::ignore =
729 return *this;
730 }
731
732 ///
733 /// @brief deduced-this helper for @c result::and_then<F>(F&&) .
734 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
735 /// @tparam F Type of the visiting functor. Must be invocable with @c value_type matching the const/ref qualification
736 /// of @c SelfType , and return @c result<U,error_type> , where @c U may be any valid @c value_type .
737 /// @param self the instance of the result to use.
738 /// @param handle_value the functor to invoke if @c self.has_value() is @c true .
739 /// @return result<U, error_type> which will be either the result of invoking @c handle_value with the contents of
740 /// @c self.value() , or it will contain a copy of @c self.error() .
741 template <typename SelfType, typename F, constraints<std::enable_if<decays_to_v<SelfType, result>>> = nullptr>
742 static constexpr auto and_then(SelfType&& self, F&& handle_value) {
743 using f_result_t =
745 static_assert(is_instantiation_of_v<f_result_t, ::arene::base::result>, "handle_value must return a result!");
746 static_assert(
748 "The result returned from handle_value's error channel must be the same as this result's error channel"
749 );
750 if (self.has_value()) {
751 return ::arene::base::invoke(
754 );
755 }
757 }
758
759 ///
760 /// @brief deduced-this helper for @c result::or_else<F>(F&&) .
761 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
762 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
763 /// of @c SelfType and return @c result<value_type,E> , where @c E may be any valid @c error_type .
764 /// @param self the instance of the result to use.
765 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
766 /// @return result<value_type, E> which will be either the result of invoking @c handle_error with the contents of
767 /// @c self.error() , or it will contain a copy of @c self.value() .
768 template <typename SelfType, typename F, constraints<std::enable_if<decays_to_v<SelfType, result>>> = nullptr>
769 static constexpr auto or_else(SelfType&& self, F&& handle_error) {
770 using f_result_t =
772 static_assert(is_instantiation_of_v<f_result_t, ::arene::base::result>, "handle_error must return a result!");
773 static_assert(
775 "The result returned from handle_error's value channel must be the same as this result's value channel"
776 );
777 if (self.has_error()) {
778 return ::arene::base::invoke(
781 );
782 }
784 }
785
786 // parasoft-begin-suppress AUTOSAR-A2_10_1-d "False positive: it isn't hiding anything."
787 /// @brief deduced-this helper for @c result::transform<F>(F&&) .
788 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
789 /// @tparam F Type of the visiting functor. Must be invocable with @c value_type matching the const/ref qualification
790 /// of @c SelfType. May return any valid @c value_type
791 /// @param self the instance of the result to use.
792 /// @param handle_value the functor to invoke if @c self.has_value() is @c true .
793 /// @return result<U, error_type> which will be one of:
794 /// * A @c result<U,error_type> constructed from the result of invoking @c handle_value with the contents of
795 /// @c self.value()
796 /// * A @c result<U,error_type> where @c U is the return type of @c F constructed from a copy of @c error() .
797 template <
798 typename SelfType,
799 typename F,
804 value>> = nullptr>
805 static constexpr auto transform(SelfType&& self, F&& handle_value) {
806 using f_value_t =
809 if (self.has_value()) {
810 return result_t{
812 ::arene::base::invoke(
815 )
816 };
817 }
819 }
820 /// @brief deduced-this helper for @c result::transform<F>(F&&) .
821 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
822 /// @tparam F Type of the visiting functor. Must be invocable with @c value_type matching the const/ref qualification
823 /// of @c SelfType. May return any valid @c value_type
824 /// @param self the instance of the result to use.
825 /// @param handle_value the functor to invoke if @c self.has_value() is @c true .
826 /// @return result<void, error_type> which will be one of:
827 /// * A @c result<void,error_type> constructed from the result of invoking @c handle_value with the contents
828 /// of @c self.value()
829 /// * A @c result<void,error_type> constructed from a copy of @c error() .
830 template <
831 typename SelfType,
832 typename F,
837 value>> = nullptr>
838 static constexpr auto transform(SelfType&& self, F&& handle_value) {
839 using result_t = result<void, error_type>;
840 if (self.has_value()) {
841 ::arene::base::invoke(
844 );
845 return result_t{};
846 }
848 }
849 /// @}
850 // parasoft-end-suppress AUTOSAR-A2_10_1-d
851
852 ///
853 /// @brief deduced-this helper for @c result::transform_error<F>(F&&) .
854 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
855 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
856 /// of @c SelfType. May return any valid @c error_type .
857 /// @param self the instance of the result to use.
858 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
859 /// @return result<value_type, E> which will be either:
860 /// * A result constructed from the result of invoking @c handle_error with the contents of @c self.error() ,
861 /// * A result constructed from a copy of @c self.value() .
862 template <typename SelfType, typename F, constraints<std::enable_if<decays_to_v<SelfType, result>>> = nullptr>
863 static constexpr auto transform_error(SelfType&& self, F&& handle_error) {
864 using f_error_t =
867 if (self.has_error()) {
868 return result_t{
870 ::arene::base::invoke(
873 )
874 };
875 }
877 }
878}; // result<T,E>
879// parasoft-end-suppress AUTOSAR-A12_0_1-a-2
880// parasoft-end-suppress AUTOSAR-M14_5_3-a-2
881// parasoft-end-suppress AUTOSAR-A1_1_1-b-2
882// parasoft-end-suppress AUTOSAR-A10_2_1-b-2
883
884// parasoft-begin-suppress AUTOSAR-A10_2_1-b-2 "False Positive: Base class function made visible with 'using'"
885// parasoft-begin-suppress AUTOSAR-A1_1_1-b-2 "False Positive: Copy constructor is defined or deleted as appropriate"
886// parasoft-begin-suppress AUTOSAR-M14_5_3-a-2 "False Positive: Copy assignment is defined or deleted as appropriate"
887// parasoft-begin-suppress AUTOSAR-A12_0_1-a-2 "False Positive: Copy assignment is defined or deleted as appropriate"
888/// @brief Specialization of result<T, E> for void value types.
889/// @tparam E The error type
890template <class E>
891// NOLINTNEXTLINE(hicpp-special-member-functions) false-positive, it can't see through the non-constructible-dummy trick
893 /// @brief The type of the base class holding the storage
895
896 public:
897 // parasoft-begin-suppress AUTOSAR-A2_10_1-d-2 "False Positive: This identifier does not hide anything"
898 /// @brief The type when the @c result contains a value.
899 using value_type = void;
900 // parasoft-end-suppress AUTOSAR-A2_10_1-d-2
901
902 /// @brief The type when the @c result contains an error.
903 using error_type = E;
904
905 private:
906 static_assert(
908 "value_type must be an unqualified type, non-reference type."
909 );
910 static_assert(
912 "error_type must be an unqualified type, non-reference type."
913 );
914
915 static_assert(!std::is_same<error_type, void>::value, "void as an error_type is not supported");
916 static_assert(
918 "monostate as an error_type is not supported"
919 );
920
921 static_assert(std::is_object<error_type>::value, "error_type must be an object type (it must not be a reference).");
922
923 public:
924 ///
925 /// @brief Constructs a @c result with the value-channel engaged.
926 /// @post @c has_value() returns @c true
927 constexpr result() = default;
928
929 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
930 /// @brief Constructs a @c result with the value-channel engaged.
931 ///
932 /// @tparam P The type of the initializers. Must satisfy @c std::is_constructible<value_type,P&&...> .
933 /// @post @c has_value() returns @c true
934 // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
935 constexpr result(in_place_value_t) noexcept(noexcept(base_type(in_place_value, monostate{})))
937 /// @brief Constructs a @c result with the value-channel engaged. Provided for backwards compatibility.
938 ///
939 /// @tparam P The type of the initializers. Must satisfy @c std::is_constructible<value_type,P&&...> .
940 /// @post @c has_value() returns @c true
943 // parasoft-end-suppress CERT_C-EXP37-a-3
944
945 ///
946 /// @brief Constructs a @c result containing the @c error_type by way of direct-non-list-initialization.
947 ///
948 /// @tparam P The type of the initializers. Must satisfy @c std::is_constructible<error_type,P&&...> .
949 /// @param args The arguments to initialize the value channel with.
950 /// @post @c has_error() returns @c true
951 /// @post @c error() returns reference to an object equivalent to constructing @c error_type with @c args .
952 ///
953 /// Example Usage:
954 /// @snippet docs/examples/result_examples.cpp in_place_error_void
955 template <class... P, constraints<std::enable_if_t<std::is_constructible<error_type, P&&...>::value>> = nullptr>
956 // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
957 constexpr result(in_place_error_t, P&&... args) noexcept(noexcept(base_type(in_place_error, std::forward<P>(args)...))
958 )
960
961 /// @brief Default copy constructor
962 constexpr result(result const& copy) noexcept(noexcept(base_type(std::declval<result const&>()))) = default;
963 /// @brief Default move constructor
964 // NOLINTNEXTLINE(hicpp-noexcept-move) We want to exactly mimic the noexcept properties of ValueType and ErrorType.
965 constexpr result(result&& move) noexcept(noexcept(base_type(std::declval<result&&>()))) = default;
966 /// @brief Destroy the stored value or error
967 ~result() = default;
968
969 private:
970 /// @brief trait which detects if the result should be copy-assignable
971 static constexpr bool is_copy_assignable{
973 };
974
975 /// @brief The argument for the "copy assign" operator: @c result if the assignment is possible, @c
976 /// non_constructible_dummy if not
978 /// @brief The argument for the *deleted* "copy assign" operator: @c non_constructible_dummy if the assignment is
979 /// possible, @c result if not (so the copy assignment is deleted)
981
982 public:
983 /// @brief Copy-assignment for the case that @c error_type satisfies @c std::is_nothrow_copy_constructible and @c
984 /// std::is_nothrow_copy_assignable, otherwise a dummy assignment operator that can never be called
985 /// @param other The value to copy from
986 /// @return *this
987 constexpr auto operator=(copy_assign_arg const& other) noexcept -> result& {
988 if (&other != this) {
989 std::ignore = assign(other);
990 }
991 return *this;
992 }
993 /// @brief Deleted Copy-assignment if @c error_type does not satisfy @c std::is_nothrow_copy_constructible and @c
994 /// std::is_nothrow_copy_assignable, otherwise a deleted dummy assignment operator
995 /// @param other The value to copy from
996 /// @return *this
997 constexpr auto operator=(deleted_copy_assign_arg const& other) noexcept -> result& = delete;
998
999 private:
1000 /// @brief trait to detect if the result should be move-assignable
1001 static constexpr bool is_move_assignable{
1003 };
1004
1005 /// @brief The argument for the "move assign" operator: @c result if the assignment is possible, @c
1006 /// non_constructible_dummy if not
1008 /// @brief The argument for the *deleted* "move assign" operator: @c non_constructible_dummy if the assignment is
1009 /// possible, @c result if not (so the move assignment is deleted)
1011
1012 public:
1013 /// @brief Move-assignment for the case that @c error_type satisfies @c std::is_nothrow_move_constructible and @c
1014 /// std::is_nothrow_move_assignable, otherwise a dummy assignment operator that can never be called
1015 /// @param other The value to move from
1016 /// @return *this
1017 constexpr auto operator=(move_assign_arg&& other) noexcept -> result& {
1018 std::ignore = assign(std::move(other));
1019 return *this;
1020 }
1021 /// @brief Deleted Move-assignment if @c error_type does not satisfy @c std::is_nothrow_move_constructible and @c
1022 /// std::is_nothrow_move_assignable, otherwise a deleted dummy assignment operator
1023 /// @param other The value to move from
1024 /// @return *this
1025 constexpr auto operator=(deleted_move_assign_arg&& other) noexcept -> result& = delete;
1026
1027 // @brief Use @c has_value from base type
1028 using base_type::has_value;
1029
1030 // @brief Use @c has_value from base type
1031 using base_type::has_error;
1032
1033 // @brief Use boolean conversion from base type
1034 using base_type::operator bool;
1035
1036 /// @brief Access the content of the value channel.
1037 ///
1038 /// @pre has_value(), else ARENE_PRECONDITION violation.
1039 constexpr void operator*() const& noexcept { return value(); }
1040
1041 /// @brief Access the content of the value channel.
1042 ///
1043 /// @pre has_value(), else ARENE_PRECONDITION violation.
1044 constexpr void value() const& noexcept { ARENE_PRECONDITION(this->has_value()); }
1045 /// @brief Access the content of the value channel.
1046 ///
1047 /// @pre has_value(), else ARENE_PRECONDITION violation.
1048 constexpr void value() && noexcept { ARENE_PRECONDITION(this->has_value()); }
1049
1050 // parasoft-begin-suppress AUTOSAR-A2_7_3-a-2 "False positive: All overloads are fully are documented"
1051 // parasoft-begin-suppress AUTOSAR-A2_7_3-b-2 "False positive: All overloads are fully are documented"
1052 /// @brief Accesses a reference to the content of the error channel.
1053 ///
1054 /// @pre has_error(), else ARENE_PRECONDITION violation
1055 /// @return A reference to the contained error
1056 /// @{
1057 // parasoft-begin-suppress AUTOSAR-A9_3_1-a-2 "False positive: This class is a container of the value"
1058 ARENE_NODISCARD constexpr auto error() & noexcept -> error_type& {
1059 ARENE_PRECONDITION(this->has_error());
1060 return this->storage().unsafe_error();
1061 }
1062 // parasoft-end-suppress AUTOSAR-A9_3_1-a-2
1063 ARENE_NODISCARD constexpr auto error() const& noexcept -> error_type const& {
1064 ARENE_PRECONDITION(this->has_error());
1065 return this->storage().unsafe_error();
1066 }
1067 // parasoft-begin-suppress AUTOSAR-A9_3_1-a-2 "False positive: This class is a container of the value"
1068 ARENE_NODISCARD constexpr auto error() && noexcept -> error_type&& {
1069 ARENE_PRECONDITION(this->has_error());
1070 return std::move(this->storage().unsafe_error());
1071 }
1072 // parasoft-end-suppress AUTOSAR-A9_3_1-a-2
1073 // parasoft-begin-suppress AUTOSAR-A18_9_3-a-2 "We want to ensure the qualifier is preserved"
1074 ARENE_NODISCARD constexpr auto error() const&& noexcept -> error_type const&& {
1075 ARENE_PRECONDITION(this->has_error());
1076 return std::move(this->storage().unsafe_error());
1077 }
1078 // parasoft-end-suppress AUTOSAR-A18_9_3-a-2
1079 /// @}
1080 // parasoft-end-suppress AUTOSAR-A2_7_3-b-2
1081 // parasoft-end-suppress AUTOSAR-A2_7_3-a-2
1082
1083 ///
1084 /// @brief Swaps the state of two results.
1085 ///
1086 /// @tparam SourceErrorType Must satisfy @c is_swappable_v<error_type> and @c
1087 /// std::is_nothrow_move_constructable<error_type>
1088 /// @param other The result to swap with
1089 /// @post If both @c this and @c other have matching channels populated, the content of those channels are swapped as
1090 /// if via @c arene::base::swap . Otherwise, it is equivalent to emplacing @c this with the active channel
1091 /// from @c other , and vice-versa.
1092 ///
1093 template <
1094 typename SourceErrorType = E,
1099 if (this->has_value()) {
1100 if (other.has_value()) {
1101 // swapping voids isn't meaningful
1102 return;
1103 }
1104 static_cast<void>(this->emplace(in_place_error, std::move(other.storage().unsafe_error())));
1106 } else if (this->has_error()) {
1107 if (other.has_error()) {
1109 } else {
1110 static_cast<void>(other.emplace(in_place_error, std::move(this->storage().unsafe_error())));
1111 this->emplace(in_place_value);
1112 }
1113 } else {
1114 // nothing to do
1115 }
1116 }
1117
1118 // parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "Hidden friends permitted by A11-3-1 Permit #2"
1119 /// @brief Swaps the state of two results.
1120 ///
1121 /// @tparam SourceErrorType Must satisfy @c is_swappable_v<error_type> and @c
1122 /// std::is_nothrow_move_constructable<error_type>
1123 /// @param lhs The left hand result to swap
1124 /// @param rhs The right hand result to swap
1125 /// @post If both @c lhs and @c rhs have matching channels populated, the content of those channels are swapped as
1126 /// if via @c arene::base::swap . Otherwise, it is equivalent to move-assigning @c lhs with the active channel
1127 /// from @c rhs , and vise-versa.
1128 ///
1129 template <
1130 typename SourceErrorType = E,
1134 friend constexpr void swap(result& lhs, result& rhs) noexcept(noexcept(lhs.swap(rhs))) {
1135 lhs.swap(rhs);
1136 }
1137 // parasoft-end-suppress AUTOSAR-A11_3_1-a-2
1138
1139 // imports emplace from result_base.
1140 using base_type::emplace;
1141
1142 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
1143 ///
1144 /// @brief Emplaces the void value into the result
1145 /// @post @c has_value() returns @c true .
1146 ///
1147 void emplace(in_place_value_t) noexcept {
1148 this->reset();
1149 this->discriminator() = result_detail::discriminator_type::holds_value;
1150 ::arene::base::construct_at(std::addressof(this->storage().unsafe_value()), monostate{});
1151 }
1152 // parasoft-end-suppress CERT_C-EXP37-a-3
1153
1154 // parasoft-begin-suppress AUTOSAR-A2_7_3-a-2 "False positive: All overloads are fully are documented"
1155 // parasoft-begin-suppress AUTOSAR-A2_7_3-b-2 "False positive: All overloads are fully are documented"
1156 /// @brief Monadic API which invokes a functor with the contents of @c value() if the value channel is populated.
1157 ///
1158 /// @tparam F Type of the visiting functor. Must be invocable with @c value_type matching the const/ref qualification
1159 /// of @c SelfType , or with no arguments if @c value_type is @c void , and return @c result<U,error_type> ,
1160 /// where
1161 /// @c U may be any valid @c value_type .
1162 /// @param handle_value the functor to invoke if @c self.has_value() is @c true .
1163 /// @return result<U, error_type> which will be either the result of invoking @c handle_value with the contents of
1164 /// @c self.value() , or it will contain a copy of @c self.error() .
1165 ///
1166 /// Basic usage example for opening a file:
1167 /// @snippet docs/examples/result_examples.cpp and_then
1168 ///
1169 /// After this statement, @c maybe_file will contain either a valid instance of @c arene::base::file_handle in the
1170 /// value channel, or it will contain an instance of @c arene::base::error_code representing either the failure to
1171 /// open the file or the failure to open the directory.
1172 ///
1173 /// @{
1174 template <typename F>
1175 constexpr auto and_then(F&& handle_value) & {
1176 return result::and_then(*this, std::forward<F>(handle_value));
1177 }
1178 template <typename F>
1179 constexpr auto and_then(F&& handle_value) const& {
1180 return result::and_then(*this, std::forward<F>(handle_value));
1181 }
1182 template <typename F>
1183 constexpr auto and_then(F&& handle_value) && {
1184 return result::and_then(std::move(*this), std::forward<F>(handle_value));
1185 }
1186 template <typename F>
1187 constexpr auto and_then(F&& handle_value) const&& {
1188 return result::and_then(std::move(*this), std::forward<F>(handle_value));
1189 }
1190 /// @}
1191 // parasoft-end-suppress AUTOSAR-A2_7_3-b-2
1192 // parasoft-end-suppress AUTOSAR-A2_7_3-a-2
1193
1194 // parasoft-begin-suppress AUTOSAR-A2_7_3-a-2 "False positive: All overloads are fully are documented"
1195 // parasoft-begin-suppress AUTOSAR-A2_7_3-b-2 "False positive: All overloads are fully are documented"
1196 /// @brief Monadic API which invokes a functor with the contents of @c error() if the error channel is populated.
1197 ///
1198 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
1199 /// of @c SelfType and return @c result<value_type,E> , where @c E may be any valid @c error_type .
1200 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
1201 /// @return result<value_type, E> which will be either the result of invoking @c handle_error with the contents of
1202 /// @c self.error() , or it will contain a copy of @c self.value() .
1203 ///
1204 /// Basic usage example for opening a directory:
1205 /// @snippet docs/examples/result_examples.cpp or_else
1206 ///
1207 /// After this statement, @c maybe_dir will contain either a valid instance of @c arene::base::directory_handle in
1208 /// the value channel, or it will have logged the error and contain the passed through @c error_code .
1209 ///
1210 /// @{
1211 template <typename F>
1212 constexpr auto or_else(F&& handle_error) & {
1213 return result::or_else(*this, std::forward<F>(handle_error));
1214 }
1215 template <typename F>
1216 constexpr auto or_else(F&& handle_error) const& {
1217 return result::or_else(*this, std::forward<F>(handle_error));
1218 }
1219 template <typename F>
1220 constexpr auto or_else(F&& handle_error) && {
1221 return result::or_else(std::move(*this), std::forward<F>(handle_error));
1222 }
1223 template <typename F>
1224 constexpr auto or_else(F&& handle_error) const&& {
1225 return result::or_else(std::move(*this), std::forward<F>(handle_error));
1226 }
1227 /// @}
1228 // parasoft-end-suppress AUTOSAR-A2_7_3-b-2
1229 // parasoft-end-suppress AUTOSAR-A2_7_3-a-2
1230
1231 // parasoft-begin-suppress AUTOSAR-A2_7_3-a-2 "False positive: All overloads are fully are documented"
1232 // parasoft-begin-suppress AUTOSAR-A2_7_3-b-2 "False positive: All overloads are fully are documented"
1233 // parasoft-begin-suppress AUTOSAR-A2_10_1-d "False positive: it is not hiding anything"
1234 /// @brief Calls a provided functor with the value channel if it is populated, and produces a new result with the
1235 /// return from it.
1236 /// @tparam F Type of the visiting functor. Must be invocable with @c value_type matching the const/ref qualification
1237 /// of @c this , or with no arguments if @c value_type is @c void . May return any valid @c value_type
1238 /// @param handle_value the functor to invoke if @c has_value() is @c true .
1239 /// @return result<U, error_type> which will be one of:
1240 /// * A @c result<U,error_type> constructed from the result of invoking @c handle_value if the return from
1241 /// @c F is not @c void
1242 /// * A @c result<void,error_type> constructed from the result of invoking @c handle_value if the return from
1243 /// @c F is @c void
1244 /// * A @c result<U,error_type> where @c U is the return type of @c F constructed from a copy of
1245 /// @c self.error() .
1246 /// @{
1247 template <typename F>
1248 constexpr auto transform(F&& handle_value) & {
1249 return result::transform(*this, std::forward<F>(handle_value));
1250 }
1251 template <typename F>
1252 constexpr auto transform(F&& handle_value) const& {
1253 return result::transform(*this, std::forward<F>(handle_value));
1254 }
1255 template <typename F>
1256 constexpr auto transform(F&& handle_value) && {
1257 return result::transform(std::move(*this), std::forward<F>(handle_value));
1258 }
1259 // parasoft-begin-suppress AUTOSAR-A18_9_3-a-2 "We want to ensure the qualifier is preserved"
1260 template <typename F>
1261 constexpr auto transform(F&& handle_value) const&& {
1262 return result::transform(std::move(*this), std::forward<F>(handle_value));
1263 }
1264 // parasoft-end-suppress AUTOSAR-A18_9_3-a-2
1265 /// @}
1266 // parasoft-end-suppress AUTOSAR-A2_7_3-b-2
1267 // parasoft-end-suppress AUTOSAR-A2_7_3-a-2
1268 // parasoft-end-suppress AUTOSAR-A2_10_1-d
1269
1270 /// @brief Calls a provided functor with the error channel if it is populated, and produces a new result with the
1271 /// return from it.
1272 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
1273 /// of @c this. May return any valid @c error_type .
1274 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
1275 /// @return result<value_type, E> which will be either:
1276 /// * A result constructed from the result of invoking @c handle_error with the contents of @c self.error() ,
1277 /// * A result constructed from a copy of @c self.value() .
1278 /// Basic usage example for opening a directory:
1279 /// @snippet docs/examples/result_examples.cpp transform_error
1280 ///
1281 /// After this statement, @c maybe_dir will contain either a valid instance of @c arene::base::directory_handle in
1282 /// the value channel, or it will have logged the error and contain the passed through @c error_code .
1283 template <typename F>
1284 constexpr auto transform_error(F&& handle_error) & {
1285 return result::transform_error(*this, std::forward<F>(handle_error));
1286 }
1287 /// @brief Calls a provided functor with the error channel if it is populated, and produces a new result with the
1288 /// return from it.
1289 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
1290 /// of @c this. May return any valid @c error_type .
1291 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
1292 /// @return result<value_type, E> which will be either:
1293 /// * A result constructed from the result of invoking @c handle_error with the contents of @c self.error() ,
1294 /// * A result constructed from a copy of @c self.value() .
1295 /// Basic usage example for opening a directory:
1296 /// @snippet docs/examples/result_examples.cpp transform_error
1297 ///
1298 /// After this statement, @c maybe_dir will contain either a valid instance of @c arene::base::directory_handle in
1299 /// the value channel, or it will have logged the error and contain the passed through @c error_code .
1300 template <typename F>
1301 constexpr auto transform_error(F&& handle_error) const& {
1302 return result::transform_error(*this, std::forward<F>(handle_error));
1303 }
1304 /// @brief Calls a provided functor with the error channel if it is populated, and produces a new result with the
1305 /// return from it.
1306 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
1307 /// of @c this. May return any valid @c error_type .
1308 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
1309 /// @return result<value_type, E> which will be either:
1310 /// * A result constructed from the result of invoking @c handle_error with the contents of @c self.error() ,
1311 /// * A result constructed from a copy of @c self.value() .
1312 /// Basic usage example for opening a directory:
1313 /// @snippet docs/examples/result_examples.cpp transform_error
1314 ///
1315 /// After this statement, @c maybe_dir will contain either a valid instance of @c arene::base::directory_handle in
1316 /// the value channel, or it will have logged the error and contain the passed through @c error_code .
1317 template <typename F>
1318 constexpr auto transform_error(F&& handle_error) && {
1319 return result::transform_error(std::move(*this), std::forward<F>(handle_error));
1320 }
1321 /// @brief Calls a provided functor with the error channel if it is populated, and produces a new result with the
1322 /// return from it.
1323 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
1324 /// of @c this. May return any valid @c error_type .
1325 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
1326 /// @return result<value_type, E> which will be either:
1327 /// * A result constructed from the result of invoking @c handle_error with the contents of @c self.error() ,
1328 /// * A result constructed from a copy of @c self.value() .
1329 /// Basic usage example for opening a directory:
1330 /// @snippet docs/examples/result_examples.cpp transform_error
1331 ///
1332 /// After this statement, @c maybe_dir will contain either a valid instance of @c arene::base::directory_handle in
1333 /// the value channel, or it will have logged the error and contain the passed through @c error_code .
1334 template <typename F>
1335 constexpr auto transform_error(F&& handle_error) const&& {
1336 return result::transform_error(std::move(*this), std::forward<F>(handle_error));
1337 }
1338
1339 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function used in other TUs"
1340 // parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Conditionally noexcept based on underlying comparison"
1341 // parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "False positive: comparison operators are permitted"
1342 /// @brief Compare two results for equality.
1343 /// @param lhs The first result
1344 /// @param rhs The second result
1345 /// @return bool @c true if the both @c lhs and @c rhs hold values that are equal, or both hold errors that are
1346 /// equal, @c false otherwise
1347 ARENE_NODISCARD friend constexpr auto operator==(result const& lhs, result const& rhs) noexcept(
1348 noexcept(lhs.has_error(rhs.error()))
1349 ) -> bool {
1350 static_assert(is_equality_comparable_v<error_type>, "Error type must be equality comparable");
1351 if (lhs.has_value()) {
1352 return rhs.has_value();
1353 }
1354 return rhs.has_error(lhs.storage().unsafe_error());
1355 }
1356 // parasoft-end-suppress AUTOSAR-A11_3_1-a-2
1357 // parasoft-end-suppress AUTOSAR-A13_5_5-b-2
1358 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
1359
1360 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function used in other TUs"
1361 // parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Conditionally noexcept based on underlying comparison"
1362 // parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "False positive: comparison operators are permitted"
1363 /// @brief Compare two results for inequality.
1364 /// @param lhs The first result
1365 /// @param rhs The second result
1366 /// @return bool @c true if the both @c lhs and @c rhs hold values that are not equal, or both hold errors that are
1367 /// not equal, or one holds a value and the other holds an error, @c false otherwise
1368 ARENE_NODISCARD friend constexpr auto operator!=(result const& lhs, result const& rhs) noexcept(noexcept(lhs == rhs))
1369 -> bool {
1370 return !(lhs == rhs);
1371 }
1372 // parasoft-end-suppress AUTOSAR-A11_3_1-a-2
1373 // parasoft-end-suppress AUTOSAR-A13_5_5-b-2
1374 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
1375
1376 private:
1377 /// @brief Helper for implementing assignment which handles copy/move.
1378 /// @tparam OtherType the result type to assign from. @c OtherType::error_type must be nothrow constructible and
1379 /// nothrow
1380 /// assignable to @c error_type respectably.
1381 /// @param other the result to assign from.
1382 /// @post The state of @c this will be as follows:
1383 /// * If both @c this and @c other 's value channels are populated, it is a noop.
1384 /// * If both @c this and @c other 's error channels are populated, then @c this will have its error channel's
1385 /// state set as if via assignment from @c other 's error channel.
1386 /// * OtherTypewise, @c this will have its state set as if @c emplace 'd with the active channel of @c other .
1387 /// @return result& A reference to @c this post assignment.
1388 template <typename OtherType, constraints<std::enable_if_t<decays_to_v<OtherType, result>>> = nullptr>
1389 constexpr auto assign(OtherType&& other) noexcept -> result& {
1390 if (this->has_value()) {
1391 if (other.has_value()) {
1392 // assignment from two void values isn't meaningful, so nothing to do.
1393 return *this;
1394 }
1395 std::ignore = this->emplace(
1398 );
1399 return *this;
1400 }
1401 if (other.has_error()) {
1403 return *this;
1404 }
1405 // we switch ourselves to void.
1406 this->emplace(in_place_value);
1407 return *this;
1408 }
1409
1410 ///
1411 /// @brief deduced-this helper for @c result::and_then<F>(F&&) .
1412 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
1413 /// @tparam F Type of the visiting functor. Must be invocable no arguments, and return @c result<U,error_type> , where
1414 /// @c U may be any valid @c value_type .
1415 /// @param self the instance of the result to use.
1416 /// @param handle_value the functor to invoke if @c self.has_value() is @c true .
1417 /// @return result<U, error_type> which will be either the result of invoking @c handle_value , or it will contain a
1418 /// copy of @c self.error() .
1419 template <typename SelfType, typename F, constraints<std::enable_if<decays_to_v<SelfType, result>>> = nullptr>
1420 static constexpr auto and_then(SelfType&& self, F&& handle_value) {
1421 using f_result_t = invoke_result_t<F>;
1422 static_assert(is_instantiation_of_v<f_result_t, ::arene::base::result>, "handle_value must return a result!");
1423 static_assert(
1425 "The result returned from handle_value's error channel must be the same as this result's error channel"
1426 );
1427 if (self.has_value()) {
1428 return ::arene::base::invoke(std::forward<F>(handle_value));
1429 }
1431 }
1432
1433 ///
1434 /// @brief deduced-this helper for @c result::or_else<F>(F&&) .
1435 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
1436 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
1437 /// of @c SelfType and return @c result<void,E> , where @c E may be any valid @c error_type .
1438 /// @param self the instance of the result to use.
1439 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
1440 /// @return result<void, E> which will be either the result of invoking @c handle_error with the contents of
1441 /// @c self.error() , or it will have its value channel populated .
1442 template <typename SelfType, typename F, constraints<std::enable_if<decays_to_v<SelfType, result>>> = nullptr>
1443 static constexpr auto or_else(SelfType&& self, F&& handle_error) {
1444 using f_result_t =
1446 static_assert(is_instantiation_of_v<f_result_t, ::arene::base::result>, "handle_error must return a result!");
1447 static_assert(
1449 "The result returned from handle_error's value channel must be the same as this result's value channel"
1450 );
1451 if (self.has_error()) {
1452 return ::arene::base::invoke(
1455 );
1456 }
1457 return f_result_t{};
1458 }
1459
1460 // parasoft-begin-suppress AUTOSAR-A2_10_1-d "False positive: it is not hiding anything"
1461 /// @brief deduced-this helper for @c result::transform<F>(F&&) .
1462 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
1463 /// @tparam F Type of the visiting functor. Must be invocable with @c value_type matching the const/ref qualification
1464 /// of @c SelfType , or with no arguments if @c value_type is @c void . May return any valid @c value_type
1465 /// @param self the instance of the result to use.
1466 /// @param handle_value the functor to invoke if @c self.has_value() is @c true .
1467 /// @return result<U, error_type> where @c U is the return type of @c F , which will be one of:
1468 /// * A @c result<U,error_type> constructed from the result of invoking @c handle_value if @c self.has_value()
1469 /// is @c true
1470 /// * A @c result<U,error_type> constructed from a copy of @c self.error() otherwise.
1471 template <
1472 typename SelfType,
1473 typename F,
1476 std::enable_if_t<!std::is_void<invoke_result_t<F>>::value>> = nullptr>
1477 static constexpr auto transform(SelfType&& self, F&& handle_value) {
1478 using f_value_t = invoke_result_t<F>;
1480 if (self.has_value()) {
1482 }
1484 }
1485
1486 /// @brief deduced-this helper for @c result::transform<F>(F&&) .
1487 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
1488 /// @tparam F Type of the visiting functor. Must be invocable with @c value_type matching the const/ref qualification
1489 /// of @c SelfType , or with no arguments if @c value_type is @c void . May return any valid @c value_type
1490 /// @param self the instance of the result to use.
1491 /// @param handle_value the functor to invoke if @c self.has_value() is @c true .
1492 /// @return result<void, error_type> which will be one of:
1493 /// * A default-constructed @c result<void,error_type> if @c self.has_value() is @c true
1494 /// * A @c result<void,error_type> constructed from a copy of @c self.error() otherwise.
1495 template <
1496 typename SelfType,
1497 typename F,
1500 std::enable_if_t<std::is_void<invoke_result_t<F>>::value>> = nullptr>
1501 static constexpr auto transform(SelfType&& self, F&& handle_value) {
1502 using result_t = result<void, error_type>;
1503 if (self.has_value()) {
1505 return result_t{};
1506 }
1508 }
1509 // parasoft-end-suppress AUTOSAR-A2_10_1-d
1510
1511 ///
1512 /// @brief deduced-this helper for @c result::transform_error<F>(F&&) .
1513 /// @tparam SelfType The qualified result type to invoke with. Must satisfy @c decays_to<SelfType,result>
1514 /// @tparam F Type of the visiting functor. Must be invocable with @c error_type matching the const/ref qualification
1515 /// of @c SelfType. May return any valid @c error_type .
1516 /// @param self the instance of the result to use.
1517 /// @param handle_error the functor to invoke if @c self.has_error() is @c true .
1518 /// @return result<value_type, E> which will be either:
1519 /// * A result constructed from the result of invoking @c handle_error with the contents of @c self.error() ,
1520 /// * A result constructed from a copy of @c self.value() .
1521 template <typename SelfType, typename F, constraints<std::enable_if<decays_to_v<SelfType, result>>> = nullptr>
1522 static constexpr auto transform_error(SelfType&& self, F&& handle_error) {
1523 using f_error_t =
1525 using result_t = result<void, f_error_t>;
1526 if (self.has_error()) {
1527 return result_t{
1529 ::arene::base::invoke(
1532 )
1533 };
1534 }
1535 return result_t{};
1536 }
1537}; // result<void,E>
1538// parasoft-end-suppress AUTOSAR-A12_0_1-a-2
1539// parasoft-end-suppress AUTOSAR-M14_5_3-a-2
1540// parasoft-end-suppress AUTOSAR-A1_1_1-b-2
1541// parasoft-end-suppress AUTOSAR-A10_2_1-b-2
1542
1543// parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1544/// @brief Visit the contained value or error with two independent functors.
1545/// @tparam ResultType The type of the @c result object to visit.
1546/// @tparam OnValue The type of the invocable to invoke if the @c result holds a value . Must satisfy @c is_invocable
1547/// with the result of @c self.value() , and must have the same return type as @c OnValue .
1548/// @tparam OnError The type of the invocable to invoke if the @c result holds an error. Must satisfy @c is_invocable
1549/// with the result of @c self.error() , and must have the same return type as @c OnValue .
1550/// @param self The @c result object
1551/// @param on_expected The invocable to invoke if @c self holds a value
1552/// @param on_unexpected The invocable to invoke if @c self holds an error
1553/// @return auto The result of invoking the appropriate invocable
1554///
1555/// Example Usage:
1556/// @snippet docs/examples/result_examples.cpp expand_result
1557template <
1558 class ResultType,
1559 class OnValue,
1560 class OnError,
1565 invoke_result_t<OnError, decltype(std::declval<ResultType>().error())>>::value>> = nullptr>
1566constexpr auto expand_result(
1567 ResultType&& self,
1570) noexcept(is_nothrow_invocable_v<OnValue, decltype(std::declval<ResultType>().value())>&&
1571 is_nothrow_invocable_v<OnError, decltype(std::declval<ResultType>().error())>) -> decltype(auto) {
1572 if (self.has_value()) {
1574 }
1576}
1577// parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1578
1579///
1580/// @brief Intermediary type for constructing a @c result with a given @c value_type .
1581/// @note Generally this should not be constructed manually; it intended as a transient type that allow to construct a
1582/// @c result Object while using type deduction for @c value_type and @c error_type .
1583/// @tparam ValueType the @c value_type of a @c result constructed from this type.
1584/// @see @c arene::base::value_result for the factory function that should be used in user code.
1585/// @{
1586template <typename ValueType>
1588 public:
1589 // parasoft-begin-suppress AUTOSAR-A13_5_2-a-2 "Implicit conversion to result is part of the API"
1590 // parasoft-begin-suppress AUTOSAR-A13_2_3-a-2 "False positive: Not a relational operator"
1591 /// @brief Instantiates a @c result<ValueType,Error> from the contained value instance. Consumes the container.
1592 /// @tparam Error the @c error_type of the produced @c result .
1593 template <typename Error>
1594 // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
1595 constexpr operator result<ValueType, Error>(
1596 ) const& noexcept(noexcept(result<ValueType, Error>(in_place_value, std::declval<ValueType const&>()))) {
1597 return {in_place_value, value_};
1598 }
1599 /// @brief Instantiates a @c result<ValueType,Error> from the contained value instance. Consumes the container.
1600 /// @tparam Error the @c error_type of the produced @c result .
1601 template <typename Error>
1602 // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
1603 constexpr operator result<ValueType, Error>(
1604 ) && noexcept(noexcept(result<ValueType, Error>(in_place_value, std::declval<ValueType&&>()))) {
1605 return {in_place_value, std::move(value_)};
1606 }
1607 // parasoft-end-suppress AUTOSAR-A13_2_3-a-2
1608 // parasoft-end-suppress AUTOSAR-A13_5_2-a-2
1609
1610 /// @brief Construct the stored value from the specified arguments
1611 /// @tparam ArgTypes the types of the arguments
1612 /// @param args The arguments
1613 template <
1614 typename... ArgTypes,
1616 nullptr>
1617 // NOLINTNEXTLINE(hicpp-explicit-conversions)
1620
1621 // parasoft-begin-suppress AUTOSAR-A13_3_1-a-2 "False positive: Constructor constrained via SFINAE is permitted"
1622 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
1623 /// @brief Copy constructor
1624 constexpr value_result_t(value_result_t const&) = default;
1625 // parasoft-end-suppress AUTOSAR-A13_3_1-a-2
1626
1627 /// @brief Move constructor
1628 constexpr value_result_t(value_result_t&&) = default;
1629
1630 /// @brief Copy assignment
1631 constexpr auto operator=(value_result_t const&) -> value_result_t& = default;
1632 /// @brief Move constructor
1633 constexpr auto operator=(value_result_t&&) -> value_result_t& = default;
1634 // parasoft-end-suppress CERT_C-EXP37-a-3
1635
1636 /// @brief destructor
1637 ~value_result_t() = default;
1638
1639 private:
1640 /// @brief The contained value
1641 ValueType value_;
1642};
1643
1644/// @brief Intermediary type for constructing a @c result with a @c void value
1645/// @note Generally this should not be constructed manually; it intended as a transient type that allow to construct a
1646/// @c result Object while using type deduction for @c value_type and @c error_type .
1647/// @see @c arene::base::value_result for the factory function that should be used in user code.
1648template <>
1649class value_result_t<void> {
1650 public:
1651 // parasoft-begin-suppress AUTOSAR-A13_5_2-a-2 "Implicit conversion to result is part of the API"
1652 // parasoft-begin-suppress AUTOSAR-A13_2_3-a-2 "False positive: Not a relational operator"
1653 /// @brief Instantiates a @c result<Value,Error> from the contained value instance. Consumes the container.
1654 /// @tparam Error the @c error_type of the produced @c result .
1655 template <typename Error>
1656 // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
1657 constexpr operator result<void, Error>() noexcept {
1658 return {};
1659 }
1660 // parasoft-end-suppress AUTOSAR-A13_2_3-a-2
1661 // parasoft-end-suppress AUTOSAR-A13_5_2-a-2
1662};
1663/// @}
1664
1665///
1666/// @brief Intermediary type for constructing a @c result with a given @c error_type .
1667/// @note Generally this should not be constructed manually; it intended as a transient type that allow to construct a
1668/// @c result Object while using type deduction for @c value_type and @c error_type .
1669/// @tparam ErrorType the @c error_type of a @c result constructed from this type.
1670/// @see @c arene::base::error_result for the factory function that should be used in user code.
1671template <typename ErrorType>
1673 public:
1674 // parasoft-begin-suppress AUTOSAR-A13_5_2-a-2 "Implicit conversion to result is part of the API"
1675 // parasoft-begin-suppress AUTOSAR-A13_2_3-a-2 "False positive: Not a relational operator"
1676 /// @brief Instantiates a @c result<Value,ErrorType> from the contained error instance.
1677 /// @tparam Value the @c value_type of the produced @c result .
1678 template <typename Value>
1679 // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
1680 constexpr operator result<Value, ErrorType>(
1681 ) const& noexcept(noexcept(result<Value, ErrorType>(in_place_error, std::declval<ErrorType const&>()))) {
1682 return {in_place_error, error_};
1683 }
1684 /// @brief Instantiates a @c result<Value,ErrorType> from the contained error instance, moving the error value into
1685 /// the @c result
1686 /// @tparam Value the @c value_type of the produced @c result .
1687 template <typename Value>
1688 // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
1689 constexpr operator result<Value, ErrorType>(
1690 ) && noexcept(noexcept(result<Value, ErrorType>(in_place_error, std::declval<ErrorType&&>()))) {
1691 return {in_place_error, std::move(error_)};
1692 }
1693 // parasoft-end-suppress AUTOSAR-A13_2_3-a-2
1694 // parasoft-end-suppress AUTOSAR-A13_5_2-a-2
1695
1696 /// @brief Construct the stored error from the specified arguments
1697 /// @tparam ArgTypes the types of the arguments
1698 /// @param args The arguments
1699 template <
1700 typename... ArgTypes,
1702 nullptr>
1703 // NOLINTNEXTLINE(hicpp-explicit-conversions)
1706
1707 // parasoft-begin-suppress AUTOSAR-A13_3_1-a-2 "False positive: Constructor constrained via SFINAE is permitted"
1708 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
1709 /// @brief Copy constructor
1710 constexpr error_result_t(error_result_t const&) = default;
1711 // parasoft-end-suppress AUTOSAR-A13_3_1-a-2
1712
1713 /// @brief Move constructor
1714 constexpr error_result_t(error_result_t&&) = default;
1715
1716 /// @brief Copy assignment
1717 constexpr auto operator=(error_result_t const&) -> error_result_t& = default;
1718 /// @brief Move constructor
1719 constexpr auto operator=(error_result_t&&) -> error_result_t& = default;
1720 // parasoft-end-suppress CERT_C-EXP37-a-3
1721
1722 /// @brief destructor
1723 ~error_result_t() = default;
1724
1725 private:
1726 /// @brief The contained error
1727 ErrorType error_;
1728};
1729
1730// parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1731// parasoft-begin-suppress AUTOSAR-A2_10_1-a-2 "False positive: No global or namespace entity named 'value'"
1732///
1733/// @brief Convenience function to construct a @c result<ValueType,Error> containing the @c ValueType from any
1734/// reference.
1735///
1736/// Example Usage:
1737/// @snippet docs/examples/result_examples.cpp value_result
1738///
1739/// @tparam ValueType the @c value_type of the produced result.
1740/// @param value value to instantiate the @c result with.
1741/// @return value_result_t An object which is move-convertible to any @c result<ValueType,Error> .
1742template <typename ValueType>
1748// parasoft-end-suppress AUTOSAR-A2_10_1-a-2
1749// parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1750
1751///
1752/// @brief Convenience function to construct a @c result<void,Error> .
1753///
1754/// Example Usage:
1755/// @snippet docs/examples/result_examples.cpp value_result_void
1756///
1757/// @return value_result_t An object which is move-convertible to any @c result<void,Error> .
1758inline constexpr auto value_result() noexcept -> value_result_t<void> { return {}; }
1759
1760// parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1761// parasoft-begin-suppress AUTOSAR-A2_10_1-a-2 "False positive: No global or namespace entity named 'error'"
1762/// @brief Convenience function to construct a @c result<Value,ErrorType> containing the @c ErrorType from any
1763/// reference.
1764///
1765/// Example Usage:
1766/// @snippet docs/examples/result_examples.cpp error_result
1767///
1768/// @tparam ErrorType the @c error_type of the produced result.
1769/// @param error error to instantiate the @c result with.
1770/// @return error_result_t An object which is move-convertible to any @c result<Value,ErrorType> .
1771template <typename ErrorType>
1777// parasoft-end-suppress AUTOSAR-A2_10_1-a-2
1778// parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1779
1780} // namespace base
1781} // namespace arene
1782
1783// parasoft-begin-suppress AUTOSAR-A17_6_1-a-2 "False positive: specialization of standard templates is permitted"
1784// parasoft-begin-suppress CERT_CPP-DCL58-a-2 "False positive: specialization of standard templates is permitted"
1785namespace std {
1786
1787// parasoft-begin-suppress AUTOSAR-A11_0_2-a-2 "False positive: must follow the primary template"
1788/// @brief Specialization of @c std::hash for @c arene::base::result
1789///
1790/// @tparam V the type of the value channel. @c std::hash<V> must be well-formed for this specialization to be
1791/// well-formed.
1792/// @tparam E the type of the error channel. @c std::hash<E> must be well-formed for this specialization to be
1793/// well-formed.
1794///
1795template <typename V, typename E>
1796struct hash<::arene::base::result<V, E>> {
1797 // parasoft-begin-suppress AUTOSAR-A18_1_6-a "False positive: The declaration does have a noexcept specifier"
1798 // parasoft-begin-suppress AUTOSAR-A2_10_1-a-2 "False positive: No global or namespace entity named 'value'"
1799 /// @brief Calculate the hash of a @c result
1800 /// @param value The instance of @c result to hash
1801 /// @return The result of hashing the stored value if @c value has a value, the result of hashing the stored error
1802 /// otherwise
1803 constexpr auto operator()(::arene::base::result<V, E> const& value) const
1804 noexcept(noexcept(hash<E>{}(std::declval<E const&>())) && noexcept(hash<V>{}(std::declval<V const&>())))
1805 -> std::size_t {
1806 return value.has_value() ? hash<V>{}(value.value()) : hash<E>{}(value.error());
1807 }
1808 // parasoft-end-suppress AUTOSAR-A2_10_1-a-2
1809 // parasoft-end-suppress AUTOSAR-A18_1_6-a-2
1810};
1811// parasoft-end-suppress AUTOSAR-A11_0_2-a-2
1812
1813// parasoft-begin-suppress AUTOSAR-A11_0_2-a-2 "False positive: must follow the primary template"
1814/// @brief Specialization of @c std::hash for @c arene::base::result<void, E>
1815///
1816/// @tparam E the type of the error channel. @c std::hash<E> must be well-formed for this specialization to be
1817/// well-formed.
1818///
1819template <typename E>
1820struct hash<::arene::base::result<void, E>> {
1821 // parasoft-begin-suppress AUTOSAR-A18_1_6-a "False positive: The declaration does have a noexcept specifier"
1822 // parasoft-begin-suppress AUTOSAR-A2_10_1-a-2 "False positive: No global or namespace entity named 'value'"
1823 /// @brief Calculate the hash of a @c result
1824 /// @param value The instance of @c result to hash
1825 /// @return The result of hashing @c monostate if @c value has a value, the result of hashing the stored error
1826 /// otherwise
1827 constexpr auto operator()(::arene::base::result<void, E> const& value) const
1828 noexcept(noexcept(hash<E>{}(std::declval<E const&>()))) -> std::size_t {
1829 return value.has_value() ? hash<::arene::base::monostate>{}({}) : hash<E>{}(value.error());
1830 }
1831 // parasoft-end-suppress AUTOSAR-A2_10_1-a-2
1832 // parasoft-end-suppress AUTOSAR-A18_1_6-a-2
1833};
1834// parasoft-end-suppress AUTOSAR-A11_0_2-a-2
1835
1836} // namespace std
1837// parasoft-end-suppress CERT_CPP-DCL58-a-2
1838// parasoft-end-suppress AUTOSAR-A17_6_1-a-2
1839
1840#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_RESULT_RESULT_HPP_
Intermediary type for constructing a result with a given error_type .
Definition result.hpp:1672
constexpr operator result< Value, ErrorType >() const &noexcept(noexcept(result< Value, ErrorType >(in_place_error, std::declval< ErrorType const & >())))
Instantiates a result<Value,ErrorType> from the contained error instance.
Definition result.hpp:1680
constexpr error_result_t(error_result_t &&)=default
Move constructor.
~error_result_t()=default
destructor
constexpr operator result< Value, ErrorType >() &&noexcept(noexcept(result< Value, ErrorType >(in_place_error, std::declval< ErrorType && >())))
Instantiates a result<Value,ErrorType> from the contained error instance, moving the error value into...
Definition result.hpp:1689
constexpr auto operator=(error_result_t &&) -> error_result_t &=default
Move constructor.
constexpr auto operator=(error_result_t const &) -> error_result_t &=default
Copy assignment.
constexpr auto transform(F &&handle_value) const &
Calls a provided functor with the value channel if it is populated, and produces a new result with th...
Definition result.hpp:1252
~result()=default
Destroy the stored value or error.
ARENE_NODISCARD friend constexpr auto operator==(result const &lhs, result const &rhs) noexcept(noexcept(lhs.has_error(rhs.error()))) -> bool
Compare two results for equality.
Definition result.hpp:1347
constexpr auto or_else(F &&handle_error) const &&
Monadic API which invokes a functor with the contents of error() if the error channel is populated.
Definition result.hpp:1224
constexpr result()=default
Constructs a result with the value-channel engaged.
constexpr auto or_else(F &&handle_error) const &
Monadic API which invokes a functor with the contents of error() if the error channel is populated.
Definition result.hpp:1216
ARENE_NODISCARD constexpr auto error() &&noexcept -> error_type &&
Accesses a reference to the content of the error channel.
Definition result.hpp:1068
constexpr auto transform(F &&handle_value) &&
Calls a provided functor with the value channel if it is populated, and produces a new result with th...
Definition result.hpp:1256
constexpr auto and_then(F &&handle_value) const &
Monadic API which invokes a functor with the contents of value() if the value channel is populated.
Definition result.hpp:1179
constexpr auto and_then(F &&handle_value) const &&
Monadic API which invokes a functor with the contents of value() if the value channel is populated.
Definition result.hpp:1187
constexpr auto operator=(move_assign_arg &&other) noexcept -> result &
Move-assignment for the case that error_type satisfies std::is_nothrow_move_constructible and std::is...
Definition result.hpp:1017
constexpr auto transform_error(F &&handle_error) &
Calls a provided functor with the error channel if it is populated, and produces a new result with th...
Definition result.hpp:1284
constexpr void value() const &noexcept
Access the content of the value channel.
Definition result.hpp:1044
constexpr auto transform_error(F &&handle_error) &&
Calls a provided functor with the error channel if it is populated, and produces a new result with th...
Definition result.hpp:1318
constexpr auto operator=(copy_assign_arg const &other) noexcept -> result &
Copy-assignment for the case that error_type satisfies std::is_nothrow_copy_constructible and std::is...
Definition result.hpp:987
constexpr result(result &&move) noexcept(noexcept(base_type(std::declval< result && >())))=default
Default move constructor.
ARENE_NODISCARD constexpr auto error() const &&noexcept -> error_type const &&
Accesses a reference to the content of the error channel.
Definition result.hpp:1074
ARENE_NODISCARD constexpr auto error() const &noexcept -> error_type const &
Accesses a reference to the content of the error channel.
Definition result.hpp:1063
constexpr auto transform_error(F &&handle_error) const &
Calls a provided functor with the error channel if it is populated, and produces a new result with th...
Definition result.hpp:1301
constexpr auto or_else(F &&handle_error) &&
Monadic API which invokes a functor with the contents of error() if the error channel is populated.
Definition result.hpp:1220
ARENE_NODISCARD friend constexpr auto operator!=(result const &lhs, result const &rhs) noexcept(noexcept(lhs==rhs)) -> bool
Compare two results for inequality.
Definition result.hpp:1368
constexpr auto or_else(F &&handle_error) &
Monadic API which invokes a functor with the contents of error() if the error channel is populated.
Definition result.hpp:1212
constexpr auto and_then(F &&handle_value) &
Monadic API which invokes a functor with the contents of value() if the value channel is populated.
Definition result.hpp:1175
constexpr void value() &&noexcept
Access the content of the value channel.
Definition result.hpp:1048
ARENE_NODISCARD constexpr auto error() &noexcept -> error_type &
Accesses a reference to the content of the error channel.
Definition result.hpp:1058
constexpr auto transform(F &&handle_value) const &&
Calls a provided functor with the value channel if it is populated, and produces a new result with th...
Definition result.hpp:1261
constexpr void operator*() const &noexcept
Access the content of the value channel.
Definition result.hpp:1039
constexpr auto transform(F &&handle_value) &
Calls a provided functor with the value channel if it is populated, and produces a new result with th...
Definition result.hpp:1248
constexpr auto and_then(F &&handle_value) &&
Monadic API which invokes a functor with the contents of value() if the value channel is populated.
Definition result.hpp:1183
void emplace(in_place_value_t) noexcept
Emplaces the void value into the result.
Definition result.hpp:1147
constexpr auto transform_error(F &&handle_error) const &&
Calls a provided functor with the error channel if it is populated, and produces a new result with th...
Definition result.hpp:1335
A sum type which can hold either a value or an error. Similar to std::expected.
Definition result.hpp:104
~result()=default
Destroy the stored value or error.
ARENE_NODISCARD constexpr auto value() const &noexcept -> value_type const &
Accesses a reference to the content of the value channel.
Definition result.hpp:329
constexpr auto operator=(move_assign_arg &&other) noexcept -> result &
Move-assignment for the case that value_type and error_type satisfy std::is_nothrow_move_constructibl...
Definition result.hpp:242
constexpr result(result &&move) noexcept(noexcept(base_type(std::declval< result && >())))=default
Default move constructor.
constexpr auto operator=(copy_assign_arg const &other) noexcept -> result &
Copy-assignment for the case that value_type and error_type satisfy std::is_nothrow_copy_constructibl...
Definition result.hpp:209
ARENE_NODISCARD constexpr auto value() const &&noexcept -> value_type const &&
Accesses a reference to the content of the value channel.
Definition result.hpp:350
ARENE_NODISCARD constexpr auto operator->() noexcept -> value_type *
Accesses a pointer to the content of the value channel.
Definition result.hpp:280
ARENE_NODISCARD constexpr auto operator*() &noexcept -> value_type &
Accesses a reference to the content of the value channel.
Definition result.hpp:292
ARENE_NODISCARD constexpr auto operator->() const noexcept -> value_type const *
Accesses a pointer to the content of the value channel.
Definition result.hpp:286
ARENE_NODISCARD constexpr auto operator*() const &&noexcept -> value_type const &&
Accesses a reference to the content of the value channel.
Definition result.hpp:311
constexpr result()=default
Constructs a result with a default-constructed value_type . Does not participate in overload resoluti...
ARENE_NODISCARD constexpr auto operator*() const &noexcept -> value_type const &
Accesses a reference to the content of the value channel.
Definition result.hpp:298
ARENE_NODISCARD constexpr auto value() &noexcept -> value_type &
Accesses a reference to the content of the value channel.
Definition result.hpp:319
ARENE_NODISCARD constexpr auto operator*() &&noexcept -> value_type &&
Accesses a reference to the content of the value channel.
Definition result.hpp:304
ARENE_NODISCARD constexpr auto value() &&noexcept -> value_type &&
Accesses a reference to the content of the value channel.
Definition result.hpp:339
constexpr operator result< void, Error >() noexcept
Instantiates a result<Value,Error> from the contained value instance. Consumes the container.
Definition result.hpp:1657
Intermediary type for constructing a result with a given value_type .
Definition result.hpp:1587
constexpr auto operator=(value_result_t const &) -> value_result_t &=default
Copy assignment.
constexpr auto operator=(value_result_t &&) -> value_result_t &=default
Move constructor.
constexpr value_result_t(value_result_t &&)=default
Move constructor.
constexpr operator result< ValueType, Error >() const &noexcept(noexcept(result< ValueType, Error >(in_place_value, std::declval< ValueType const & >())))
Instantiates a result<ValueType,Error> from the contained value instance. Consumes the container.
Definition result.hpp:1595
~value_result_t()=default
destructor
constexpr operator result< ValueType, Error >() &&noexcept(noexcept(result< ValueType, Error >(in_place_value, std::declval< ValueType && >())))
Instantiates a result<ValueType,Error> from the contained value instance. Consumes the container.
Definition result.hpp:1603
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10
constexpr auto operator()(::arene::base::result< V, E > const &value) const noexcept(noexcept(hash< E >{}(std::declval< E const & >())) &&noexcept(hash< V >{}(std::declval< V const & >()))) -> std::size_t
Calculate the hash of a result.
Definition result.hpp:1803
constexpr auto operator()(::arene::base::result< void, E > const &value) const noexcept(noexcept(hash< E >{}(std::declval< E const & >()))) -> std::size_t
Calculate the hash of a result.
Definition result.hpp:1827