Result
result.hpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 /// \file result.hpp
3 ///
4 /// \brief This header contains the 'result' monadic type for indicating
5 /// possible error conditions
6 ////////////////////////////////////////////////////////////////////////////////
7 
8 /*
9  The MIT License (MIT)
10 
11  Copyright (c) 2017-2021 Matthew Rodusek All rights reserved.
12 
13  Permission is hereby granted, free of charge, to any person obtaining a copy
14  of this software and associated documentation files (the "Software"), to deal
15  in the Software without restriction, including without limitation the rights
16  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  copies of the Software, and to permit persons to whom the Software is
18  furnished to do so, subject to the following conditions:
19 
20  The above copyright notice and this permission notice shall be included in
21  all copies or substantial portions of the Software.
22 
23  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  SOFTWARE.
30 */
31 
32 #ifndef RESULT_RESULT_HPP
33 #define RESULT_RESULT_HPP
34 
35 #include <cstddef> // std::size_t
36 #include <type_traits> // std::enable_if, std::is_constructible, etc
37 #include <new> // placement-new
38 #include <memory> // std::address_of
39 #include <functional> // std::reference_wrapper, std::invoke
40 #include <utility> // std::in_place_t, std::forward
41 #include <initializer_list> // std::initializer_list
42 #include <string> // std::string (for exception message)
43 
44 #if defined(RESULT_EXCEPTIONS_DISABLED)
45 # include <cstdio> // std::fprintf, stderr
46 #else
47 # include <stdexcept> // std::logic_error
48 #endif
49 
50 #if __cplusplus >= 201402L
51 # define RESULT_CPP14_CONSTEXPR constexpr
52 #else
53 # define RESULT_CPP14_CONSTEXPR
54 #endif
55 
56 #if __cplusplus >= 201703L
57 # define RESULT_CPP17_INLINE inline
58 #else
59 # define RESULT_CPP17_INLINE
60 #endif
61 
62 #if defined(__clang__) && defined(_MSC_VER)
63 # define RESULT_INLINE_VISIBILITY __attribute__((visibility("hidden")))
64 #elif defined(__clang__) || defined(__GNUC__)
65 # define RESULT_INLINE_VISIBILITY __attribute__((visibility("hidden"), always_inline))
66 #elif defined(_MSC_VER)
67 # define RESULT_INLINE_VISIBILITY __forceinline
68 #else
69 # define RESULT_INLINE_VISIBILITY
70 #endif
71 
72 // [[clang::warn_unused_result]] is more full-featured than gcc's variant, since
73 // it supports being applied to class objects.
74 #if __cplusplus >= 201703L
75 # define RESULT_NODISCARD [[nodiscard]]
76 # define RESULT_WARN_UNUSED [[nodiscard]]
77 #elif defined(__clang__) && ((__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ >= 9)))
78 # define RESULT_NODISCARD [[clang::warn_unused_result]]
79 # define RESULT_WARN_UNUSED [[clang::warn_unused_result]]
80 #elif defined(__GNUC__)
81 # define RESULT_NODISCARD
82 # define RESULT_WARN_UNUSED [[gnu::warn_unused_result]]
83 #else
84 # define RESULT_WARN_UNUSED
85 # define RESULT_NODISCARD
86 #endif
87 
88 #if defined(RESULT_NAMESPACE)
89 # define RESULT_NAMESPACE_INTERNAL RESULT_NAMESPACE
90 #else
91 # define RESULT_NAMESPACE_INTERNAL cpp
92 #endif
93 #define RESULT_NS_IMPL RESULT_NAMESPACE_INTERNAL::bitwizeshift
94 
95 // clang's `-Wdocumentation-unknown-command` flag is bugged and does not
96 // understand `\copydoc` tags, despite this being a valid doxygen tag.
97 #if defined(__clang__)
98 # pragma clang diagnostic push
99 # pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
100 #endif
101 
102 namespace RESULT_NAMESPACE_INTERNAL {
103 inline namespace bitwizeshift {
104 
105  //===========================================================================
106  // utilities : constexpr forward
107  //===========================================================================
108 
109  // std::forward is not constexpr until C++14
110  namespace detail {
111 #if __cplusplus >= 201402L
112  using std::forward;
113 #else
114  template <typename T>
115  inline RESULT_INLINE_VISIBILITY constexpr
116  auto forward(typename std::remove_reference<T>::type& t)
117  noexcept -> T&&
118  {
119  return static_cast<T&&>(t);
120  }
121 
122  template <typename T>
123  inline RESULT_INLINE_VISIBILITY constexpr
124  auto forward(typename std::remove_reference<T>::type&& t)
125  noexcept -> T&&
126  {
127  return static_cast<T&&>(t);
128  }
129 #endif
130  } // namespace detail
131 
132 
133  //===========================================================================
134  // utilities : invoke / invoke_result
135  //===========================================================================
136 
137  // std::invoke was introduced in C++17
138 
139  namespace detail {
140 #if __cplusplus >= 201703L
141  using std::invoke;
142  using std::invoke_result;
143  using std::invoke_result_t;
144 #else
145  template<typename T>
146  struct is_reference_wrapper : std::false_type{};
147 
148  template<typename U>
149  struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type{};
150 
151  //-------------------------------------------------------------------------
152 
153  template <typename Base, typename T, typename Derived, typename... Args,
154  typename = typename std::enable_if<
155  std::is_function<T>::value &&
156  std::is_base_of<Base, typename std::decay<Derived>::type>::value
157  >::type>
158  inline RESULT_INLINE_VISIBILITY constexpr
159  auto invoke(T Base::*pmf, Derived&& ref, Args&&... args)
160  noexcept(noexcept((::RESULT_NS_IMPL::detail::forward<Derived>(ref).*pmf)(::RESULT_NS_IMPL::detail::forward<Args>(args)...)))
161  -> decltype((::RESULT_NS_IMPL::detail::forward<Derived>(ref).*pmf)(::RESULT_NS_IMPL::detail::forward<Args>(args)...))
162  {
163  return (RESULT_NS_IMPL::detail::forward<Derived>(ref).*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...);
164  }
165 
166  template <typename Base, typename T, typename RefWrap, typename... Args,
167  typename = typename std::enable_if<
168  std::is_function<T>::value &&
169  is_reference_wrapper<typename std::decay<RefWrap>::type>::value
170  >::type>
171  inline RESULT_INLINE_VISIBILITY constexpr
172  auto invoke(T Base::*pmf, RefWrap&& ref, Args&&... args)
173  noexcept(noexcept((ref.get().*pmf)(std::forward<Args>(args)...)))
174  -> decltype((ref.get().*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...))
175  {
176  return (ref.get().*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...);
177  }
178 
179  template <typename Base, typename T, typename Pointer, typename... Args,
180  typename = typename std::enable_if<
181  std::is_function<T>::value &&
182  !is_reference_wrapper<typename std::decay<Pointer>::type>::value &&
183  !std::is_base_of<Base, typename std::decay<Pointer>::type>::value
184  >::type>
185  inline RESULT_INLINE_VISIBILITY constexpr
186  auto invoke(T Base::*pmf, Pointer&& ptr, Args&&... args)
187  noexcept(noexcept(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)))
188  -> decltype(((*RESULT_NS_IMPL::detail::forward<Pointer>(ptr)).*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...))
189  {
190  return ((*RESULT_NS_IMPL::detail::forward<Pointer>(ptr)).*pmf)(RESULT_NS_IMPL::detail::forward<Args>(args)...);
191  }
192 
193  template <typename Base, typename T, typename Derived,
194  typename = typename std::enable_if<
195  !std::is_function<T>::value &&
196  std::is_base_of<Base, typename std::decay<Derived>::type>::value
197  >::type>
198  inline RESULT_INLINE_VISIBILITY constexpr
199  auto invoke(T Base::*pmd, Derived&& ref)
200  noexcept(noexcept(std::forward<Derived>(ref).*pmd))
201  -> decltype(RESULT_NS_IMPL::detail::forward<Derived>(ref).*pmd)
202  {
203  return RESULT_NS_IMPL::detail::forward<Derived>(ref).*pmd;
204  }
205 
206  template <typename Base, typename T, typename RefWrap,
207  typename = typename std::enable_if<
208  !std::is_function<T>::value &&
209  is_reference_wrapper<typename std::decay<RefWrap>::type>::value
210  >::type>
211  inline RESULT_INLINE_VISIBILITY constexpr
212  auto invoke(T Base::*pmd, RefWrap&& ref)
213  noexcept(noexcept(ref.get().*pmd))
214  -> decltype(ref.get().*pmd)
215  {
216  return ref.get().*pmd;
217  }
218 
219  template <typename Base, typename T, typename Pointer,
220  typename = typename std::enable_if<
221  !std::is_function<T>::value &&
222  !is_reference_wrapper<typename std::decay<Pointer>::type>::value &&
223  !std::is_base_of<Base, typename std::decay<Pointer>::type>::value
224  >::type>
225  inline RESULT_INLINE_VISIBILITY constexpr
226  auto invoke(T Base::*pmd, Pointer&& ptr)
227  noexcept(noexcept((*std::forward<Pointer>(ptr)).*pmd))
228  -> decltype((*RESULT_NS_IMPL::detail::forward<Pointer>(ptr)).*pmd)
229  {
230  return (*RESULT_NS_IMPL::detail::forward<Pointer>(ptr)).*pmd;
231  }
232 
233  template <typename F, typename... Args,
234  typename = typename std::enable_if<!std::is_member_pointer<typename std::decay<F>::type>::value>::type>
235  inline RESULT_INLINE_VISIBILITY constexpr
236  auto invoke(F&& f, Args&&... args)
237  noexcept(noexcept(std::forward<F>(f)(std::forward<Args>(args)...)))
238  -> decltype(RESULT_NS_IMPL::detail::forward<F>(f)(RESULT_NS_IMPL::detail::forward<Args>(args)...))
239  {
240  return RESULT_NS_IMPL::detail::forward<F>(f)(RESULT_NS_IMPL::detail::forward<Args>(args)...);
241  }
242 
243  template<typename Fn, typename...Args>
244  struct is_invocable
245  {
246  template <typename Fn2, typename...Args2>
247  static auto test( Fn2&&, Args2&&... )
248  -> decltype(invoke(std::declval<Fn2>(), std::declval<Args2>()...), std::true_type{});
249 
250  static auto test(...)
251  -> std::false_type;
252 
253  using type = decltype(test(std::declval<Fn>(), std::declval<Args>()...));
254  static constexpr bool value = type::value;
255  };
256 
257  template <bool B, typename Fn, typename...Args>
258  struct invoke_result_impl {
259  using type = decltype(RESULT_NS_IMPL::detail::invoke(std::declval<Fn>(), std::declval<Args>()...));
260  };
261  template <typename Fn, typename...Args>
262  struct invoke_result_impl<false, Fn, Args...>{};
263 
264  template <typename Fn, typename...Args>
265  struct invoke_result
266  : invoke_result_impl<is_invocable<Fn,Args...>::value, Fn, Args...>{};
267 
268  template <typename Fn, typename...Args>
269  using invoke_result_t = typename invoke_result<Fn, Args...>::type;
270 #endif
271  }
272 
273  //===========================================================================
274  // struct : in_place_t
275  //===========================================================================
276 
277 #if __cplusplus >= 201703L
278  using std::in_place_t;
279  using std::in_place;
280 #else
281  /// \brief A structure for representing in-place construction
282  struct in_place_t
283  {
284  explicit in_place_t() = default;
285  };
286  RESULT_CPP17_INLINE constexpr auto in_place = in_place_t{};
287 #endif
288 
289  //===========================================================================
290  // struct : in_place_t
291  //===========================================================================
292 
293  /// \brief A structure for representing in-place construction of an error type
295  {
296  explicit in_place_error_t() = default;
297  };
298 
299  RESULT_CPP17_INLINE constexpr auto in_place_error = in_place_error_t{};
300 
301  //===========================================================================
302  // forward-declarations
303  //===========================================================================
304 
305  template <typename>
306  class failure;
307 
308  template <typename, typename>
309  class result;
310 
311  template <typename>
312  class bad_result_access;
313 
314  //===========================================================================
315  // traits
316  //===========================================================================
317 
318  template <typename T>
319  struct is_failure : std::false_type{};
320  template <typename E>
321  struct is_failure<failure<E>> : std::true_type{};
322 
323  template <typename T>
324  struct is_result : std::false_type{};
325  template <typename T, typename E>
326  struct is_result<result<T,E>> : std::true_type{};
327 
328  //===========================================================================
329  // trait : detail::wrapped_result_type
330  //===========================================================================
331 
332  namespace detail {
333 
334  template <typename T>
335  using wrapped_result_type = typename std::conditional<
336  std::is_lvalue_reference<T>::value,
337  std::reference_wrapper<
338  typename std::remove_reference<T>::type
339  >,
340  typename std::remove_const<T>::type
341  >::type;
342 
343  } // namespace detail
344 
345 #if !defined(RESULT_DISABLE_EXCEPTIONS)
346 
347  //===========================================================================
348  // class : bad_result_access<E>
349  //===========================================================================
350 
351  /////////////////////////////////////////////////////////////////////////////
352  /// \brief An exception thrown when result::value is accessed without
353  /// a contained value
354  /////////////////////////////////////////////////////////////////////////////
355  template <typename E>
356  class bad_result_access : public std::logic_error
357  {
358  //-------------------------------------------------------------------------
359  // Constructor / Assignment
360  //-------------------------------------------------------------------------
361  public:
362 
363  /// \brief Constructs this exception using the underlying error type for
364  /// the error type
365  ///
366  /// \param error the underlying error
367  template <typename E2,
368  typename = typename std::enable_if<std::is_constructible<E,E2>::value>::type>
369  explicit bad_result_access(E2&& error);
370 
371  /// \{
372  /// \brief Constructs this exception using the underlying error type for
373  /// the error and a message
374  ///
375  /// \param what_arg the message for the failure
376  /// \param error the underlying error
377  template <typename E2,
378  typename = typename std::enable_if<std::is_constructible<E,E2>::value>::type>
379  bad_result_access(const char* what_arg, E2&& error);
380  template <typename E2,
381  typename = typename std::enable_if<std::is_constructible<E,E2>::value>::type>
382  bad_result_access(const std::string& what_arg, E2&& error);
383  /// \}
384 
385  bad_result_access(const bad_result_access& other) = default;
386  bad_result_access(bad_result_access&& other) = default;
387 
388  //-------------------------------------------------------------------------
389 
390  auto operator=(const bad_result_access& other) -> bad_result_access& = default;
391  auto operator=(bad_result_access&& other) -> bad_result_access& = default;
392 
393  /// \{
394  /// \brief Gets the underlying error
395  ///
396  /// \return the error
397  auto error() & noexcept -> E&;
398  auto error() && noexcept -> E&&;
399  auto error() const & noexcept -> const E&;
400  auto error() const && noexcept -> const E&&;
401  /// \}
402 
403  //-------------------------------------------------------------------------
404  // Private Members
405  //-------------------------------------------------------------------------
406  private:
407 
408  E m_error;
409  };
410 
411 #endif
412 
413  namespace detail {
414 
415  template <typename E, typename E2>
416  using failure_is_value_convertible = std::integral_constant<bool,(
417  std::is_constructible<E, E2&&>::value &&
418  !std::is_same<typename std::decay<E2>::type, in_place_t>::value &&
419  !is_failure<typename std::decay<E2>::type>::value &&
420  !is_result<typename std::decay<E2>::type>::value
421  )>;
422 
423  template <typename E, typename E2>
424  using failure_is_explicit_value_convertible = std::integral_constant<bool,(
425  failure_is_value_convertible<E, E2>::value &&
426  !std::is_convertible<E2, E>::value
427  )>;
428 
429  template <typename E, typename E2>
430  using failure_is_implicit_value_convertible = std::integral_constant<bool,(
431  failure_is_value_convertible<E, E2>::value &&
432  std::is_convertible<E2, E>::value
433  )>;
434 
435  template <typename E, typename E2>
436  using failure_is_value_assignable = std::integral_constant<bool,(
437  !is_result<typename std::decay<E2>::type>::value &&
438  !is_failure<typename std::decay<E2>::type>::value &&
439  std::is_assignable<wrapped_result_type<E>&,E2>::value
440  )>;
441 
442  } // namespace detail
443 
444  //===========================================================================
445  // class : failure_type
446  //===========================================================================
447 
448  //////////////////////////////////////////////////////////////////////////////
449  /// \brief A semantic type used for distinguishing failure values in an
450  /// API that returns result types
451  ///
452  /// \tparam E the error type
453  //////////////////////////////////////////////////////////////////////////////
454  template <typename E>
455  class failure
456  {
457  static_assert(
458  !is_result<typename std::decay<E>::type>::value,
459  "A (possibly CV-qualified) result 'E' type is ill-formed."
460  );
461  static_assert(
462  !is_failure<typename std::decay<E>::type>::value,
463  "A (possibly CV-qualified) failure 'E' type is ill-formed."
464  );
465  static_assert(
466  !std::is_void<typename std::decay<E>::type>::value,
467  "A (possibly CV-qualified) 'void' 'E' type is ill-formed."
468  );
469  static_assert(
470  !std::is_rvalue_reference<E>::value,
471  "rvalue references for 'E' type is ill-formed. "
472  "Only lvalue references are valid."
473  );
474 
475  //-------------------------------------------------------------------------
476  // Public Member Types
477  //-------------------------------------------------------------------------
478  public:
479 
480  using error_type = E;
481 
482  //-------------------------------------------------------------------------
483  // Constructors / Assignment
484  //-------------------------------------------------------------------------
485  public:
486 
487  /// \brief Constructs a failure via default construction
488  failure() = default;
489 
490  /// \brief Constructs a failure by delegating construction to the
491  /// underlying constructor
492  ///
493  /// \param args the arguments to forward to E's constructor
494  template <typename...Args,
495  typename = typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
496  constexpr failure(in_place_t, Args&&...args)
497  noexcept(std::is_nothrow_constructible<E, Args...>::value);
498 
499  /// \brief Constructs a failure by delegating construction to the
500  /// underlying constructor
501  ///
502  /// \param ilist the initializer list
503  /// \param args the arguments to forward to E's constructor
504  template <typename U, typename...Args,
505  typename = typename std::enable_if<std::is_constructible<E,std::initializer_list<U>,Args...>::value>::type>
506  constexpr failure(in_place_t, std::initializer_list<U> ilist, Args&&...args)
508 
509  /// \{
510  /// \brief Constructs a failure from the given error
511  ///
512  /// \param error the error to create a failure from
513  template <typename E2,
514  typename std::enable_if<detail::failure_is_implicit_value_convertible<E,E2>::value,int>::type = 0>
515  constexpr failure(E2&& error)
516  noexcept(std::is_nothrow_constructible<E,E2>::value);
517  template <typename E2,
518  typename std::enable_if<detail::failure_is_explicit_value_convertible<E,E2>::value,int>::type = 0>
519  constexpr explicit failure(E2&& error)
520  noexcept(std::is_nothrow_constructible<E,E2>::value);
521  /// \}
522 
523  /// \brief Constructs this failure by copying the contents of an existing
524  /// one
525  ///
526  /// \param other the other failure to copy
527  /* implicit */ failure(const failure& other) = default;
528 
529  /// \brief Constructs this failure by moving the contents of an existing
530  /// one
531  ///
532  /// \param other the other failure to move
533  /* implicit */ failure(failure&& other) = default;
534 
535  /// \brief Constructs this failure by copy-converting \p other
536  ///
537  /// \param other the other failure to copy
538  template <typename E2,
539  typename = typename std::enable_if<std::is_constructible<E,const E2&>::value>::type>
540  constexpr /* implicit */ failure(const failure<E2>& other)
541  noexcept(std::is_nothrow_constructible<E,const E2&>::value);
542 
543  /// \brief Constructs this failure by move-converting \p other
544  ///
545  /// \param other the other failure to copy
546  template <typename E2,
547  typename = typename std::enable_if<std::is_constructible<E,E2&&>::value>::type>
548  constexpr /* implicit */ failure(failure<E2>&& other)
549  noexcept(std::is_nothrow_constructible<E,E2&&>::value);
550 
551  //--------------------------------------------------------------------------
552 
553  /// \brief Assigns the value of \p error to this failure through
554  /// move-assignment
555  ///
556  /// \param error the value to assign
557  /// \return reference to `(*this)`
558  template <typename E2,
559  typename = typename std::enable_if<detail::failure_is_value_assignable<E,E2>::value>::type>
561  auto operator=(E2&& error)
562  noexcept(std::is_nothrow_assignable<E,E2>::value || std::is_lvalue_reference<E>::value) -> failure&;
563 
564  /// \brief Assigns the contents of \p other to this by copy-assignment
565  ///
566  /// \param other the other failure to copy
567  /// \return reference to `(*this)`
568  auto operator=(const failure& other) -> failure& = default;
569 
570  /// \brief Assigns the contents of \p other to this by move-assignment
571  ///
572  /// \param other the other failure to move
573  /// \return reference to `(*this)`
574  auto operator=(failure&& other) -> failure& = default;
575 
576  /// \brief Assigns the contents of \p other to this by copy conversion
577  ///
578  /// \param other the other failure to copy-convert
579  /// \return reference to `(*this)`
580  template <typename E2,
581  typename = typename std::enable_if<std::is_assignable<E&,const E2&>::value>::type>
583  auto operator=(const failure<E2>& other)
584  noexcept(std::is_nothrow_assignable<E,const E2&>::value) -> failure&;
585 
586  /// \brief Assigns the contents of \p other to this by move conversion
587  ///
588  /// \param other the other failure to move-convert
589  /// \return reference to `(*this)`
590  template <typename E2,
591  typename = typename std::enable_if<std::is_assignable<E&,E2&&>::value>::type>
593  auto operator=(failure<E2>&& other)
594  noexcept(std::is_nothrow_assignable<E,E2&&>::value) -> failure&;
595 
596  //--------------------------------------------------------------------------
597  // Observers
598  //--------------------------------------------------------------------------
599  public:
600 
601  /// \{
602  /// \brief Gets the underlying error
603  ///
604  /// \return the underlying error
606  auto error() & noexcept
607  -> typename std::add_lvalue_reference<E>::type;
609  auto error() && noexcept
610  -> typename std::add_rvalue_reference<E>::type;
611  constexpr auto error() const & noexcept
612  -> typename std::add_lvalue_reference<typename std::add_const<E>::type>::type;
613  constexpr auto error() const && noexcept
614  -> typename std::add_rvalue_reference<typename std::add_const<E>::type>::type;
615  /// \}
616 
617  //-------------------------------------------------------------------------
618  // Private Member Types
619  //-------------------------------------------------------------------------
620  private:
621 
622  using underlying_type = detail::wrapped_result_type<E>;
623 
624  //-------------------------------------------------------------------------
625  // Private Members
626  //-------------------------------------------------------------------------
627  private:
628 
629  underlying_type m_failure;
630  };
631 
632 #if __cplusplus >= 201703L
633  template <typename T>
634  failure(std::reference_wrapper<T>) -> failure<T&>;
635 
636  template <typename T>
637  failure(T&&) -> failure<typename std::decay<T>::type>;
638 #endif
639 
640  //===========================================================================
641  // non-member functions : class : failure
642  //===========================================================================
643 
644  //---------------------------------------------------------------------------
645  // Comparison
646  //---------------------------------------------------------------------------
647 
648  template <typename E1, typename E2>
649  constexpr auto operator==(const failure<E1>& lhs,
650  const failure<E2>& rhs) noexcept -> bool;
651  template <typename E1, typename E2>
652  constexpr auto operator!=(const failure<E1>& lhs,
653  const failure<E2>& rhs) noexcept -> bool;
654  template <typename E1, typename E2>
655  constexpr auto operator<(const failure<E1>& lhs,
656  const failure<E2>& rhs) noexcept -> bool;
657  template <typename E1, typename E2>
658  constexpr auto operator>(const failure<E1>& lhs,
659  const failure<E2>& rhs) noexcept -> bool;
660  template <typename E1, typename E2>
661  constexpr auto operator<=(const failure<E1>& lhs,
662  const failure<E2>& rhs) noexcept -> bool;
663  template <typename E1, typename E2>
664  constexpr auto operator>=(const failure<E1>& lhs,
665  const failure<E2>& rhs) noexcept -> bool;
666 
667  //---------------------------------------------------------------------------
668  // Utilities
669  //---------------------------------------------------------------------------
670 
671  /// \brief Deduces and constructs a failure type from \p e
672  ///
673  /// \param e the failure value
674  /// \return a constructed failure value
675  template <typename E>
677  constexpr auto fail(E&& e)
678  noexcept(std::is_nothrow_constructible<typename std::decay<E>::type,E>::value)
679  -> failure<typename std::decay<E>::type>;
680 
681  /// \brief Deduces a failure reference from a reverence_wrapper
682  ///
683  /// \param e the failure value
684  /// \return a constructed failure reference
685  template <typename E>
687  constexpr auto fail(std::reference_wrapper<E> e)
688  noexcept -> failure<E&>;
689 
690  /// \brief Constructs a failure type from a series of arguments
691  ///
692  /// \tparam E the failure type
693  /// \param args the arguments to forward to E's constructor
694  /// \return a constructed failure type
695  template <typename E, typename...Args,
696  typename = typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
698  constexpr auto fail(Args&&...args)
699  noexcept(std::is_nothrow_constructible<E, Args...>::value)
700  -> failure<E>;
701 
702  /// \brief Constructs a failure type from an initializer list and series of
703  /// arguments
704  ///
705  /// \tparam E the failure type
706  /// \param args the arguments to forward to E's constructor
707  /// \return a constructed failure type
708  template <typename E, typename U, typename...Args,
709  typename = typename std::enable_if<std::is_constructible<E,std::initializer_list<U>,Args...>::value>::type>
711  constexpr auto fail(std::initializer_list<U> ilist, Args&&...args)
713  -> failure<E>;
714 
715  /// \brief Swaps the contents of two failure values
716  ///
717  /// \param lhs the left failure
718  /// \param rhs the right failure
719  template <typename E>
720  auto swap(failure<E>& lhs, failure<E>& rhs)
721 #if __cplusplus >= 201703L
722  noexcept(std::is_nothrow_swappable<E>::value) -> void;
723 #else
724  noexcept(std::is_nothrow_move_constructible<E>::value) -> void;
725 #endif
726 
727  namespace detail {
728 
729  //=========================================================================
730  // class : unit
731  //=========================================================================
732 
733  /// \brief A standalone monostate object (effectively std::monostate). This
734  /// exists to allow for `void` specializations
735  struct unit {};
736 
737  //=========================================================================
738  // non-member functions : class : unit
739  //=========================================================================
740 
741  constexpr auto operator==(unit, unit) noexcept -> bool { return true; }
742  constexpr auto operator!=(unit, unit) noexcept -> bool { return false; }
743  constexpr auto operator<(unit, unit) noexcept -> bool { return false; }
744  constexpr auto operator>(unit, unit) noexcept -> bool { return false; }
745  constexpr auto operator<=(unit, unit) noexcept -> bool { return true; }
746  constexpr auto operator>=(unit, unit) noexcept -> bool { return true; }
747 
748  //=========================================================================
749  // class : detail::result_union<T, E, IsTrivial>
750  //=========================================================================
751 
752  ///////////////////////////////////////////////////////////////////////////
753  /// \brief A basic utility that acts as a union containing the T and E
754  /// types
755  ///
756  /// This is specialized on the case that both T and E are trivial, in which
757  /// case `result_union` is also trivial
758  ///
759  /// \tparam T the value type result to be returned
760  /// \tparam E the error type returned on failure
761  /// \tparam IsTrivial Whether or not both T and E are trivial
762  ///////////////////////////////////////////////////////////////////////////
763  template <typename T, typename E,
764  bool IsTrivial = std::is_trivially_destructible<T>::value &&
765  std::is_trivially_destructible<E>::value>
766  struct result_union
767  {
768  //-----------------------------------------------------------------------
769  // Public Member Types
770  //-----------------------------------------------------------------------
771 
772  using underlying_value_type = wrapped_result_type<T>;
773  using underlying_error_type = E;
774 
775  //-----------------------------------------------------------------------
776  // Constructors / Assignment
777  //-----------------------------------------------------------------------
778 
779  /// \brief Constructs an empty object
780  ///
781  /// This is for use with conversion constructors, since it allows a
782  /// temporary unused object to be set
783  result_union(unit) noexcept;
784 
785  /// \brief Constructs the underlying value from the specified \p args
786  ///
787  /// \param args the arguments to forward to T's constructor
788  template <typename...Args>
789  constexpr result_union(in_place_t, Args&&...args)
790  noexcept(std::is_nothrow_constructible<T, Args...>::value);
791 
792  /// \brief Constructs the underlying error from the specified \p args
793  ///
794  /// \param args the arguments to forward to E's constructor
795  template <typename...Args>
796  constexpr result_union(in_place_error_t, Args&&...args)
797  noexcept(std::is_nothrow_constructible<E, Args...>::value);
798 
799  result_union(const result_union&) = default;
800  result_union(result_union&&) = default;
801 
802  //-----------------------------------------------------------------------
803 
804  auto operator=(const result_union&) -> result_union& = default;
805  auto operator=(result_union&&) -> result_union& = default;
806 
807  //-----------------------------------------------------------------------
808  // Modifiers
809  //-----------------------------------------------------------------------
810 
811  /// \brief A no-op for trivial types
812  auto destroy() const noexcept -> void;
813 
814  //-----------------------------------------------------------------------
815  // Public Members
816  //-----------------------------------------------------------------------
817 
818  union {
819  underlying_value_type m_value;
820  underlying_error_type m_error;
821  unit m_empty;
822  };
823  bool m_has_value;
824  };
825 
826  //-------------------------------------------------------------------------
827 
828  template <typename T, typename E>
829  struct result_union<T, E, false>
830  {
831  //-----------------------------------------------------------------------
832  // Public Member Types
833  //-----------------------------------------------------------------------
834 
835  using underlying_value_type = wrapped_result_type<T>;
836  using underlying_error_type = E;
837 
838  //-----------------------------------------------------------------------
839  // Constructors / Assignment / Destructor
840  //-----------------------------------------------------------------------
841 
842  /// \brief Constructs an empty object
843  ///
844  /// This is for use with conversion constructors, since it allows a
845  /// temporary unused object to be set
846  result_union(unit) noexcept;
847 
848  /// \brief Constructs the underlying value from the specified \p args
849  ///
850  /// \param args the arguments to forward to T's constructor
851  template <typename...Args>
852  constexpr result_union(in_place_t, Args&&...args)
853  noexcept(std::is_nothrow_constructible<T, Args...>::value);
854 
855  /// \brief Constructs the underlying error from the specified \p args
856  ///
857  /// \param args the arguments to forward to E's constructor
858  template <typename...Args>
859  constexpr result_union(in_place_error_t, Args&&...args)
860  noexcept(std::is_nothrow_constructible<E, Args...>::value);
861 
862  result_union(const result_union&) = default;
863  result_union(result_union&&) = default;
864 
865  //-----------------------------------------------------------------------
866 
867  /// \brief Destroys the underlying stored object
868  ~result_union()
869  noexcept(std::is_nothrow_destructible<T>::value &&
870  std::is_nothrow_destructible<E>::value);
871 
872  //-----------------------------------------------------------------------
873 
874  auto operator=(const result_union&) -> result_union& = default;
875  auto operator=(result_union&&) -> result_union& = default;
876 
877  //-----------------------------------------------------------------------
878  // Modifiers
879  //-----------------------------------------------------------------------
880 
881  /// \brief Destroys the underlying stored object
882  auto destroy() -> void;
883 
884  //-----------------------------------------------------------------------
885  // Public Members
886  //-----------------------------------------------------------------------
887 
888  union {
889  underlying_value_type m_value;
890  underlying_error_type m_error;
891  unit m_empty;
892  };
893  bool m_has_value;
894  };
895 
896  //=========================================================================
897  // class : result_construct_base<T, E>
898  //=========================================================================
899 
900  ///////////////////////////////////////////////////////////////////////////
901  /// \brief Base class of assignment to enable construction and assignment
902  ///
903  /// This class is used with several pieces of construction to ensure
904  /// trivial constructibility and assignability:
905  ///
906  /// * `result_trivial_copy_ctor_base`
907  /// * `result_trivial_move_ctor_base`
908  /// * `result_copy_assign_base`
909  /// * `result_move_assign_base`
910  ///
911  /// \tparam T the value type
912  /// \tparam E the error type
913  ///////////////////////////////////////////////////////////////////////////
914  template <typename T, typename E>
915  struct result_construct_base
916  {
917  //-----------------------------------------------------------------------
918  // Constructors / Assignment
919  //-----------------------------------------------------------------------
920 
921  /// \brief Constructs an empty object
922  ///
923  /// This is for use with conversion constructors, since it allows a
924  /// temporary unused object to be set
925  result_construct_base(unit) noexcept;
926 
927  /// \brief Constructs the underlying value from the specified \p args
928  ///
929  /// \param args the arguments to forward to T's constructor
930  template <typename...Args>
931  constexpr result_construct_base(in_place_t, Args&&...args)
932  noexcept(std::is_nothrow_constructible<T, Args...>::value);
933 
934  /// \brief Constructs the underlying error from the specified \p args
935  ///
936  /// \param args the arguments to forward to E's constructor
937  template <typename...Args>
938  constexpr result_construct_base(in_place_error_t, Args&&...args)
939  noexcept(std::is_nothrow_constructible<E, Args...>::value);
940 
941  result_construct_base(const result_construct_base&) = default;
942  result_construct_base(result_construct_base&&) = default;
943 
944  auto operator=(const result_construct_base&) -> result_construct_base& = default;
945  auto operator=(result_construct_base&&) -> result_construct_base& = default;
946 
947  //-----------------------------------------------------------------------
948  // Construction / Assignment
949  //-----------------------------------------------------------------------
950 
951  /// \brief Constructs the value type from \p args
952  ///
953  /// \note This is an implementation detail only meant to be used during
954  /// construction
955  ///
956  /// \pre there is no contained value or error at the time of construction
957  ///
958  /// \param args the arguments to forward to T's constructor
959  template <typename...Args>
960  auto construct_value(Args&&...args)
961  noexcept(std::is_nothrow_constructible<T,Args...>::value) -> void;
962 
963  /// \brief Constructs the error type from \p args
964  ///
965  /// \note This is an implementation detail only meant to be used during
966  /// construction
967  ///
968  /// \pre there is no contained value or error at the time of construction
969  ///
970  /// \param args the arguments to forward to E's constructor
971  template <typename...Args>
972  auto construct_error(Args&&...args)
973  noexcept(std::is_nothrow_constructible<E,Args...>::value) -> void;
974 
975  /// \brief Constructs the underlying error from the \p other result
976  ///
977  /// If \p other contains a value, then the T type will be
978  /// default-constructed.
979  ///
980  /// \note This is an implementation detail only meant to be used during
981  /// construction of `result<void, E>` types
982  ///
983  /// \pre there is no contained value or error at the time of construction
984  ///
985  /// \param other the other result to construct
986  template <typename Result>
987  auto construct_error_from_result(Result&& other) -> void;
988 
989  /// \brief Constructs the underlying type from a result object
990  ///
991  /// \note This is an implementation detail only meant to be used during
992  /// construction
993  ///
994  /// \pre there is no contained value or error at the time of construction
995  ///
996  /// \param other the other result to construct
997  template <typename Result>
998  auto construct_from_result(Result&& other) -> void;
999 
1000  //-----------------------------------------------------------------------
1001 
1002  template <typename Value>
1003  auto assign_value(Value&& value)
1004  noexcept(std::is_nothrow_assignable<T, Value>::value) -> void;
1005 
1006  template <typename Error>
1007  auto assign_error(Error&& error)
1008  noexcept(std::is_nothrow_assignable<E, Error>::value) -> void;
1009 
1010  template <typename Result>
1011  auto assign_from_result(Result&& other) -> void;
1012 
1013  //-----------------------------------------------------------------------
1014 
1015  template <typename ReferenceWrapper>
1016  auto construct_value_from_result_impl(std::true_type, ReferenceWrapper&& reference)
1017  noexcept -> void;
1018 
1019  template <typename Value>
1020  auto construct_value_from_result_impl(std::false_type, Value&& value)
1021  noexcept(std::is_nothrow_constructible<T,Value>::value) -> void;
1022 
1023  template <typename Result>
1024  auto assign_value_from_result_impl(std::true_type, Result&& other) -> void;
1025 
1026  template <typename Result>
1027  auto assign_value_from_result_impl(std::false_type, Result&& other) -> void;
1028 
1029  //-----------------------------------------------------------------------
1030  // Public Members
1031  //-----------------------------------------------------------------------
1032 
1033  using storage_type = result_union<T, E>;
1034 
1035  storage_type storage;
1036  };
1037 
1038  //=========================================================================
1039  // class : result_trivial_copy_ctor_base
1040  //=========================================================================
1041 
1042  template <typename T, typename E>
1043  struct result_trivial_copy_ctor_base_impl : result_construct_base<T,E>
1044  {
1045  using base_type = result_construct_base<T,E>;
1046  using base_type::base_type;
1047 
1048  result_trivial_copy_ctor_base_impl(const result_trivial_copy_ctor_base_impl& other)
1049  noexcept(std::is_nothrow_copy_constructible<T>::value &&
1050  std::is_nothrow_copy_constructible<E>::value);
1051  result_trivial_copy_ctor_base_impl(result_trivial_copy_ctor_base_impl&& other) = default;
1052 
1053  auto operator=(const result_trivial_copy_ctor_base_impl& other) -> result_trivial_copy_ctor_base_impl& = default;
1054  auto operator=(result_trivial_copy_ctor_base_impl&& other) -> result_trivial_copy_ctor_base_impl& = default;
1055  };
1056 
1057  template <bool Condition, typename Base>
1058  using conditionally_nest_type = typename std::conditional<
1059  Condition,
1060  typename Base::base_type,
1061  Base
1062  >::type;
1063 
1064  template <typename T, typename E>
1065  using result_trivial_copy_ctor_base = conditionally_nest_type<
1066  std::is_trivially_copy_constructible<T>::value &&
1067  std::is_trivially_copy_constructible<E>::value,
1068  result_trivial_copy_ctor_base_impl<T,E>
1069  >;
1070 
1071  //=========================================================================
1072  // class : result_trivial_move_ctor_base
1073  //=========================================================================
1074 
1075  template <typename T, typename E>
1076  struct result_trivial_move_ctor_base_impl : result_trivial_copy_ctor_base<T,E>
1077  {
1078  using base_type = result_trivial_copy_ctor_base<T,E>;
1079  using base_type::base_type;
1080 
1081  result_trivial_move_ctor_base_impl(const result_trivial_move_ctor_base_impl& other) = default;
1082  result_trivial_move_ctor_base_impl(result_trivial_move_ctor_base_impl&& other)
1083  noexcept(std::is_nothrow_move_constructible<T>::value &&
1084  std::is_nothrow_move_constructible<E>::value);
1085 
1086  auto operator=(const result_trivial_move_ctor_base_impl& other) -> result_trivial_move_ctor_base_impl& = default;
1087  auto operator=(result_trivial_move_ctor_base_impl&& other) -> result_trivial_move_ctor_base_impl& = default;
1088  };
1089 
1090  template <typename T, typename E>
1091  using result_trivial_move_ctor_base = conditionally_nest_type<
1092  std::is_trivially_move_constructible<T>::value &&
1093  std::is_trivially_move_constructible<E>::value,
1094  result_trivial_move_ctor_base_impl<T,E>
1095  >;
1096 
1097  //=========================================================================
1098  // class : result_trivial_copy_assign_base
1099  //=========================================================================
1100 
1101  template <typename T, typename E>
1102  struct result_trivial_copy_assign_base_impl
1103  : result_trivial_move_ctor_base<T, E>
1104  {
1105  using base_type = result_trivial_move_ctor_base<T,E>;
1106  using base_type::base_type;
1107 
1108  result_trivial_copy_assign_base_impl(const result_trivial_copy_assign_base_impl& other) = default;
1109  result_trivial_copy_assign_base_impl(result_trivial_copy_assign_base_impl&& other) = default;
1110 
1111  auto operator=(const result_trivial_copy_assign_base_impl& other)
1112  noexcept(std::is_nothrow_copy_constructible<T>::value &&
1113  std::is_nothrow_copy_constructible<E>::value &&
1114  std::is_nothrow_copy_assignable<T>::value &&
1115  std::is_nothrow_copy_assignable<E>::value)
1116  -> result_trivial_copy_assign_base_impl&;
1117  auto operator=(result_trivial_copy_assign_base_impl&& other)
1118  -> result_trivial_copy_assign_base_impl& = default;
1119  };
1120 
1121  template <typename T, typename E>
1122  using result_trivial_copy_assign_base = conditionally_nest_type<
1123  std::is_trivially_copy_constructible<T>::value &&
1124  std::is_trivially_copy_constructible<E>::value &&
1125  std::is_trivially_copy_assignable<T>::value &&
1126  std::is_trivially_copy_assignable<E>::value &&
1127  std::is_trivially_destructible<T>::value &&
1128  std::is_trivially_destructible<E>::value,
1129  result_trivial_copy_assign_base_impl<T,E>
1130  >;
1131 
1132  //=========================================================================
1133  // class : result_trivial_move_assign_base
1134  //=========================================================================
1135 
1136  template <typename T, typename E>
1137  struct result_trivial_move_assign_base_impl
1138  : result_trivial_copy_assign_base<T, E>
1139  {
1140  using base_type = result_trivial_copy_assign_base<T,E>;
1141  using base_type::base_type;
1142 
1143  result_trivial_move_assign_base_impl(const result_trivial_move_assign_base_impl& other) = default;
1144  result_trivial_move_assign_base_impl(result_trivial_move_assign_base_impl&& other) = default;
1145 
1146  auto operator=(const result_trivial_move_assign_base_impl& other)
1147  -> result_trivial_move_assign_base_impl& = default;
1148  auto operator=(result_trivial_move_assign_base_impl&& other)
1149  noexcept(std::is_nothrow_move_constructible<T>::value &&
1150  std::is_nothrow_move_constructible<E>::value &&
1151  std::is_nothrow_move_assignable<T>::value &&
1152  std::is_nothrow_move_assignable<E>::value)
1153  -> result_trivial_move_assign_base_impl&;
1154  };
1155 
1156  template <typename T, typename E>
1157  using result_trivial_move_assign_base = conditionally_nest_type<
1158  std::is_trivially_move_constructible<T>::value &&
1159  std::is_trivially_move_constructible<E>::value &&
1160  std::is_trivially_move_assignable<T>::value &&
1161  std::is_trivially_move_assignable<E>::value &&
1162  std::is_trivially_destructible<T>::value &&
1163  std::is_trivially_destructible<E>::value,
1164  result_trivial_move_assign_base_impl<T,E>
1165  >;
1166 
1167  //=========================================================================
1168  // class : disable_copy_ctor
1169  //=========================================================================
1170 
1171  template <typename T, typename E>
1172  struct disable_copy_ctor : result_trivial_move_assign_base<T,E>
1173  {
1174  using base_type = result_trivial_move_assign_base<T,E>;
1175  using base_type::base_type;
1176 
1177  disable_copy_ctor(const disable_copy_ctor& other) = delete;
1178  disable_copy_ctor(disable_copy_ctor&& other) = default;
1179 
1180  auto operator=(const disable_copy_ctor& other)
1181  -> disable_copy_ctor& = default;
1182  auto operator=(disable_copy_ctor&& other)
1183  -> disable_copy_ctor& = default;
1184  };
1185 
1186  template <typename T, typename E>
1187  using result_copy_ctor_base = conditionally_nest_type<
1188  std::is_copy_constructible<T>::value &&
1189  std::is_copy_constructible<E>::value,
1190  disable_copy_ctor<T,E>
1191  >;
1192 
1193  //=========================================================================
1194  // class : disable_move_ctor
1195  //=========================================================================
1196 
1197  template <typename T, typename E>
1198  struct disable_move_ctor : result_copy_ctor_base<T,E>
1199  {
1200  using base_type = result_copy_ctor_base<T,E>;
1201  using base_type::base_type;
1202 
1203  disable_move_ctor(const disable_move_ctor& other) = default;
1204  disable_move_ctor(disable_move_ctor&& other) = delete;
1205 
1206  auto operator=(const disable_move_ctor& other)
1207  -> disable_move_ctor& = default;
1208  auto operator=(disable_move_ctor&& other)
1209  -> disable_move_ctor& = default;
1210  };
1211 
1212  template <typename T, typename E>
1213  using result_move_ctor_base = conditionally_nest_type<
1214  std::is_move_constructible<T>::value &&
1215  std::is_move_constructible<E>::value,
1216  disable_move_ctor<T,E>
1217  >;
1218 
1219  //=========================================================================
1220  // class : disable_move_assignment
1221  //=========================================================================
1222 
1223  template <typename T, typename E>
1224  struct disable_move_assignment
1225  : result_move_ctor_base<T, E>
1226  {
1227  using base_type = result_move_ctor_base<T, E>;
1228  using base_type::base_type;
1229 
1230  disable_move_assignment(const disable_move_assignment& other) = default;
1231  disable_move_assignment(disable_move_assignment&& other) = default;
1232 
1233  auto operator=(const disable_move_assignment& other)
1234  -> disable_move_assignment& = delete;
1235  auto operator=(disable_move_assignment&& other)
1236  -> disable_move_assignment& = default;
1237  };
1238 
1239  template <typename T, typename E>
1240  using result_copy_assign_base = conditionally_nest_type<
1241  std::is_nothrow_copy_constructible<T>::value &&
1242  std::is_nothrow_copy_constructible<E>::value &&
1243  std::is_copy_assignable<wrapped_result_type<T>>::value &&
1244  std::is_copy_assignable<E>::value,
1245  disable_move_assignment<T,E>
1246  >;
1247 
1248  //=========================================================================
1249  // class : disable_copy_assignment
1250  //=========================================================================
1251 
1252  template <typename T, typename E>
1253  struct disable_copy_assignment
1254  : result_copy_assign_base<T, E>
1255  {
1256  using base_type = result_copy_assign_base<T, E>;
1257  using base_type::base_type;
1258 
1259  disable_copy_assignment(const disable_copy_assignment& other) = default;
1260  disable_copy_assignment(disable_copy_assignment&& other) = default;
1261 
1262  auto operator=(const disable_copy_assignment& other)
1263  -> disable_copy_assignment& = default;
1264  auto operator=(disable_copy_assignment&& other)
1265  -> disable_copy_assignment& = delete;
1266  };
1267 
1268  template <typename T, typename E>
1269  using result_move_assign_base = conditionally_nest_type<
1270  std::is_nothrow_move_constructible<T>::value &&
1271  std::is_nothrow_move_constructible<E>::value &&
1272  std::is_move_assignable<wrapped_result_type<T>>::value &&
1273  std::is_move_assignable<E>::value,
1274  disable_copy_assignment<T,E>
1275  >;
1276 
1277  //=========================================================================
1278  // alias : result_storage
1279  //=========================================================================
1280 
1281  template <typename T, typename E>
1282  using result_storage = result_move_assign_base<T, E>;
1283 
1284  //=========================================================================
1285  // traits : result
1286  //=========================================================================
1287 
1288  template <typename T1, typename E1, typename T2, typename E2>
1289  using result_is_convertible = std::integral_constant<bool,(
1290  // T1 constructible from result<T2,E2>
1291  std::is_constructible<T1, result<T2,E2>&>:: value ||
1292  std::is_constructible<T1, const result<T2,E2>&>:: value ||
1293  std::is_constructible<T1, result<T2,E2>&&>:: value ||
1294  std::is_constructible<T1, const result<T2,E2>&&>:: value ||
1295 
1296  // E1 constructible from result<T2,E2>
1297  std::is_constructible<E1, result<T2,E2>&>:: value ||
1298  std::is_constructible<E1, const result<T2,E2>&>:: value ||
1299  std::is_constructible<E1, result<T2,E2>&&>:: value ||
1300  std::is_constructible<E1, const result<T2,E2>&&>:: value ||
1301 
1302  // result<T2,E2> convertible to T1
1303  std::is_convertible<result<T2,E2>&, T1>:: value ||
1304  std::is_convertible<const result<T2,E2>&, T1>:: value ||
1305  std::is_convertible<result<T2,E2>&&, T1>::value ||
1306  std::is_convertible<const result<T2,E2>&&, T1>::value ||
1307 
1308  // result<T2,E2> convertible to E2
1309  std::is_convertible<result<T2,E2>&, E1>:: value ||
1310  std::is_convertible<const result<T2,E2>&, E1>:: value ||
1311  std::is_convertible<result<T2,E2>&&, E1>::value ||
1312  std::is_convertible<const result<T2,E2>&&, E1>::value
1313  )>;
1314 
1315  //-------------------------------------------------------------------------
1316 
1317  template <typename T1, typename E1, typename T2, typename E2>
1318  using result_is_copy_convertible = std::integral_constant<bool,(
1319  !result_is_convertible<T1,E1,T2,E2>::value &&
1320  std::is_constructible<T1, const T2&>::value &&
1321  std::is_constructible<E1, const E2&>::value
1322  )>;
1323 
1324  template <typename T1, typename E1, typename T2, typename E2>
1325  using result_is_implicit_copy_convertible = std::integral_constant<bool,(
1326  result_is_copy_convertible<T1,E1,T2,E2>::value &&
1327  std::is_convertible<const T2&, T1>::value &&
1328  std::is_convertible<const E2&, E1>::value
1329  )>;
1330 
1331  template <typename T1, typename E1, typename T2, typename E2>
1332  using result_is_explicit_copy_convertible = std::integral_constant<bool,(
1333  result_is_copy_convertible<T1,E1,T2,E2>::value &&
1334  (!std::is_convertible<const T2&, T1>::value ||
1335  !std::is_convertible<const E2&, E1>::value)
1336  )>;
1337 
1338  //-------------------------------------------------------------------------
1339 
1340  template <typename T1, typename E1, typename T2, typename E2>
1341  using result_is_move_convertible = std::integral_constant<bool,(
1342  !result_is_convertible<T1,E1,T2,E2>::value &&
1343  std::is_constructible<T1, T2&&>::value &&
1344  std::is_constructible<E1, E2&&>::value
1345  )>;
1346 
1347  template <typename T1, typename E1, typename T2, typename E2>
1348  using result_is_implicit_move_convertible = std::integral_constant<bool,(
1349  result_is_move_convertible<T1,E1,T2,E2>::value &&
1350  std::is_convertible<T2&&, T1>::value &&
1351  std::is_convertible<E2&&, E1>::value
1352  )>;
1353 
1354  template <typename T1, typename E1, typename T2, typename E2>
1355  using result_is_explicit_move_convertible = std::integral_constant<bool,(
1356  result_is_move_convertible<T1,E1,T2,E2>::value &&
1357  (!std::is_convertible<T2&&, T1>::value ||
1358  !std::is_convertible<E2&&, E1>::value)
1359  )>;
1360 
1361  //-------------------------------------------------------------------------
1362 
1363  template <typename T, typename U>
1364  using result_is_value_convertible = std::integral_constant<bool,(
1365  std::is_constructible<T, U&&>::value &&
1366  !std::is_same<typename std::decay<U>::type, in_place_t>::value &&
1367  !std::is_same<typename std::decay<U>::type, in_place_error_t>::value &&
1368  !is_result<typename std::decay<U>::type>::value
1369  )>;
1370 
1371  template <typename T, typename U>
1372  using result_is_explicit_value_convertible = std::integral_constant<bool,(
1373  result_is_value_convertible<T, U>::value &&
1374  !std::is_convertible<U&&, T>::value
1375  )>;
1376 
1377  template <typename T, typename U>
1378  using result_is_implicit_value_convertible = std::integral_constant<bool,(
1379  result_is_value_convertible<T, U>::value &&
1380  std::is_convertible<U&&, T>::value
1381  )>;
1382 
1383  //-------------------------------------------------------------------------
1384 
1385  template <typename T1, typename E1, typename T2, typename E2>
1386  using result_is_convert_assignable = std::integral_constant<bool,(
1387  result_is_convertible<T1,E1,T2,E2>::value &&
1388 
1389  std::is_assignable<T1&, result<T2,E2>&>::value &&
1390  std::is_assignable<T1&, const result<T2,E2>&>::value &&
1391  std::is_assignable<T1&, result<T2,E2>&&>::value &&
1392  std::is_assignable<T1&, const result<T2,E2>&&>::value &&
1393 
1394  std::is_assignable<E1&, result<T2,E2>&>::value &&
1395  std::is_assignable<E1&, const result<T2,E2>&>::value &&
1396  std::is_assignable<E1&, result<T2,E2>&&>::value &&
1397  std::is_assignable<E1&, const result<T2,E2>&&>::value
1398  )>;
1399 
1400  template <typename T1, typename E1, typename T2, typename E2>
1401  using result_is_copy_convert_assignable = std::integral_constant<bool,(
1402  !result_is_convert_assignable<T1,E1,T2,E2>::value &&
1403 
1404  std::is_nothrow_constructible<T1, const T2&>::value &&
1405  std::is_assignable<wrapped_result_type<T1>&, const T2&>::value &&
1406  std::is_nothrow_constructible<E1, const E2&>::value &&
1407  std::is_assignable<E1&, const E2&>::value
1408  )>;
1409 
1410  template <typename T1, typename E1, typename T2, typename E2>
1411  using result_is_move_convert_assignable = std::integral_constant<bool,(
1412  !result_is_convert_assignable<T1,E1,T2,E2>::value &&
1413 
1414  std::is_nothrow_constructible<T1, T2&&>::value &&
1415  std::is_assignable<T1&, T2&&>::value &&
1416  std::is_nothrow_constructible<E1, E2&&>::value &&
1417  std::is_assignable<E1&, E2&&>::value
1418  )>;
1419 
1420  //-------------------------------------------------------------------------
1421 
1422  template <typename T, typename U>
1423  using result_is_value_assignable = std::integral_constant<bool,(
1424  !is_result<typename std::decay<U>::type>::value &&
1425  !is_failure<typename std::decay<U>::type>::value &&
1426  std::is_nothrow_constructible<T,U>::value &&
1427  std::is_assignable<wrapped_result_type<T>&,U>::value &&
1428  (
1429  !std::is_same<typename std::decay<U>::type,typename std::decay<T>::type>::value ||
1430  !std::is_scalar<T>::value
1431  )
1432  )>;
1433 
1434  template <typename E, typename E2>
1435  using result_is_failure_assignable = std::integral_constant<bool,(
1436  std::is_nothrow_constructible<E,E2>::value &&
1437  std::is_assignable<E&,E2>::value
1438  )>;
1439 
1440  // Friending 'extract_error" below was causing some compilers to incorrectly
1441  // identify `exp.m_storage.m_error` as being an access violation despite the
1442  // friendship. Using a type name instead seems to be ubiquitous across
1443  // compilers
1444  struct result_error_extractor
1445  {
1446  template <typename T, typename E>
1447  static constexpr auto get(const result<T,E>& exp) noexcept -> const E&;
1448  template <typename T, typename E>
1449  static constexpr auto get(result<T,E>& exp) noexcept -> E&;
1450  };
1451 
1452  template <typename T, typename E>
1453  constexpr auto extract_error(const result<T,E>& exp) noexcept -> const E&;
1454 
1455  template <typename E>
1456  [[noreturn]]
1457  auto throw_bad_result_access(E&& error) -> void;
1458 
1459  template <typename String, typename E>
1460  [[noreturn]]
1461  auto throw_bad_result_access_message(String&& message, E&& error) -> void;
1462 
1463  } // namespace detail
1464 
1465  /////////////////////////////////////////////////////////////////////////////
1466  /// \brief The class template `result` manages result results from APIs,
1467  /// while encoding possible failure conditions.
1468  ///
1469  /// A common use-case for result is the return value of a function that
1470  /// may fail. As opposed to other approaches, such as `std::pair<T,bool>`
1471  /// or `std::optional`, `result` more accurately conveys the intent of the
1472  /// user along with the failure condition to the caller. This effectively
1473  /// produces an orthogonal error handling mechanism that allows for exception
1474  /// safety while also allowing discrete testability of the return type.
1475  ///
1476  /// `result<T,E>` types may contain a `T` value, which signifies that an
1477  /// operation succeeded in producing the result value of type `T`. If an
1478  /// `result` does not contain a `T` value, it will always contain an `E`
1479  /// error condition instead.
1480  ///
1481  /// An `result<T,E>` can always be queried for a possible error case by
1482  /// calling the `error()` function, even if it contains a value.
1483  /// In the case that a `result<T,E>` contains a value object, this will
1484  /// simply return an `E` object constructed through default aggregate
1485  /// construction, as if through the expression `E{}`, which is assumed to be
1486  /// a "valid" (no-error) state for an `E` type.
1487  /// For example:
1488  ///
1489  /// * `std::error_code{}` produces a default-construct error-code, which is
1490  /// the "no error" state,
1491  /// * integral (or enum) error codes produce a `0` value (no error), thanks to
1492  /// zero-initialization,
1493  /// * `std::exception_ptr{}` produces a null-pointer,
1494  /// * `std::string{}` produces an empty string `""`,
1495  /// * etc.
1496  ///
1497  /// When a `result<T,E>` contains either a value or error, the storage for
1498  /// that object is guaranteed to be allocated as part of the result
1499  /// object's footprint, i.e. no dynamic memory allocation ever takes place.
1500  /// Thus, a result object models an object, not a pointer, even though the
1501  /// `operator*()` and `operator->()` are defined.
1502  ///
1503  /// When an object of type `result<T,E>` is contextually converted to
1504  /// `bool`, the conversion returns `true` if the object contains a value and
1505  /// `false` if it contains an error.
1506  ///
1507  /// `result` objects do not have a "valueless" state like `variant`s do.
1508  /// Once a `result` has been constructed with a value or error, the
1509  /// active underlying type can only be changed through assignment which may
1510  /// is only enabled if construction is guaranteed to be *non-throwing*. This
1511  /// ensures that a valueless state cannot occur naturally.
1512  ///
1513  /// Example Use:
1514  /// \code
1515  /// auto to_string(int x) -> result<std::string>
1516  /// {
1517  /// try {
1518  /// return std::stoi(x);
1519  /// } catch (const std::invalid_argument&) {
1520  /// return fail(std::errc::invalid_argument);
1521  /// } catch (const std::std::out_of_range&) {
1522  /// return fail(std::errc::result_out_of_range);
1523  /// }
1524  /// }
1525  /// \endcode
1526  ///
1527  /// \note If using C++17 or above, `fail` can be replaced with
1528  /// `failure{...}` thanks to CTAD.
1529  ///
1530  /// \tparam T the underlying value type
1531  /// \tparam E the underlying error type
1532  ///////////////////////////////////////////////////////////////////////////
1533  template <typename T, typename E>
1534  class RESULT_NODISCARD result
1535  {
1536  // Type requirements
1537 
1538  static_assert(
1539  !std::is_abstract<T>::value,
1540  "It is ill-formed for T to be abstract type"
1541  );
1542  static_assert(
1543  !std::is_same<typename std::decay<T>::type, in_place_t>::value,
1544  "It is ill-formed for T to be a (possibly CV-qualified) in_place_t type"
1545  );
1546  static_assert(
1547  !is_result<typename std::decay<T>::type>::value,
1548  "It is ill-formed for T to be a (possibly CV-qualified) 'result' type"
1549  );
1550  static_assert(
1551  !is_failure<typename std::decay<T>::type>::value,
1552  "It is ill-formed for T to be a (possibly CV-qualified) 'failure' type"
1553  );
1554  static_assert(
1555  !std::is_rvalue_reference<T>::value,
1556  "It is ill-formed for T to be an rvalue 'result type. "
1557  "Only lvalue references are valid."
1558  );
1559 
1560  static_assert(
1561  !std::is_abstract<E>::value,
1562  "It is ill-formed for E to be abstract type"
1563  );
1564  static_assert(
1565  !std::is_void<typename std::decay<E>::type>::value,
1566  "It is ill-formed for E to be (possibly CV-qualified) void type"
1567  );
1568  static_assert(
1569  !is_result<typename std::decay<E>::type>::value,
1570  "It is ill-formed for E to be a (possibly CV-qualified) 'result' type"
1571  );
1572  static_assert(
1573  !is_failure<typename std::decay<E>::type>::value,
1574  "It is ill-formed for E to be a (possibly CV-qualified) 'failure' type"
1575  );
1576  static_assert(
1577  !std::is_same<typename std::decay<E>::type, in_place_t>::value,
1578  "It is ill-formed for E to be a (possibly CV-qualified) in_place_t type"
1579  );
1580  static_assert(
1581  !std::is_reference<E>::value,
1582  "It is ill-formed for E to be a reference type. "
1583  "Only T types may be lvalue references"
1584  );
1585 
1586  // Friendship
1587 
1588  friend detail::result_error_extractor;
1589 
1590  template <typename T2, typename E2>
1591  friend class result;
1592 
1593  //-------------------------------------------------------------------------
1594  // Public Member Types
1595  //-------------------------------------------------------------------------
1596  public:
1597 
1598  using value_type = T; ///< The value type of this result
1599  using error_type = E; ///< The error type of this result
1600  using failure_type = failure<E>; ///< The failure type
1601 
1602  template <typename U>
1603  using rebind = result<U,E>; ///< Rebinds the result type
1604 
1605  //-------------------------------------------------------------------------
1606  // Constructor / Destructor / Assignment
1607  //-------------------------------------------------------------------------
1608  public:
1609 
1610  /// \brief Default-constructs a result with the underlying value type
1611  /// active
1612  ///
1613  /// This constructor is only enabled if `T` is default-constructible
1614  ///
1615  /// ### Examples
1616  ///
1617  /// Basic Usage:
1618  ///
1619  /// ```cpp
1620  /// assert(cpp::result<std::string,int>{} == std::string{});
1621  /// ```
1622  template <typename U=T,
1623  typename = typename std::enable_if<std::is_constructible<U>::value>::type>
1624  constexpr result()
1625  noexcept(std::is_nothrow_constructible<U>::value);
1626 
1627  /// \brief Copy constructs this result
1628  ///
1629  /// If \p other contains a value, initializes the contained value as if
1630  /// direct-initializing (but not direct-list-initializing) an object of
1631  /// type `T` with the expression *other.
1632  ///
1633  /// If other contains an error, constructs an object that contains a copy
1634  /// of that error.
1635  ///
1636  /// \note This constructor is defined as deleted if
1637  /// `std::is_copy_constructible<T>::value` or
1638  /// `std::is_copy_constructible<E>::value` is `false`
1639  ///
1640  /// \note This constructor is defined as trivial if both
1641  /// `std::is_trivially_copy_constructible<T>::value` and
1642  /// `std::is_trivially_copy_constructible<E>::value` are `true`
1643  ///
1644  /// ### Examples
1645  ///
1646  /// Basic Usage:
1647  ///
1648  /// ```cpp
1649  /// const auto r = cpp::result<int,int>{42};
1650  /// const auto s = r;
1651  ///
1652  /// assert(r == s);
1653  /// ```
1654  ///
1655  /// \param other the result to copy
1656  constexpr result(const result& other) = default;
1657 
1658  /// \brief Move constructs a result
1659  ///
1660  /// If other contains a value, initializes the contained value as if
1661  /// direct-initializing (but not direct-list-initializing) an object
1662  /// of type T with the expression `std::move(*other)` and does not make
1663  /// other empty: a moved-from result still contains a value, but the
1664  /// value itself is moved from.
1665  ///
1666  /// If other contains an error, move-constructs this result from that
1667  /// error.
1668  ///
1669  /// \note This constructor is defined as deleted if
1670  /// `std::is_move_constructible<T>::value` or
1671  /// `std::is_move_constructible<E>::value` is `false`
1672  ///
1673  /// \note This constructor is defined as trivial if both
1674  /// `std::is_trivially_move_constructible<T>::value` and
1675  /// `std::is_trivially_move_constructible<E>::value` are `true`
1676  ///
1677  /// ### Examples
1678  ///
1679  /// Basic Usage:
1680  ///
1681  /// ```cpp
1682  /// auto r = cpp::result<std::string,int>{"hello world"};
1683  /// auto s = std::move(r);
1684  ///
1685  /// assert(s == "hello world");
1686  /// ```
1687  ///
1688  /// \param other the result to move
1689  constexpr result(result&& other) = default;
1690 
1691  /// \{
1692  /// \brief Converting copy constructor
1693  ///
1694  /// If \p other contains a value, constructs a result object
1695  /// that contains a value, initialized as if direct-initializing
1696  /// (but not direct-list-initializing) an object of type `T` with the
1697  /// expression `*other`.
1698  ///
1699  /// If \p other contains an error, constructs a result object that
1700  /// contains an error, initialized as if direct-initializing
1701  /// (but not direct-list-initializing) an object of type `E`.
1702  ///
1703  /// \note This constructor does not participate in overload resolution
1704  /// unless the following conditions are met:
1705  /// - `std::is_constructible_v<T, const U&>` is `true`
1706  /// - T is not constructible or convertible from any expression
1707  /// of type (possibly const) `result<T2,E2>`
1708  /// - E is not constructible or convertible from any expression
1709  /// of type (possible const) `result<T2,E2>`
1710  ///
1711  /// \note This constructor is explicit if and only if
1712  /// `std::is_convertible_v<const T2&, T>` or
1713  /// `std::is_convertible_v<const E2&, E>` is `false`
1714  ///
1715  /// ### Examples
1716  ///
1717  /// Basic Usage:
1718  ///
1719  /// ```cpp
1720  /// const auto r = cpp::result<int,int>{42};
1721  /// const auto s = cpp::result<long,long>{r};
1722  ///
1723  /// assert(r == s);
1724  /// ```
1725  ///
1726  /// \param other the other type to convert
1727  template <typename T2, typename E2,
1728  typename std::enable_if<detail::result_is_implicit_copy_convertible<T,E,T2,E2>::value,int>::type = 0>
1729  result(const result<T2,E2>& other)
1730  noexcept(std::is_nothrow_constructible<T,const T2&>::value &&
1731  std::is_nothrow_constructible<E,const E2&>::value);
1732  template <typename T2, typename E2,
1733  typename std::enable_if<detail::result_is_explicit_copy_convertible<T,E,T2,E2>::value,int>::type = 0>
1734  explicit result(const result<T2,E2>& other)
1735  noexcept(std::is_nothrow_constructible<T,const T2&>::value &&
1736  std::is_nothrow_constructible<E,const E2&>::value);
1737  /// \}
1738 
1739  /// \{
1740  /// \brief Converting move constructor
1741  ///
1742  /// If \p other contains a value, constructs a result object
1743  /// that contains a value, initialized as if direct-initializing
1744  /// (but not direct-list-initializing) an object of type T with the
1745  /// expression `std::move(*other)`.
1746  ///
1747  /// If \p other contains an error, constructs a result object that
1748  /// contains an error, initialized as if direct-initializing
1749  /// (but not direct-list-initializing) an object of type E&&.
1750  ///
1751  /// \note This constructor does not participate in overload resolution
1752  /// unless the following conditions are met:
1753  /// - `std::is_constructible_v<T, const U&>` is `true`
1754  /// - T is not constructible or convertible from any expression
1755  /// of type (possibly const) `result<T2,E2>`
1756  /// - E is not constructible or convertible from any expression
1757  /// of type (possible const) `result<T2,E2>`
1758  ///
1759  /// \note This constructor is explicit if and only if
1760  /// `std::is_convertible_v<const T2&, T>` or
1761  /// `std::is_convertible_v<const E2&, E>` is `false`
1762  ///
1763  /// ### Examples
1764  ///
1765  /// Basic Usage:
1766  ///
1767  /// ```cpp
1768  /// auto r = cpp::result<std::unique_ptr<Derived>,int>{
1769  /// std::make_unique<Derived>()
1770  /// };
1771  /// const auto s = cpp::result<std::unique_ptr<Base>,long>{
1772  /// std::move(r)
1773  /// };
1774  /// ```
1775  ///
1776  /// \param other the other type to convert
1777  template <typename T2, typename E2,
1778  typename std::enable_if<detail::result_is_implicit_move_convertible<T,E,T2,E2>::value,int>::type = 0>
1779  result(result<T2,E2>&& other)
1780  noexcept(std::is_nothrow_constructible<T,T2&&>::value &&
1782  template <typename T2, typename E2,
1783  typename std::enable_if<detail::result_is_explicit_move_convertible<T,E,T2,E2>::value,int>::type = 0>
1784  explicit result(result<T2,E2>&& other)
1785  noexcept(std::is_nothrow_constructible<T,T2&&>::value &&
1787  /// \}
1788 
1789  //-------------------------------------------------------------------------
1790 
1791  /// \brief Constructs a result object that contains a value
1792  ///
1793  /// The value is initialized as if direct-initializing (but not
1794  /// direct-list-initializing) an object of type `T` from the arguments
1795  /// `std::forward<Args>(args)...`
1796  ///
1797  /// ### Examples
1798  ///
1799  /// Basic Usage:
1800  ///
1801  /// ```cpp
1802  /// auto r = cpp::result<std::string,int>{
1803  /// cpp::in_place, "Hello world"
1804  /// };
1805  /// ```
1806  ///
1807  /// \param args the arguments to pass to T's constructor
1808  template <typename...Args,
1809  typename = typename std::enable_if<std::is_constructible<T,Args...>::value>::type>
1810  constexpr explicit result(in_place_t, Args&&... args)
1811  noexcept(std::is_nothrow_constructible<T, Args...>::value);
1812 
1813  /// \brief Constructs a result object that contains a value
1814  ///
1815  /// The value is initialized as if direct-initializing (but not
1816  /// direct-list-initializing) an object of type `T` from the arguments
1817  /// `std::forward<std::initializer_list<U>>(ilist)`,
1818  /// `std::forward<Args>(args)...`
1819  ///
1820  /// ### Examples
1821  ///
1822  /// Basic Usage:
1823  ///
1824  /// ```cpp
1825  /// auto r = cpp::result<std::string,int>{
1826  /// cpp::in_place, {'H','e','l','l','o'}
1827  /// };
1828  /// ```
1829  ///
1830  /// \param ilist An initializer list of entries to forward
1831  /// \param args the arguments to pass to T's constructor
1832  template <typename U, typename...Args,
1833  typename = typename std::enable_if<std::is_constructible<T, std::initializer_list<U>&, Args...>::value>::type>
1834  constexpr explicit result(in_place_t,
1835  std::initializer_list<U> ilist,
1836  Args&&...args)
1838 
1839  //-------------------------------------------------------------------------
1840 
1841  /// \brief Constructs a result object that contains an error
1842  ///
1843  /// the value is initialized as if direct-initializing (but not
1844  /// direct-list-initializing) an object of type `E` from the arguments
1845  /// `std::forward<Args>(args)...`
1846  ///
1847  /// ### Examples
1848  ///
1849  /// Basic Usage:
1850  ///
1851  /// ```cpp
1852  /// auto r = cpp::result<int,std::string>{
1853  /// cpp::in_place_error, "Hello world"
1854  /// };
1855  /// ```
1856  ///
1857  /// \param args the arguments to pass to E's constructor
1858  template <typename...Args,
1859  typename = typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
1860  constexpr explicit result(in_place_error_t, Args&&... args)
1861  noexcept(std::is_nothrow_constructible<E, Args...>::value);
1862 
1863  /// \brief Constructs a result object that contains an error
1864  ///
1865  /// The value is initialized as if direct-initializing (but not
1866  /// direct-list-initializing) an object of type `E` from the arguments
1867  /// `std::forward<std::initializer_list<U>>(ilist)`,
1868  /// `std::forward<Args>(args)...`
1869  ///
1870  /// ### Examples
1871  ///
1872  /// Basic Usage:
1873  ///
1874  /// ```cpp
1875  /// auto r = cpp::result<int,std::string>{
1876  /// cpp::in_place_error, {'H','e','l','l','o'}
1877  /// };
1878  /// ```
1879  ///
1880  /// \param ilist An initializer list of entries to forward
1881  /// \param args the arguments to pass to Es constructor
1882  template <typename U, typename...Args,
1883  typename = typename std::enable_if<std::is_constructible<E, std::initializer_list<U>&, Args...>::value>::type>
1884  constexpr explicit result(in_place_error_t,
1885  std::initializer_list<U> ilist,
1886  Args&&...args)
1888 
1889  //-------------------------------------------------------------------------
1890 
1891  /// \{
1892  /// \brief Constructs the underlying error of this result
1893  ///
1894  /// \note This constructor only participates in overload resolution if
1895  /// `E` is constructible from \p e
1896  ///
1897  /// ### Examples
1898  ///
1899  /// Basic Usage:
1900  ///
1901  /// ```cpp
1902  /// cpp::result<int,int> r = cpp::fail(42);
1903  ///
1904  /// auto get_error_result() -> cpp::result<int,std::string> {
1905  /// return cpp::fail("hello world!");
1906  /// }
1907  /// ```
1908  ///
1909  /// \param e the failure error
1910  template <typename E2,
1911  typename = typename std::enable_if<std::is_constructible<E,const E2&>::value>::type>
1912  constexpr /* implicit */ result(const failure<E2>& e)
1913  noexcept(std::is_nothrow_constructible<E,const E2&>::value);
1914  template <typename E2,
1915  typename = typename std::enable_if<std::is_constructible<E,E2&&>::value>::type>
1916  constexpr /* implicit */ result(failure<E2>&& e)
1917  noexcept(std::is_nothrow_constructible<E,E2&&>::value);
1918  /// \}
1919 
1920  /// \{
1921  /// \brief Constructs a result object that contains a value
1922  ///
1923  /// The value is initialized as if direct-initializing (but not
1924  /// direct-list-initializing) an object of type T with the expression
1925  /// value.
1926  ///
1927  /// \note This constructor is constexpr if the constructor of T
1928  /// selected by direct-initialization is constexpr
1929  ///
1930  /// \note This constructor does not participate in overload
1931  /// resolution unless `std::is_constructible_v<T, U&&>` is true
1932  /// and `decay_t<U>` is neither `in_place_t`, `in_place_error_t`,
1933  /// nor a `result` type.
1934  ///
1935  /// \note This constructor is explicit if and only if
1936  /// `std::is_convertible_v<U&&, T>` is `false`
1937  ///
1938  /// ### Examples
1939  ///
1940  /// Basic Usage:
1941  ///
1942  /// ```cpp
1943  /// cpp::result<int,int> r = 42;
1944  ///
1945  /// auto get_value() -> cpp::result<std::string,int> {
1946  /// return "hello world!"; // implicit conversion
1947  /// }
1948  /// ```
1949  ///
1950  /// \param value the value to copy
1951  template <typename U,
1952  typename std::enable_if<detail::result_is_explicit_value_convertible<T,U>::value,int>::type = 0>
1953  constexpr explicit result(U&& value)
1954  noexcept(std::is_nothrow_constructible<T,U>::value);
1955  template <typename U,
1956  typename std::enable_if<detail::result_is_implicit_value_convertible<T,U>::value,int>::type = 0>
1957  constexpr /* implicit */ result(U&& value)
1958  noexcept(std::is_nothrow_constructible<T,U>::value);
1959  /// \}
1960 
1961  //-------------------------------------------------------------------------
1962 
1963  /// \brief Copy assigns the result stored in \p other
1964  ///
1965  /// \note This assignment operator only participates in overload resolution
1966  /// if the following conditions are met:
1967  /// - `std::is_nothrow_copy_constructible_v<T>` is `true`, and
1968  /// - `std::is_nothrow_copy_constructible_v<E>` is `true`
1969  /// this restriction guarantees that no '
1970  ///
1971  /// \note This assignment operator is defined as trivial if the following
1972  /// conditions are all `true`:
1973  /// - `std::is_trivially_copy_constructible<T>::value`
1974  /// - `std::is_trivially_copy_constructible<E>::value`
1975  /// - `std::is_trivially_copy_assignable<T>::value`
1976  /// - `std::is_trivially_copy_assignable<E>::value`
1977  /// - `std::is_trivially_destructible<T>::value`
1978  /// - `std::is_trivially_destructible<E>::value`
1979  ///
1980  /// \param other the other result to copy
1981  auto operator=(const result& other) -> result& = default;
1982 
1983  /// \brief Move assigns the result stored in \p other
1984  ///
1985  /// \note This assignment operator only participates in overload resolution
1986  /// if the following conditions are met:
1987  /// - `std::is_nothrow_copy_constructible_v<T>` is `true`, and
1988  /// - `std::is_nothrow_copy_constructible_v<E>` is `true`
1989  /// this restriction guarantees that no 'valueless_by_exception` state
1990  /// may occur.
1991  ///
1992  /// \note This assignment operator is defined as trivial if the following
1993  /// conditions are all `true`:
1994  /// - `std::is_trivially_move_constructible<T>::value`
1995  /// - `std::is_trivially_move_constructible<E>::value`
1996  /// - `std::is_trivially_move_assignable<T>::value`
1997  /// - `std::is_trivially_move_assignable<E>::value`
1998  /// - `std::is_trivially_destructible<T>::value`
1999  /// - `std::is_trivially_destructible<E>::value`
2000  ///
2001  /// \param other the other result to copy
2002  auto operator=(result&& other) -> result& = default;
2003 
2004  /// \brief Copy-converts the state of \p other
2005  ///
2006  /// If both `*this` and \p other contain either values or errors, the
2007  /// underlying value is constructed as if through assignment.
2008  ///
2009  /// Otherwise if `*this` contains a value, but \p other contains an error,
2010  /// then the contained value is destroyed by calling its destructor. `*this`
2011  /// will no longer contain a value after the call, and will now contain `E`
2012  /// constructed as if direct-initializing (but not direct-list-initializing)
2013  /// an object with an argument of `const E2&`.
2014  ///
2015  /// If \p other contains a value and `*this` contains an error, then the
2016  /// contained error is destroyed by calling its destructor. `*this` now
2017  /// contains a value constructed as if direct-initializing (but not
2018  /// direct-list-initializing) an object with an argument of `const T2&`.
2019  ///
2020  /// \note The function does not participate in overload resolution unless
2021  /// - `std::is_nothrow_constructible_v<T, const T2&>`,
2022  /// `std::is_assignable_v<T&, const T2&>`,
2023  /// `std::is_nothrow_constructible_v<E, const E2&>`,
2024  /// `std::is_assignable_v<E&, const E2&>` are all true.
2025  /// - T is not constructible, convertible, or assignable from any
2026  /// expression of type (possibly const) `result<T2,E2>`
2027  ///
2028  /// \param other the other result object to convert
2029  /// \return reference to `(*this)`
2030  template <typename T2, typename E2,
2031  typename = typename std::enable_if<detail::result_is_copy_convert_assignable<T,E,T2,E2>::value>::type>
2032  auto operator=(const result<T2,E2>& other)
2033  noexcept(std::is_nothrow_assignable<T,const T2&>::value &&
2034  std::is_nothrow_assignable<E,const E2&>::value) -> result&;
2035 
2036  /// \brief Move-converts the state of \p other
2037  ///
2038  /// If both `*this` and \p other contain either values or errors, the
2039  /// underlying value is constructed as if through move-assignment.
2040  ///
2041  /// Otherwise if `*this` contains a value, but \p other contains an error,
2042  /// then the contained value is destroyed by calling its destructor. `*this`
2043  /// will no longer contain a value after the call, and will now contain `E`
2044  /// constructed as if direct-initializing (but not direct-list-initializing)
2045  /// an object with an argument of `E2&&`.
2046  ///
2047  /// If \p other contains a value and `*this` contains an error, then the
2048  /// contained error is destroyed by calling its destructor. `*this` now
2049  /// contains a value constructed as if direct-initializing (but not
2050  /// direct-list-initializing) an object with an argument of `T2&&`.
2051  ///
2052  /// \note The function does not participate in overload resolution unless
2053  /// - `std::is_nothrow_constructible_v<T, T2&&>`,
2054  /// `std::is_assignable_v<T&, T2&&>`,
2055  /// `std::is_nothrow_constructible_v<E, E2&&>`,
2056  /// `std::is_assignable_v<E&, E2&&>` are all true.
2057  /// - T is not constructible, convertible, or assignable from any
2058  /// expression of type (possibly const) `result<T2,E2>`
2059  ///
2060  /// \param other the other result object to convert
2061  /// \return reference to `(*this)`
2062  template <typename T2, typename E2,
2063  typename = typename std::enable_if<detail::result_is_move_convert_assignable<T,E,T2,E2>::value>::type>
2064  auto operator=(result<T2,E2>&& other)
2065  noexcept(std::is_nothrow_assignable<T,T2&&>::value &&
2066  std::is_nothrow_assignable<E,E2&&>::value) -> result&;
2067 
2068  /// \brief Perfect-forwarded assignment
2069  ///
2070  /// Depending on whether `*this` contains a value before the call, the
2071  /// contained value is either direct-initialized from std::forward<U>(value)
2072  /// or assigned from std::forward<U>(value).
2073  ///
2074  /// \note The function does not participate in overload resolution unless
2075  /// - `std::decay_t<U>` is not a result type,
2076  /// - `std::decay_t<U>` is not a failure type
2077  /// - `std::is_nothrow_constructible_v<T, U>` is `true`
2078  /// - `std::is_assignable_v<T&, U>` is `true`
2079  /// - and at least one of the following is `true`:
2080  /// - `T` is not a scalar type;
2081  /// - `std::decay_t<U>` is not `T`.
2082  ///
2083  /// \param value to assign to the contained value
2084  /// \return reference to `(*this)`
2085  template <typename U,
2086  typename = typename std::enable_if<detail::result_is_value_assignable<T,U>::value>::type>
2087  auto operator=(U&& value)
2088  noexcept(std::is_nothrow_assignable<T,U>::value) -> result&;
2089 
2090  /// \{
2091  /// \brief Perfect-forwarded assignment
2092  ///
2093  /// Depending on whether `*this` contains an error before the call, the
2094  /// contained error is either direct-initialized via forwarding the error,
2095  /// or assigned from forwarding the error
2096  ///
2097  /// \note The function does not participate in overload resolution unless
2098  /// - `std::is_nothrow_constructible_v<E, E2>` is `true`, and
2099  /// - `std::is_assignable_v<E&, E2>` is `true`
2100  ///
2101  /// \param other the failure value to assign to this
2102  /// \return reference to `(*this)`
2103  template <typename E2,
2104  typename = typename std::enable_if<detail::result_is_failure_assignable<E,const E2&>::value>::type>
2105  auto operator=(const failure<E2>& other)
2106  noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> result&;
2107  template <typename E2,
2108  typename = typename std::enable_if<detail::result_is_failure_assignable<E,E2&&>::value>::type>
2109  auto operator=(failure<E2>&& other)
2110  noexcept(std::is_nothrow_assignable<E, E2&&>::value) -> result&;
2111  /// \}
2112 
2113  //-------------------------------------------------------------------------
2114  // Observers
2115  //-------------------------------------------------------------------------
2116  public:
2117 
2118  /// \{
2119  /// \brief Retrieves a pointer to the contained value
2120  ///
2121  /// This operator exists to give `result` an `optional`-like API for cases
2122  /// where it's known that the `result` already contains a value.
2123  ///
2124  /// Care must be taken to ensure that this is only used in safe contexts
2125  /// where a `T` value is active.
2126  ///
2127  /// \note The behavior is undefined if `*this` does not contain a value.
2128  ///
2129  /// ### Examples
2130  ///
2131  /// Basic Usage:
2132  ///
2133  /// ```cpp
2134  /// auto r = cpp::result<Widget,int>{
2135  /// make_widget()
2136  /// };
2137  ///
2138  /// r->do_something();
2139  /// ```
2140  ///
2141  /// \return a pointer to the contained value
2144  noexcept -> typename std::remove_reference<T>::type*;
2146  constexpr auto operator->()
2147  const noexcept -> typename std::remove_reference<typename std::add_const<T>::type>::type*;
2148  /// \}
2149 
2150  /// \{
2151  /// \brief Retrieves a reference to the contained value
2152  ///
2153  /// This operator exists to give `result` an `optional`-like API for cases
2154  /// where it's known that the `result` already contains a value.
2155  ///
2156  /// Care must be taken to ensure that this is only used in safe contexts
2157  /// where a `T` value is active.
2158  ///
2159  /// \note The behaviour is undefined if `*this` does not contain a value
2160  ///
2161  /// ### Examples
2162  ///
2163  /// Basic Usage:
2164  ///
2165  /// ```cpp
2166  /// auto r = cpp::result<Widget,int>{
2167  /// make_widget()
2168  /// };
2169  ///
2170  /// (*r).do_something();
2171  ///
2172  /// consume(*r);
2173  /// ```
2174  ///
2175  /// \return a reference to the contained value
2178  & noexcept -> typename std::add_lvalue_reference<T>::type;
2180  RESULT_CPP14_CONSTEXPR auto operator*()
2181  && noexcept -> typename std::add_rvalue_reference<T>::type;
2183  constexpr auto operator*()
2184  const& noexcept -> typename std::add_lvalue_reference<typename std::add_const<T>::type>::type;
2186  constexpr auto operator*()
2187  const&& noexcept -> typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
2188  /// \}
2189 
2190  //-------------------------------------------------------------------------
2191 
2192  /// \brief Contextually convertible to `true` if `*this` contains a value
2193  ///
2194  /// This function exists to allow for simple, terse checks for containing
2195  /// a value.
2196  ///
2197  /// ### Examples
2198  ///
2199  /// Basic Usage:
2200  ///
2201  /// ```cpp
2202  /// auto get_result() -> cpp::result<int, int>;
2203  /// auto r = get_result();
2204  /// if (r) { ... }
2205  ///
2206  /// assert(static_cast<bool>(cpp::result<int,int>{42}));
2207  ///
2208  /// assert(!static_cast<bool>(cpp::result<int,int>{cpp::fail(42)}));
2209  /// ```
2210  ///
2211  /// \return `true` if `*this` contains a value, `false` if `*this`
2212  /// does not contain a value
2214  constexpr explicit operator bool() const noexcept;
2215 
2216  /// \brief Returns `true` if `*this` contains a value
2217  ///
2218  /// ### Examples
2219  ///
2220  /// Basic Usage:
2221  ///
2222  /// ```cpp
2223  /// auto get_result() -> cpp::result<int, int>;
2224  /// auto r = get_result();
2225  /// if (r.has_value()) { ... }
2226  ///
2227  /// assert(cpp::result<int,int>{42}.has_value());
2228  ///
2229  /// assert(!cpp::result<int,int>{cpp::fail(42)}.has_value());
2230  /// ```
2231  ///
2232  /// \return `true` if `*this` contains a value, `false` if `*this`
2233  /// contains an error
2235  constexpr auto has_value() const noexcept -> bool;
2236 
2237  /// \brief Returns `true` if `*this` contains an error
2238  ///
2239  /// ### Examples
2240  ///
2241  /// Basic Usage:
2242  ///
2243  /// ```cpp
2244  /// auto get_result() -> cpp::result<int, int>;
2245  ///
2246  /// auto r = get_result();
2247  /// if (r.has_error()) { ... }
2248  ///
2249  /// assert(!cpp::result<int,int>{42}.has_error());
2250  ///
2251  /// assert(cpp::result<int,int>{cpp::fail(42)}.has_error());
2252  /// ```
2253  ///
2254  /// \return `true` if `*this` contains an error, `false` if `*this`
2255  /// contains a value
2257  constexpr auto has_error() const noexcept -> bool;
2258 
2259  //-------------------------------------------------------------------------
2260 
2261  /// \{
2262  /// \brief Returns a reference to the contained value
2263  ///
2264  /// This function provides checked (throwing) access to the underlying
2265  /// value. The constness and refness of this result is propagated to the
2266  /// underlying reference.
2267  ///
2268  /// If this contains an error, an exception is thrown containing the
2269  /// underlying error. The error is consumed propagating the same constness
2270  /// and refness of this result.
2271  ///
2272  /// ### Examples
2273  ///
2274  /// Basic Usage:
2275  ///
2276  /// ```cpp
2277  /// assert(cpp::result<int,int>{42}.value() == 42);
2278  ///
2279  /// auto r = cpp::result<std::unique_ptr<int>,int>{
2280  /// std::make_unique<int>(42)
2281  /// };
2282  /// auto s = std::move(r).value();
2283  ///
2284  /// try {
2285  /// auto r = cpp::result<int,int>{ cpp::fail(42) };
2286  /// auto v = r.value();
2287  /// } catch (const cpp::bad_result_access<int>& e) {
2288  /// assert(e.error() == 42);
2289  /// }
2290  /// ```
2291  ///
2292  /// \throws bad_result_access<E> if `*this` does not contain a value.
2293  ///
2294  /// \return the value of `*this`
2297  & -> typename std::add_lvalue_reference<T>::type;
2299  RESULT_CPP14_CONSTEXPR auto value()
2300  && -> typename std::add_rvalue_reference<T>::type;
2302  constexpr auto value()
2303  const & -> typename std::add_lvalue_reference<typename std::add_const<T>::type>::type;
2305  constexpr auto value()
2306  const && -> typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
2307  /// \}
2308 
2309  /// \{
2310  /// \brief Returns the contained error, if one exists, or a
2311  /// default-constructed error value
2312  ///
2313  /// The `error()` function will not throw any exceptions if `E` does not
2314  /// throw any exceptions for the copy or move construction.
2315  ///
2316  /// This is to limit the possible scope for exceptions, and to allow the
2317  /// error type to be treated as a "status"-like type, where the
2318  /// default-constructed case is considered the "good" state.
2319  ///
2320  /// If this function is invoked on an rvalue of a result, the error is
2321  /// returned via move-construction
2322  ///
2323  /// ### Requires
2324  ///
2325  /// * `std::is_default_constructible<E>::value` is `true`
2326  /// * `std::is_copy_constructible<E>::value` or
2327  /// `std::is_move_constructible<E>::value` is `true`
2328  /// * `E{}` represents the "good" (non-error) state
2329  ///
2330  /// ### Examples
2331  ///
2332  /// Basic Usage:
2333  ///
2334  /// ```cpp
2335  /// auto r = cpp::result<int,std::error_code>{ 42 };
2336  /// assert(r.error() == std::error_code{});
2337  ///
2338  /// auto r = cpp::result<int,std::error_code>{
2339  /// cpp::fail(std::io_errc::stream)
2340  /// };
2341  ///
2342  /// assert(r.error() == std::io_errc::stream);
2343  /// ```
2344  ///
2345  /// \return the error or a default-constructed error value
2347  constexpr auto error() const &
2348  noexcept(std::is_nothrow_constructible<E>::value &&
2351  RESULT_CPP14_CONSTEXPR auto error() &&
2352  noexcept(std::is_nothrow_constructible<E>::value &&
2353  std::is_nothrow_move_constructible<E>::value) -> E;
2354  /// }
2355 
2356  /// \{
2357  /// \brief Asserts an expectation that this result contains an error,
2358  /// throwing a bad_result_access on failure
2359  ///
2360  /// If this function is invoked from an rvalue of `result`, then this will
2361  /// consume the underlying error first, if there is one.
2362  ///
2363  /// \note This function exists as a means to allow for results to be marked
2364  /// `used` without requiring directly inspecting the underlying value.
2365  /// This is, in effect, equivalent to `assert(res.has_value())`,
2366  /// however it uses exceptions to ensure the stack can be unwound, and
2367  /// exceptions invoked.
2368  ///
2369  /// ### Examples
2370  ///
2371  /// Basic Usage:
2372  ///
2373  /// ```cpp
2374  /// auto start_service() -> cpp::result<void,int>;
2375  ///
2376  /// start_service().expect("Service failed to start!");
2377  /// ```
2378  ///
2379  /// \param message the message to provide to this expectation
2380  ///
2381  /// \return the value of `*this`
2382  template <typename String,
2383  typename = typename std::enable_if<(
2384  std::is_convertible<String,const std::string&>::value &&
2385  std::is_copy_constructible<E>::value
2386  )>::type>
2387  RESULT_CPP14_CONSTEXPR auto expect(String&& message) & -> typename std::add_lvalue_reference<T>::type;
2388  template <typename String,
2389  typename = typename std::enable_if<(
2390  std::is_convertible<String,const std::string&>::value &&
2391  std::is_move_constructible<E>::value
2392  )>::type>
2393  RESULT_CPP14_CONSTEXPR auto expect(String&& message) && -> typename std::add_rvalue_reference<T>::type;
2394  template <typename String,
2395  typename = typename std::enable_if<(
2396  std::is_convertible<String,const std::string&>::value &&
2397  std::is_copy_constructible<E>::value
2398  )>::type>
2399  RESULT_CPP14_CONSTEXPR auto expect(String&& message) const & -> typename std::add_lvalue_reference<typename std::add_const<T>::type>::type;
2400  template <typename String,
2401  typename = typename std::enable_if<(
2402  std::is_convertible<String,const std::string&>::value &&
2403  std::is_copy_constructible<E>::value
2404  )>::type>
2405  RESULT_CPP14_CONSTEXPR auto expect(String&& message) const && -> typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
2406  /// \}
2407 
2408  //-------------------------------------------------------------------------
2409  // Monadic Functionalities
2410  //-------------------------------------------------------------------------
2411  public:
2412 
2413  /// \{
2414  /// \brief Returns the contained value if `*this` has a value,
2415  /// otherwise returns \p default_value.
2416  ///
2417  /// ### Examples
2418  ///
2419  /// Basic Usage:
2420  ///
2421  /// ```cpp
2422  /// auto r = cpp::result<int,int>{42};
2423  /// assert(r.value_or(0) == 42);
2424  ///
2425  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2426  /// assert(r.value_or(0) == 0);
2427  /// ```
2428  ///
2429  /// \param default_value the value to use in case `*this` contains an error
2430  /// \return the contained value or \p default_value
2431  template <typename U>
2433  constexpr auto value_or(U&& default_value)
2434  const & -> typename std::remove_reference<T>::type;
2435  template <typename U>
2437  RESULT_CPP14_CONSTEXPR auto value_or(U&& default_value)
2438  && -> typename std::remove_reference<T>::type;
2439  /// \}
2440 
2441  /// \{
2442  /// \brief Returns the contained error if `*this` has an error,
2443  /// otherwise returns \p default_error.
2444  ///
2445  /// ### Examples
2446  ///
2447  /// Basic Usage:
2448  ///
2449  /// ```cpp
2450  /// auto r = cpp::result<int,int>{42};
2451  /// assert(r.error_or(0) == cpp::fail(0));
2452  ///
2453  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2454  /// assert(r.error_or(0) == cpp::fail(42));
2455  /// ```
2456  ///
2457  /// \param default_error the error to use in case `*this` is empty
2458  /// \return the contained value or \p default_error
2459  template <typename U>
2461  constexpr auto error_or(U&& default_error) const & -> error_type;
2462  template <typename U>
2464  RESULT_CPP14_CONSTEXPR auto error_or(U&& default_error) && -> error_type;
2465  /// \}
2466 
2467  //-------------------------------------------------------------------------
2468 
2469  /// \brief Returns a result containing \p value if this result contains
2470  /// a value, otherwise returns a result containing the current
2471  /// error.
2472  ///
2473  /// ### Examples
2474  ///
2475  /// Basic Usage:
2476  ///
2477  /// ```cpp
2478  /// auto r = cpp::result<int,int>{42};
2479  /// assert(r.and_then(100) == 100);
2480  ///
2481  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2482  /// assert(r.and_then(100) == cpp::fail(42));
2483  /// ```
2484  ///
2485  /// \param value the value to return as a result
2486  /// \return a result of \p value if this contains a value
2487  template <typename U>
2489  constexpr auto and_then(U&& value) const -> result<typename std::decay<U>::type,E>;
2490 
2491  /// \{
2492  /// \brief Invokes the function \p fn with the value of this result as
2493  /// the argument
2494  ///
2495  /// If this result contains an error, a result of the error is returned
2496  ///
2497  /// The function being called must return a `result` type or the program
2498  /// is ill-formed
2499  ///
2500  /// If this is called on an rvalue of `result` which contains an error,
2501  /// the returned `result` is constructed from an rvalue of that error.
2502  ///
2503  /// ### Examples
2504  ///
2505  /// Basic Usage:
2506  ///
2507  /// ```cpp
2508  /// auto to_string(int) -> cpp::result<std::string,int>;
2509  /// auto r = cpp::result<int,int>{42};
2510  /// assert(r.flat_map(to_string) == "42");
2511  ///
2512  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2513  /// assert(r.flat_map(to_string) == cpp::fail(42));
2514  /// ```
2515  ///
2516  /// \param fn the function to invoke with this
2517  /// \return The result of the function being called
2518  template <typename Fn>
2520  constexpr auto flat_map(Fn&& fn) const & -> detail::invoke_result_t<Fn, const T&>;
2521  template <typename Fn>
2523  RESULT_CPP14_CONSTEXPR auto flat_map(Fn&& fn) && -> detail::invoke_result_t<Fn, T&&>;
2524  /// \}
2525 
2526  /// \{
2527  /// \brief Invokes the function \p fn with the value of this result as
2528  /// the argument
2529  ///
2530  /// If this result is an error, the result of this function is that
2531  /// error. Otherwise this function wraps the result and returns it as an
2532  /// result.
2533  ///
2534  /// If this is called on an rvalue of `result` which contains an error,
2535  /// the returned `result` is constructed from an rvalue of that error.
2536  ///
2537  /// ### Examples
2538  ///
2539  /// Basic Usage:
2540  ///
2541  /// ```cpp
2542  /// auto to_string(int) -> std::string;
2543  /// auto r = cpp::result<int,int>{42};
2544  /// assert(r.map(to_string) == "42");
2545  ///
2546  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2547  /// assert(r.map(to_string) == cpp::fail(42));
2548  /// ```
2549  ///
2550  /// \param fn the function to invoke with this
2551  /// \return The result result of the function invoked
2552  template <typename Fn>
2554  constexpr auto map(Fn&& fn) const & -> result<detail::invoke_result_t<Fn,const T&>,E>;
2555  template <typename Fn>
2557  RESULT_CPP14_CONSTEXPR auto map(Fn&& fn) && -> result<detail::invoke_result_t<Fn,T&&>,E>;
2558  /// \}
2559 
2560  /// \{
2561  /// \brief Invokes the function \p fn with the error of this result as
2562  /// the argument
2563  ///
2564  /// If this result contains a value, the result of this function is that
2565  /// value. Otherwise the function is called with that error and returns the
2566  /// result as a result.
2567  ///
2568  /// If this is called on an rvalue of `result` which contains a value,
2569  /// the returned `result` is constructed from an rvalue of that value.
2570  ///
2571  /// ### Examples
2572  ///
2573  /// Basic Usage:
2574  ///
2575  /// ```cpp
2576  /// auto to_string(int) -> std::string;
2577  /// auto r = cpp::result<int,int>{42};
2578  /// assert(r.map_error(to_string) == 42);
2579  ///
2580  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2581  /// assert(r.map_error(to_string) == cpp::fail("42"));
2582  ///
2583  /// auto r = cpp::result<std::string,int>{};
2584  /// auto s = r.map(std::string::size); // 's' contains 'result<size_t,int>'
2585  /// ```
2586  ///
2587  /// \param fn the function to invoke with this
2588  /// \return The result result of the function invoked
2589  template <typename Fn>
2591  constexpr auto map_error(Fn&& fn)
2592  const & -> result<T, detail::invoke_result_t<Fn,const E&>>;
2593  template <typename Fn>
2595  RESULT_CPP14_CONSTEXPR auto map_error(Fn&& fn)
2596  && -> result<T, detail::invoke_result_t<Fn,E&&>>;
2597  /// \}
2598 
2599  /// \{
2600  /// \brief Invokes the function \p fn with the error of this result as
2601  /// the argument
2602  ///
2603  /// If this result contains a value, a result of the value is returned
2604  ///
2605  /// The function being called must return a `result` type or the program
2606  /// is ill-formed
2607  ///
2608  /// If this is called on an rvalue of `result` which contains an error,
2609  /// the returned `result` is constructed from an rvalue of that error.
2610  ///
2611  /// ### Examples
2612  ///
2613  /// Basic Usage:
2614  ///
2615  /// ```cpp
2616  /// auto to_string(int) -> cpp::result<int,std::string>;
2617  /// auto r = cpp::result<int,int>{42};
2618  /// assert(r.flat_map(to_string) == 42);
2619  ///
2620  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2621  /// assert(r.flat_map(to_string) == cpp::fail("42"));
2622  /// ```
2623  ///
2624  /// \param fn the function to invoke with this
2625  /// \return The result of the function being called
2626  template <typename Fn>
2628  constexpr auto flat_map_error(Fn&& fn)
2629  const & -> detail::invoke_result_t<Fn, const E&>;
2630  template <typename Fn>
2632  RESULT_CPP14_CONSTEXPR auto flat_map_error(Fn&& fn)
2633  && -> detail::invoke_result_t<Fn, E&&>;
2634  /// \}
2635 
2636  //-------------------------------------------------------------------------
2637  // Private Members
2638  //-------------------------------------------------------------------------
2639  private:
2640 
2641  detail::result_storage<T,E> m_storage;
2642 
2643  //-------------------------------------------------------------------------
2644  // Private Monadic Functions
2645  //-------------------------------------------------------------------------
2646  private:
2647 
2648  /// \{
2649  /// \brief Map implementations for void and non-void functions
2650  ///
2651  /// \param fn the function
2652  template <typename Fn>
2653  constexpr auto map_impl(std::true_type, Fn&& fn) const & -> result<void,E>;
2654  template <typename Fn>
2655  constexpr auto map_impl(std::false_type, Fn&& fn) const & -> result<detail::invoke_result_t<Fn,const T&>,E>;
2656  template <typename Fn>
2657  RESULT_CPP14_CONSTEXPR auto map_impl(std::true_type, Fn&& fn) && -> result<void,E>;
2658  template <typename Fn>
2659  RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn,T&&>,E>;
2660  /// \}
2661  };
2662 
2663  //===========================================================================
2664  // class : result<void,E>
2665  //===========================================================================
2666 
2667  /////////////////////////////////////////////////////////////////////////////
2668  /// \brief Partial specialization of `result<void, E>`
2669  ///
2670  /// \tparam E the underlying error type
2671  /////////////////////////////////////////////////////////////////////////////
2672  template <typename E>
2673  class RESULT_NODISCARD result<void,E>
2674  {
2675  // Type requirements
2676 
2677  static_assert(
2678  !std::is_void<typename std::decay<E>::type>::value,
2679  "It is ill-formed for E to be (possibly CV-qualified) void type"
2680  );
2681  static_assert(
2682  !std::is_abstract<E>::value,
2683  "It is ill-formed for E to be abstract type"
2684  );
2685  static_assert(
2686  !is_failure<typename std::decay<E>::type>::value,
2687  "It is ill-formed for E to be a (possibly CV-qualified) 'failure' type"
2688  );
2689  static_assert(
2690  !std::is_reference<E>::value,
2691  "It is ill-formed for E to be a reference type. "
2692  "Only T types may be lvalue references"
2693  );
2694 
2695  // Friendship
2696 
2697  friend detail::result_error_extractor;
2698 
2699  template <typename T2, typename E2>
2700  friend class result;
2701 
2702  //-------------------------------------------------------------------------
2703  // Public Member Types
2704  //-------------------------------------------------------------------------
2705  public:
2706 
2707  using value_type = void; ///< The value type of this result
2708  using error_type = E; ///< The error type of this result
2709  using failure_type = failure<E>; ///< The failure type
2710 
2711  template <typename U>
2712  using rebind = result<U,E>; ///< Rebinds the result type
2713 
2714  //-------------------------------------------------------------------------
2715  // Constructor / Assignment
2716  //-------------------------------------------------------------------------
2717  public:
2718 
2719  /// \brief Constructs a `result` object in a value state
2720  ///
2721  /// ### Examples
2722  ///
2723  /// Basic Usage:
2724  ///
2725  /// ```cpp
2726  /// auto r = cpp::result<void,int>{};
2727  /// ```
2728  constexpr result() noexcept;
2729 
2730  /// \brief Copy constructs this result
2731  ///
2732  /// If other contains an error, constructs an object that contains a copy
2733  /// of that error.
2734  ///
2735  /// \note This constructor is defined as deleted if
2736  /// `std::is_copy_constructible<E>::value` is `false`
2737  ///
2738  /// \note This constructor is defined as trivial if both
2739  /// `std::is_trivially_copy_constructible<E>::value` are `true`
2740  ///
2741  /// ### Examples
2742  ///
2743  /// Basic Usage:
2744  ///
2745  /// ```cpp
2746  /// const auto r = cpp::result<void,int>{};
2747  /// const auto s = r;
2748  /// ```
2749  ///
2750  /// \param other the result to copy
2751  constexpr result(const result& other) = default;
2752 
2753  /// \brief Move constructs a result
2754  ///
2755  /// If other contains an error, move-constructs this result from that
2756  /// error.
2757  ///
2758  /// \note This constructor is defined as deleted if
2759  /// `std::is_move_constructible<E>::value` is `false`
2760  ///
2761  /// \note This constructor is defined as trivial if both
2762  /// `std::is_trivially_move_constructible<E>::value` are `true`
2763  ///
2764  /// ### Examples
2765  ///
2766  /// Basic Usage:
2767  ///
2768  /// ```cpp
2769  /// auto r = cpp::result<void,std::string>{};
2770  /// auto s = std::move(r);
2771  /// ```
2772  ///
2773  /// \param other the result to move
2774  constexpr result(result&& other) = default;
2775 
2776  /// \brief Converting copy constructor
2777  ///
2778  /// If \p other contains a value, constructs a result object that is not
2779  /// in an error state -- ignoring the value.
2780  ///
2781  /// If \p other contains an error, constructs a result object that
2782  /// contains an error, initialized as if direct-initializing
2783  /// (but not direct-list-initializing) an object of type `E`.
2784  ///
2785  /// \note This constructor does not participate in overload resolution
2786  /// unless the following conditions are met:
2787  /// - `std::is_constructible_v<E, const E2&>` is `true`
2788  ///
2789  /// ### Examples
2790  ///
2791  /// Basic Usage:
2792  ///
2793  /// ```cpp
2794  /// const auto r = cpp::result<int,int>{42};
2795  /// const auto s = cpp::result<void,int>{r};
2796  /// ```
2797  ///
2798  /// \param other the other type to convert
2799  template <typename U, typename E2,
2800  typename = typename std::enable_if<std::is_constructible<E,E2>::value>::type>
2801  explicit result(const result<U,E2>& other)
2802  noexcept(std::is_nothrow_constructible<E,const E2&>::value);
2803 
2804  /// \brief Converting move constructor
2805  ///
2806  /// If \p other contains an error, constructs a result object that
2807  /// contains an error, initialized as if direct-initializing
2808  /// (but not direct-list-initializing) an object of type E&&.
2809  ///
2810  /// \note This constructor does not participate in overload resolution
2811  /// unless the following conditions are met:
2812  /// - `std::is_constructible_v<E, const E2&>` is `true`
2813  ///
2814  /// ### Examples
2815  ///
2816  /// Basic Usage:
2817  ///
2818  /// ```cpp
2819  /// auto r = cpp::result<int,std::string>{42};
2820  /// auto s = cpp::result<void,std::string>{
2821  /// std::move(r)
2822  /// };
2823  /// ```
2824  ///
2825  /// \param other the other type to convert
2826  template <typename U, typename E2,
2827  typename = typename std::enable_if<std::is_constructible<E,E2>::value>::type>
2828  explicit result(result<U,E2>&& other)
2829  noexcept(std::is_nothrow_constructible<E,E2&&>::value);
2830 
2831  //-------------------------------------------------------------------------
2832 
2833  /// \brief Constructs a result object in a value state
2834  ///
2835  /// This constructor exists primarily for symmetry with the `result<T,E>`
2836  /// constructor. Unlike the `T` overload, no variadic arguments may be
2837  /// supplied.
2838  ///
2839  /// ### Examples
2840  ///
2841  /// Basic Usage:
2842  ///
2843  /// ```cpp
2844  /// auto r = cpp::result<void,std::string>{cpp::in_place};
2845  /// ```
2846  constexpr explicit result(in_place_t) noexcept;
2847 
2848  /// \brief Constructs a result object that contains an error
2849  ///
2850  /// the value is initialized as if direct-initializing (but not
2851  /// direct-list-initializing) an object of type `E` from the arguments
2852  /// `std::forward<Args>(args)...`
2853  ///
2854  /// ### Examples
2855  ///
2856  /// Basic Usage:
2857  ///
2858  /// ```cpp
2859  /// auto r = cpp::result<void,std::string>{
2860  /// cpp::in_place_error, "Hello world"
2861  /// };
2862  /// ```
2863  ///
2864  /// \param args the arguments to pass to `E`'s constructor
2865  template <typename...Args,
2866  typename = typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
2867  constexpr explicit result(in_place_error_t, Args&&... args)
2868  noexcept(std::is_nothrow_constructible<E, Args...>::value);
2869 
2870  /// \brief Constructs a result object that contains an error
2871  ///
2872  /// The value is initialized as if direct-initializing (but not
2873  /// direct-list-initializing) an object of type `E` from the arguments
2874  /// `std::forward<std::initializer_list<U>>(ilist)`,
2875  /// `std::forward<Args>(args)...`
2876  ///
2877  /// ### Examples
2878  ///
2879  /// Basic Usage:
2880  ///
2881  /// ```cpp
2882  /// auto r = cpp::result<void,std::string>{
2883  /// cpp::in_place_error, {'H','e','l','l','o'}
2884  /// };
2885  /// ```
2886  ///
2887  /// \param ilist An initializer list of entries to forward
2888  /// \param args the arguments to pass to Es constructor
2889  template <typename U, typename...Args,
2890  typename = typename std::enable_if<std::is_constructible<E, std::initializer_list<U>&, Args...>::value>::type>
2891  constexpr explicit result(in_place_error_t,
2892  std::initializer_list<U> ilist,
2893  Args&&...args)
2895 
2896  //-------------------------------------------------------------------------
2897 
2898  /// \{
2899  /// \brief Constructs the underlying error of this result
2900  ///
2901  /// \note This constructor only participates in overload resolution if
2902  /// `E` is constructible from \p e
2903  ///
2904  /// ### Examples
2905  ///
2906  /// Basic Usage:
2907  ///
2908  /// ```cpp
2909  /// cpp::result<void,int> r = cpp::fail(42);
2910  ///
2911  /// auto get_error_result() -> cpp::result<void,std::string> {
2912  /// return cpp::fail("hello world!");
2913  /// }
2914  /// ```
2915  ///
2916  /// \param e the failure error
2917  template <typename E2,
2918  typename = typename std::enable_if<std::is_constructible<E,const E2&>::value>::type>
2919  constexpr /* implicit */ result(const failure<E2>& e)
2920  noexcept(std::is_nothrow_constructible<E,const E2&>::value);
2921  template <typename E2,
2922  typename = typename std::enable_if<std::is_constructible<E,E2&&>::value>::type>
2923  constexpr /* implicit */ result(failure<E2>&& e)
2924  noexcept(std::is_nothrow_constructible<E,E2&&>::value);
2925  /// \}
2926 
2927  //-------------------------------------------------------------------------
2928 
2929  /// \brief Copy assigns the result stored in \p other
2930  ///
2931  /// \note The function does not participate in overload resolution unless
2932  /// - `std::is_nothrow_copy_constructible_v<E>` is `true`
2933  /// this restriction guarantees that no 'valueless_by_exception` state
2934  /// may occur.
2935  ///
2936  /// \note This assignment operator is defined as trivial if the following
2937  /// conditions are all `true`:
2938  /// - `std::is_trivially_copy_constructible<E>::value`
2939  /// - `std::is_trivially_copy_assignable<E>::value`
2940  /// - `std::is_trivially_destructible<E>::value`
2941  ///
2942  /// \param other the other result to copy
2943  auto operator=(const result& other) -> result& = default;
2944 
2945  /// \brief Move assigns the result stored in \p other
2946  ///
2947  /// \note The function does not participate in overload resolution unless
2948  /// - `std::is_nothrow_copy_constructible_v<E>` is `true`
2949  /// this restriction guarantees that no 'valueless_by_exception` state
2950  /// may occur.
2951  ///
2952  /// \note This assignment operator is defined as trivial if the following
2953  /// conditions are all `true`:
2954  /// - `std::is_trivially_move_constructible<E>::value`
2955  /// - `std::is_trivially_move_assignable<E>::value`
2956  /// - `std::is_trivially_destructible<E>::value`
2957  ///
2958  /// \param other the other result to copy
2959  auto operator=(result&& other) -> result& = default;
2960 
2961  /// \brief Copy-converts the state of \p other
2962  ///
2963  /// If both this and \p other contain an error, the underlying error is
2964  /// assigned through copy-assignment.
2965  ///
2966  /// If \p other contains a value state, this result is constructed in a
2967  /// value state.
2968  ///
2969  /// If \p other contans an error state, and this contains a value state,
2970  /// the underlying error is constructed through copy-construction.
2971  ///
2972  /// \note The function does not participate in overload resolution unless
2973  /// - `std::is_nothrow_constructible_v<E, const E2&>`,
2974  /// `std::is_assignable_v<E&, const E2&>` are all `true`.
2975  ///
2976  /// \param other the other result object to convert
2977  /// \return reference to `(*this)`
2978  template <typename E2,
2979  typename = typename std::enable_if<std::is_nothrow_constructible<E,const E2&>::value &&
2980  std::is_assignable<E&,const E2&>::value>::type>
2981  auto operator=(const result<void,E2>& other)
2982  noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> result&;
2983 
2984  /// \brief Move-converts the state of \p other
2985  ///
2986  /// If both this and \p other contain an error, the underlying error is
2987  /// assigned through move-assignment.
2988  ///
2989  /// If \p other contains a value state, this result is constructed in a
2990  /// value state.
2991  ///
2992  /// If \p other contans an error state, and this contains a value state,
2993  /// the underlying error is constructed through move-construction.
2994  ///
2995  /// \note The function does not participate in overload resolution unless
2996  /// - `std::is_nothrow_constructible_v<E, E2&&>`,
2997  /// `std::is_assignable_v<E&, E2&&>` are all `true`.
2998  ///
2999  /// \param other the other result object to convert
3000  /// \return reference to `(*this)`
3001  template <typename E2,
3002  typename = typename std::enable_if<std::is_nothrow_constructible<E,E2&&>::value &&
3003  std::is_assignable<E&,E2&&>::value>::type>
3004  auto operator=(result<void,E2>&& other)
3005  noexcept(std::is_nothrow_assignable<E, E2&&>::value) -> result&;
3006 
3007  /// \{
3008  /// \brief Perfect-forwarded assignment
3009  ///
3010  /// Depending on whether `*this` contains an error before the call, the
3011  /// contained error is either direct-initialized via forwarding the error,
3012  /// or assigned from forwarding the error
3013  ///
3014  /// \note The function does not participate in overload resolution unless
3015  /// - `std::is_nothrow_constructible_v<E, E2>` is `true`, and
3016  /// - `std::is_assignable_v<E&, E2>` is `true`
3017  ///
3018  /// \param other the failure value to assign to this
3019  /// \return reference to `(*this)`
3020  template <typename E2,
3021  typename = typename std::enable_if<detail::result_is_failure_assignable<E,const E2&>::value>::type>
3022  auto operator=(const failure<E2>& other)
3023  noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> result&;
3024  template <typename E2,
3025  typename = typename std::enable_if<detail::result_is_failure_assignable<E,E2&&>::value>::type>
3026  auto operator=(failure<E2>&& other)
3027  noexcept(std::is_nothrow_assignable<E, E2&&>::value) -> result&;
3028  /// \}
3029 
3030  //-------------------------------------------------------------------------
3031  // Observers
3032  //-------------------------------------------------------------------------
3033  public:
3034 
3035 
3036  /// \brief Contextually convertible to `true` if `*this` does not contain
3037  /// an error
3038  ///
3039  /// This function exists to allow for simple, terse checks for containing
3040  /// a value.
3041  ///
3042  /// ### Examples
3043  ///
3044  /// Basic Usage:
3045  ///
3046  /// ```cpp
3047  /// auto get_result() -> cpp::result<void, int>;
3048  /// auto r = get_result();
3049  /// if (r) { ... }
3050  ///
3051  /// assert(static_cast<bool>(cpp::result<void,int>{}));
3052  ///
3053  /// assert(!static_cast<bool>(cpp::result<void,int>{cpp::fail(42)}));
3054  /// ```
3055  ///
3056  /// \return `true` if `*this` contains a value, `false` if `*this`
3057  /// does not contain a value
3059  constexpr explicit operator bool() const noexcept;
3060 
3061  /// \copydoc result<T,E>::has_value
3063  constexpr auto has_value() const noexcept -> bool;
3064 
3065  /// \copydoc result<T,E>::has_error
3067  constexpr auto has_error() const noexcept -> bool;
3068 
3069  //-------------------------------------------------------------------------
3070 
3071  /// \{
3072  /// \brief Throws an exception if `(*this)` is in an error state
3073  ///
3074  /// This function exists for symmetry with `cpp::result<T,E>` objects where
3075  /// `T` contains a value.
3076  ///
3077  /// If this contains an error, an exception is thrown containing the
3078  /// underlying error. The error is consumed propagating the same constness
3079  /// and refness of this result.
3080  ///
3081  /// ### Examples
3082  ///
3083  /// Basic Usage:
3084  ///
3085  /// ```cpp
3086  /// cpp::result<void,int>{}.value(); // no exception
3087  ///
3088  /// auto r = cpp::result<void,std::unique_ptr<int>>{
3089  /// cpp::fail(std::make_unique<int>(42))
3090  /// };
3091  /// std::move(r).value(); // throws bad_result_access<std::unique_ptr<int>>
3092  ///
3093  /// try {
3094  /// auto r = cpp::result<void,int>{ cpp::fail(42) }.value();
3095  /// } catch (const cpp::bad_result_access<int>& e) {
3096  /// assert(e.error() == 42);
3097  /// }
3098  /// ```
3099  ///
3100  /// \throws bad_result_access<E> if `*this` does not contain a value.
3101  RESULT_CPP14_CONSTEXPR auto value() && -> void;
3102  RESULT_CPP14_CONSTEXPR auto value() const & -> void;
3103  /// \}
3104 
3105  /// \{
3106  /// \copydoc result<T,E>::error
3108  constexpr auto error() const &
3109  noexcept(std::is_nothrow_constructible<E>::value &&
3112  RESULT_CPP14_CONSTEXPR auto error() &&
3113  noexcept(std::is_nothrow_constructible<E>::value &&
3115  /// \}
3116 
3117  /// \{
3118  /// \copydoc result<T,E>::expect
3119  template <typename String,
3120  typename = typename std::enable_if<(
3121  std::is_convertible<String,const std::string&>::value &&
3122  std::is_copy_constructible<E>::value
3123  )>::type>
3124  RESULT_CPP14_CONSTEXPR auto expect(String&& message) const & -> void;
3125  template <typename String,
3126  typename = typename std::enable_if<(
3127  std::is_convertible<String,const std::string&>::value &&
3128  std::is_move_constructible<E>::value
3129  )>::type>
3130  RESULT_CPP14_CONSTEXPR auto expect(String&& message) && -> void;
3131  /// \}
3132 
3133  //-------------------------------------------------------------------------
3134  // Monadic Functionalities
3135  //-------------------------------------------------------------------------
3136  public:
3137 
3138  /// \{
3139  /// \copydoc result<T,E>::error_or
3140  template <typename U>
3142  constexpr auto error_or(U&& default_error) const & -> error_type;
3143  template <typename U>
3145  RESULT_CPP14_CONSTEXPR auto error_or(U&& default_error) && -> error_type;
3146  /// \}
3147 
3148  //-------------------------------------------------------------------------
3149 
3150  /// \copydoc result<T,E>::and_then
3151  template <typename U>
3153  constexpr auto and_then(U&& value) const -> result<typename std::decay<U>::type,E>;
3154 
3155  /// \{
3156  /// \brief Invokes the function \p fn if `(*this)` contains no value
3157  ///
3158  /// If this result contains an error, a result of the error is returned
3159  ///
3160  /// The function being called must return a `result` type or the program
3161  /// is ill-formed
3162  ///
3163  /// If this is called on an rvalue of `result` which contains an error,
3164  /// the returned `result` is constructed from an rvalue of that error.
3165  ///
3166  /// ### Examples
3167  ///
3168  /// Basic Usage:
3169  ///
3170  /// ```cpp
3171  /// auto generate_int() -> cpp::result<int,int> { return 42; }
3172  /// auto r = cpp::result<void,int>{};
3173  /// assert(r.flat_map(generate_int) == 42);
3174  ///
3175  /// auto r = cpp::result<void,int>{cpp::fail(42)};
3176  /// assert(r.flat_map(generate_int) == cpp::fail(42));
3177  /// ```
3178  ///
3179  /// \param fn the function to invoke with this
3180  /// \return The result of the function being called
3181  template <typename Fn>
3183  constexpr auto flat_map(Fn&& fn) const & -> detail::invoke_result_t<Fn>;
3184  template <typename Fn>
3186  RESULT_CPP14_CONSTEXPR auto flat_map(Fn&& fn) && -> detail::invoke_result_t<Fn>;
3187  /// \}
3188 
3189  /// \{
3190  /// \brief Invokes the function \p fn if `(*this)` contains no value
3191  ///
3192  /// If this result is an error, the result of this function is that
3193  /// error. Otherwise this function wraps the result and returns it as an
3194  /// result.
3195  ///
3196  /// If this is called on an rvalue of `result` which contains an error,
3197  /// the returned `result` is constructed from an rvalue of that error.
3198  ///
3199  /// ### Examples
3200  ///
3201  /// Basic Usage:
3202  ///
3203  /// ```cpp
3204  /// auto generate_int() -> int { return 42; }
3205  /// auto r = cpp::result<void,int>{};
3206  /// assert(r.map(generate_int) == 42);
3207  ///
3208  /// auto r = cpp::result<void,int>{cpp::fail(42)};
3209  /// assert(r.map(generate_int) == cpp::fail(42));
3210  /// ```
3211  ///
3212  /// \param fn the function to invoke with this
3213  /// \return The result result of the function invoked
3214  template <typename Fn>
3216  constexpr auto map(Fn&& fn) const & -> result<detail::invoke_result_t<Fn>,E>;
3217  template <typename Fn>
3219  RESULT_CPP14_CONSTEXPR auto map(Fn&& fn) && -> result<detail::invoke_result_t<Fn>,E>;
3220  /// \}
3221 
3222  /// \{
3223  /// \copydoc result<T,E>::map_error
3224  template <typename Fn>
3225  constexpr auto map_error(Fn&& fn) const & -> result<void, detail::invoke_result_t<Fn,const E&>>;
3226  template <typename Fn>
3228  auto map_error(Fn&& fn) && -> result<void, detail::invoke_result_t<Fn,E&&>>;
3229  /// \}
3230 
3231 
3232  /// \{
3233  /// \copydoc result<T,E>::flat_map_error
3234  template <typename Fn>
3236  constexpr auto flat_map_error(Fn&& fn) const & -> detail::invoke_result_t<Fn, const E&>;
3237  template <typename Fn>
3239  RESULT_CPP14_CONSTEXPR auto flat_map_error(Fn&& fn) && -> detail::invoke_result_t<Fn, E&&>;
3240  /// \}
3241 
3242  //-------------------------------------------------------------------------
3243  // Private Members
3244  //-------------------------------------------------------------------------
3245  private:
3246 
3247  detail::result_storage<detail::unit,E> m_storage;
3248 
3249  //-------------------------------------------------------------------------
3250  // Private Monadic Functions
3251  //-------------------------------------------------------------------------
3252  private:
3253 
3254  /// \{
3255  /// \brief Map implementations for void and non-void functions
3256  ///
3257  /// \param fn the function
3258  template <typename Fn>
3259  constexpr auto map_impl(std::true_type, Fn&& fn) const & -> result<void,E>;
3260  template <typename Fn>
3261  constexpr auto map_impl(std::false_type, Fn&& fn) const & -> result<detail::invoke_result_t<Fn>,E>;
3262  template <typename Fn>
3263  RESULT_CPP14_CONSTEXPR auto map_impl(std::true_type, Fn&& fn) && -> result<void,E>;
3264  template <typename Fn>
3265  RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn>,E>;
3266  /// \}
3267  };
3268 
3269  //===========================================================================
3270  // non-member functions : class : result
3271  //===========================================================================
3272 
3273  //---------------------------------------------------------------------------
3274  // Comparison
3275  //---------------------------------------------------------------------------
3276 
3277  template <typename T1, typename E1, typename T2, typename E2>
3278  constexpr auto operator==(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3279  noexcept -> bool;
3280  template <typename T1, typename E1, typename T2, typename E2>
3281  constexpr auto operator!=(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3282  noexcept -> bool;
3283  template <typename T1, typename E1, typename T2, typename E2>
3284  constexpr auto operator>=(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3285  noexcept -> bool;
3286  template <typename T1, typename E1, typename T2, typename E2>
3287  constexpr auto operator<=(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3288  noexcept -> bool;
3289  template <typename T1, typename E1, typename T2, typename E2>
3290  constexpr auto operator>(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3291  noexcept -> bool;
3292  template <typename T1, typename E1, typename T2, typename E2>
3293  constexpr auto operator<(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3294  noexcept -> bool;
3295 
3296  //---------------------------------------------------------------------------
3297 
3298  template <typename E1, typename E2>
3299  constexpr auto operator==(const result<void,E1>& lhs, const result<void,E2>& rhs)
3300  noexcept -> bool;
3301  template <typename E1, typename E2>
3302  constexpr auto operator!=(const result<void,E1>& lhs, const result<void,E2>& rhs)
3303  noexcept -> bool;
3304  template <typename E1, typename E2>
3305  constexpr auto operator>=(const result<void,E1>& lhs, const result<void,E2>& rhs)
3306  noexcept -> bool;
3307  template <typename E1, typename E2>
3308  constexpr auto operator<=(const result<void,E1>& lhs, const result<void,E2>& rhs)
3309  noexcept -> bool;
3310  template <typename E1, typename E2>
3311  constexpr auto operator>(const result<void,E1>& lhs, const result<void,E2>& rhs)
3312  noexcept -> bool;
3313  template <typename E1, typename E2>
3314  constexpr auto operator<(const result<void,E1>& lhs, const result<void,E2>& rhs)
3315  noexcept -> bool;
3316 
3317  //---------------------------------------------------------------------------
3318 
3319  template <typename T, typename E, typename U,
3320  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3321  constexpr auto operator==(const result<T,E>& exp, const U& value)
3322  noexcept -> bool;
3323  template <typename T, typename U, typename E,
3324  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3325  constexpr auto operator==(const T& value, const result<U,E>& exp)
3326  noexcept -> bool;
3327  template <typename T, typename E, typename U,
3328  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3329  constexpr auto operator!=(const result<T,E>& exp, const U& value)
3330  noexcept -> bool;
3331  template <typename T, typename U, typename E,
3332  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3333  constexpr auto operator!=(const T& value, const result<U,E>& exp)
3334  noexcept -> bool;
3335  template <typename T, typename E, typename U,
3336  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3337  constexpr auto operator<=(const result<T,E>& exp, const U& value)
3338  noexcept -> bool;
3339  template <typename T, typename U, typename E,
3340  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3341  constexpr auto operator<=(const T& value, const result<U,E>& exp)
3342  noexcept -> bool;
3343  template <typename T, typename E, typename U,
3344  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3345  constexpr auto operator>=(const result<T,E>& exp, const U& value)
3346  noexcept -> bool;
3347  template <typename T, typename U, typename E,
3348  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3349  constexpr auto operator>=(const T& value, const result<U,E>& exp)
3350  noexcept -> bool;
3351  template <typename T, typename E, typename U,
3352  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3353  constexpr auto operator<(const result<T,E>& exp, const U& value)
3354  noexcept -> bool;
3355  template <typename T, typename U, typename E,
3356  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3357  constexpr auto operator<(const T& value, const result<U,E>& exp)
3358  noexcept -> bool;
3359  template <typename T, typename E, typename U,
3360  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3361  constexpr auto operator>(const result<T,E>& exp, const U& value)
3362  noexcept -> bool;
3363  template <typename T, typename U, typename E,
3364  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3365  constexpr auto operator>(const T& value, const result<U,E>& exp)
3366  noexcept -> bool;
3367 
3368  //---------------------------------------------------------------------------
3369 
3370  template <typename T, typename E, typename U>
3371  constexpr auto operator==(const result<T,E>& exp, const failure<U>& value)
3372  noexcept -> bool;
3373  template <typename T, typename U, typename E>
3374  constexpr auto operator==(const failure<T>& value, const result<E,U>& exp)
3375  noexcept -> bool;
3376  template <typename T, typename E, typename U>
3377  constexpr auto operator!=(const result<T,E>& exp, const failure<U>& value)
3378  noexcept -> bool;
3379  template <typename T, typename U, typename E>
3380  constexpr auto operator!=(const failure<T>& value, const result<E,U>& exp)
3381  noexcept -> bool;
3382  template <typename T, typename E, typename U>
3383  constexpr auto operator<=(const result<T,E>& exp, const failure<U>& value)
3384  noexcept -> bool;
3385  template <typename T, typename U, typename E>
3386  constexpr auto operator<=(const failure<T>& value, const result<E,U>& exp)
3387  noexcept -> bool;
3388  template <typename T, typename E, typename U>
3389  constexpr auto operator>=(const result<T,E>& exp, const failure<U>& value)
3390  noexcept -> bool;
3391  template <typename T, typename U, typename E>
3392  constexpr auto operator>=(const failure<T>& value, const result<E,U>& exp)
3393  noexcept -> bool;
3394  template <typename T, typename E, typename U>
3395  constexpr auto operator<(const result<T,E>& exp, const failure<U>& value)
3396  noexcept -> bool;
3397  template <typename T, typename U, typename E>
3398  constexpr auto operator<(const failure<T>& value, const result<E,U>& exp)
3399  noexcept -> bool;
3400  template <typename T, typename E, typename U>
3401  constexpr auto operator>(const result<T,E>& exp, const failure<U>& value)
3402  noexcept -> bool;
3403  template <typename T, typename U, typename E>
3404  constexpr auto operator>(const failure<T>& value, const result<E,U>& exp)
3405  noexcept -> bool;
3406 
3407  //---------------------------------------------------------------------------
3408  // Utilities
3409  //---------------------------------------------------------------------------
3410 
3411  /// \{
3412  /// \brief Swaps the contents of \p lhs with \p rhs
3413  ///
3414  /// \param lhs the left result
3415  /// \param rhs the right result
3416  template <typename T, typename E>
3417  auto swap(result<T,E>& lhs, result<T,E>& rhs)
3418 #if __cplusplus >= 201703L
3423 #else
3426 #endif
3427  -> void;
3428  template <typename E>
3429  auto swap(result<void,E>& lhs, result<void,E>& rhs)
3430 #if __cplusplus >= 201703L
3431  noexcept(std::is_nothrow_move_constructible<result<void,E>>::value &&
3434 #else
3435  noexcept(std::is_nothrow_move_constructible<result<void,E>>::value &&
3437 #endif
3438  -> void;
3439  /// \}
3440 
3441 } // inline namespace bitwizeshift
3442 } // namespace EXPECTED_NAMESPACE
3443 
3444 namespace std {
3445 
3446  template <typename T, typename E>
3447  struct hash<::RESULT_NS_IMPL::result<T,E>>
3448  {
3449  auto operator()(const RESULT_NS_IMPL::result<T,E>& x) const -> std::size_t
3450  {
3451  if (x.has_value()) {
3452  return std::hash<T>{}(*x) + 1; // add '1' to differentiate from error case
3453  }
3454  return std::hash<E>{}(::RESULT_NS_IMPL::detail::extract_error(x));
3455  }
3456  };
3457 
3458  template <typename E>
3459  struct hash<::RESULT_NS_IMPL::result<void,E>>
3460  {
3461  auto operator()(const RESULT_NS_IMPL::result<void,E>& x) const -> std::size_t
3462  {
3463  if (x.has_value()) {
3464  return 0;
3465  }
3466  return std::hash<E>{}(::RESULT_NS_IMPL::detail::extract_error(x));
3467  }
3468  };
3469 
3470 } // namespace std
3471 
3472 #if !defined(RESULT_DISABLE_EXCEPTIONS)
3473 
3474 //=============================================================================
3475 // class : bad_result_access
3476 //=============================================================================
3477 
3478 //-----------------------------------------------------------------------------
3479 // Constructors
3480 //-----------------------------------------------------------------------------
3481 
3482 template <typename E>
3483 template <typename E2, typename>
3485 RESULT_NS_IMPL::bad_result_access<E>::bad_result_access(E2&& error)
3486  : logic_error{"error attempting to access value from result containing error"},
3487  m_error(detail::forward<E2>(error))
3488 {
3489 
3490 }
3491 
3492 template <typename E>
3493 template <typename E2, typename>
3495 RESULT_NS_IMPL::bad_result_access<E>::bad_result_access(
3496  const char* what_arg,
3497  E2&& error
3498 ) : logic_error{what_arg},
3499  m_error(detail::forward<E2>(error))
3500 {
3501 
3502 }
3503 
3504 template <typename E>
3505 template <typename E2, typename>
3507 RESULT_NS_IMPL::bad_result_access<E>::bad_result_access(
3508  const std::string& what_arg,
3509  E2&& error
3510 ) : logic_error{what_arg},
3511  m_error(detail::forward<E2>(error))
3512 {
3513 
3514 }
3515 
3516 //-----------------------------------------------------------------------------
3517 // Observers
3518 //-----------------------------------------------------------------------------
3519 
3520 template <typename E>
3522 auto RESULT_NS_IMPL::bad_result_access<E>::error()
3523  & noexcept -> E&
3524 {
3525  return m_error;
3526 }
3527 
3528 template <typename E>
3530 auto RESULT_NS_IMPL::bad_result_access<E>::error()
3531  && noexcept -> E&&
3532 {
3533  return static_cast<E&&>(m_error);
3534 }
3535 
3536 template <typename E>
3538 auto RESULT_NS_IMPL::bad_result_access<E>::error()
3539  const & noexcept -> const E&
3540 {
3541  return m_error;
3542 }
3543 
3544 template <typename E>
3546 auto RESULT_NS_IMPL::bad_result_access<E>::error()
3547  const && noexcept -> const E&&
3548 {
3549  return static_cast<const E&&>(m_error);
3550 }
3551 
3552 #endif
3553 
3554 //=============================================================================
3555 // class : failure
3556 //=============================================================================
3557 
3558 //-----------------------------------------------------------------------------
3559 // Constructors
3560 //-----------------------------------------------------------------------------
3561 
3562 template <typename E>
3563 template <typename...Args, typename>
3564 inline RESULT_INLINE_VISIBILITY constexpr
3565 RESULT_NS_IMPL::failure<E>::failure(in_place_t, Args&&...args)
3566  noexcept(std::is_nothrow_constructible<E, Args...>::value)
3567  : m_failure(detail::forward<Args>(args)...)
3568 {
3569 
3570 }
3571 
3572 template <typename E>
3573 template <typename U, typename...Args, typename>
3574 inline RESULT_INLINE_VISIBILITY constexpr
3575 RESULT_NS_IMPL::failure<E>::failure(
3576  in_place_t,
3577  std::initializer_list<U> ilist,
3578  Args&&...args
3580  : m_failure(ilist, detail::forward<Args>(args)...)
3581 {
3582 
3583 }
3584 
3585 template <typename E>
3586 template <typename E2,
3587  typename std::enable_if<RESULT_NS_IMPL::detail::failure_is_explicit_value_convertible<E,E2>::value,int>::type>
3588 inline RESULT_INLINE_VISIBILITY constexpr
3589 RESULT_NS_IMPL::failure<E>::failure(E2&& error)
3590  noexcept(std::is_nothrow_constructible<E,E2>::value)
3591  : m_failure(detail::forward<E2>(error))
3592 {
3593 
3594 }
3595 
3596 template <typename E>
3597 template <typename E2,
3598  typename std::enable_if<RESULT_NS_IMPL::detail::failure_is_implicit_value_convertible<E,E2>::value,int>::type>
3599 inline RESULT_INLINE_VISIBILITY constexpr
3600 RESULT_NS_IMPL::failure<E>::failure(E2&& error)
3601  noexcept(std::is_nothrow_constructible<E,E2>::value)
3602  : m_failure(detail::forward<E2>(error))
3603 {
3604 
3605 }
3606 
3607 template <typename E>
3608 template <typename E2, typename>
3609 inline RESULT_INLINE_VISIBILITY constexpr
3610 RESULT_NS_IMPL::failure<E>::failure(const failure<E2>& other)
3611  noexcept(std::is_nothrow_constructible<E,const E2&>::value)
3612  : m_failure(other.error())
3613 {
3614 
3615 }
3616 
3617 template <typename E>
3618 template <typename E2, typename>
3619 inline RESULT_INLINE_VISIBILITY constexpr
3620 RESULT_NS_IMPL::failure<E>::failure(failure<E2>&& other)
3621  noexcept(std::is_nothrow_constructible<E,E2&&>::value)
3622  : m_failure(static_cast<failure<E2>&&>(other).error())
3623 {
3624 
3625 }
3626 
3627 //-----------------------------------------------------------------------------
3628 
3629 template <typename E>
3630 template <typename E2, typename>
3632 auto RESULT_NS_IMPL::failure<E>::operator=(E2&& error)
3633  noexcept(
3636  ) -> failure&
3637 {
3638  m_failure = detail::forward<E2>(error);
3639 
3640  return (*this);
3641 }
3642 
3643 template <typename E>
3644 template <typename E2, typename>
3646 auto RESULT_NS_IMPL::failure<E>::operator=(const failure<E2>& other)
3647  noexcept(std::is_nothrow_assignable<E,const E2&>::value)
3648  -> failure&
3649 {
3650  m_failure = other.error();
3651 
3652  return (*this);
3653 }
3654 
3655 template <typename E>
3656 template <typename E2, typename>
3658 auto RESULT_NS_IMPL::failure<E>::operator=(failure<E2>&& other)
3659  noexcept(std::is_nothrow_assignable<E,E2&&>::value)
3660  -> failure&
3661 {
3662  m_failure = static_cast<failure<E2>&&>(other).error();
3663 
3664  return (*this);
3665 }
3666 
3667 //-----------------------------------------------------------------------------
3668 // Observers
3669 //-----------------------------------------------------------------------------
3670 
3671 template <typename E>
3673 auto RESULT_NS_IMPL::failure<E>::error()
3674  & noexcept -> typename std::add_lvalue_reference<E>::type
3675 {
3676  return m_failure;
3677 }
3678 
3679 template <typename E>
3681 auto RESULT_NS_IMPL::failure<E>::error()
3682  && noexcept -> typename std::add_rvalue_reference<E>::type
3683 {
3684  using reference = typename std::add_rvalue_reference<E>::type;
3685 
3686  return static_cast<reference>(m_failure);
3687 }
3688 
3689 template <typename E>
3690 inline RESULT_INLINE_VISIBILITY constexpr
3691 auto RESULT_NS_IMPL::failure<E>::error()
3692  const & noexcept
3693  -> typename std::add_lvalue_reference<typename std::add_const<E>::type>::type
3694 {
3695  return m_failure;
3696 }
3697 
3698 template <typename E>
3699 inline RESULT_INLINE_VISIBILITY constexpr
3700 auto RESULT_NS_IMPL::failure<E>::error()
3701  const && noexcept
3702  -> typename std::add_rvalue_reference<typename std::add_const<E>::type>::type
3703 {
3704  using reference = typename std::add_rvalue_reference<typename std::add_const<E>::type>::type;
3705 
3706  return static_cast<reference>(m_failure);
3707 }
3708 
3709 //=============================================================================
3710 // non-member functions : class : failure
3711 //=============================================================================
3712 
3713 //-----------------------------------------------------------------------------
3714 // Comparison
3715 //-----------------------------------------------------------------------------
3716 
3717 template <typename E1, typename E2>
3718 inline RESULT_INLINE_VISIBILITY constexpr
3719 auto RESULT_NS_IMPL::operator==(const failure<E1>& lhs, const failure<E2>& rhs)
3720  noexcept -> bool
3721 {
3722  return lhs.error() == rhs.error();
3723 }
3724 
3725 template <typename E1, typename E2>
3726 inline RESULT_INLINE_VISIBILITY constexpr
3727 auto RESULT_NS_IMPL::operator!=(const failure<E1>& lhs, const failure<E2>& rhs)
3728  noexcept -> bool
3729 {
3730  return lhs.error() != rhs.error();
3731 }
3732 
3733 template <typename E1, typename E2>
3734 inline RESULT_INLINE_VISIBILITY constexpr
3735 auto RESULT_NS_IMPL::operator<(const failure<E1>& lhs, const failure<E2>& rhs)
3736  noexcept -> bool
3737 {
3738  return lhs.error() < rhs.error();
3739 }
3740 
3741 template <typename E1, typename E2>
3742 inline RESULT_INLINE_VISIBILITY constexpr
3743 auto RESULT_NS_IMPL::operator>(const failure<E1>& lhs, const failure<E2>& rhs)
3744  noexcept -> bool
3745 {
3746  return lhs.error() > rhs.error();
3747 }
3748 
3749 template <typename E1, typename E2>
3750 inline RESULT_INLINE_VISIBILITY constexpr
3751 auto RESULT_NS_IMPL::operator<=(const failure<E1>& lhs, const failure<E2>& rhs)
3752  noexcept -> bool
3753 {
3754  return lhs.error() <= rhs.error();
3755 }
3756 
3757 template <typename E1, typename E2>
3758 inline RESULT_INLINE_VISIBILITY constexpr
3759 auto RESULT_NS_IMPL::operator>=(const failure<E1>& lhs, const failure<E2>& rhs)
3760  noexcept -> bool
3761 {
3762  return lhs.error() >= rhs.error();
3763 }
3764 
3765 //-----------------------------------------------------------------------------
3766 // Utilities
3767 //-----------------------------------------------------------------------------
3768 
3769 template <typename E>
3770 inline RESULT_INLINE_VISIBILITY constexpr
3771 auto RESULT_NS_IMPL::fail(E&& e)
3772  noexcept(std::is_nothrow_constructible<typename std::decay<E>::type,E>::value)
3773  -> failure<typename std::decay<E>::type>
3774 {
3775  using result_type = failure<typename std::decay<E>::type>;
3776 
3777  return result_type(
3778  detail::forward<E>(e)
3779  );
3780 }
3781 
3782 template <typename E>
3783 inline RESULT_INLINE_VISIBILITY constexpr
3784 auto RESULT_NS_IMPL::fail(std::reference_wrapper<E> e)
3785  noexcept -> failure<E&>
3786 {
3787  using result_type = failure<E&>;
3788 
3789  return result_type{e.get()};
3790 }
3791 
3792 template <typename E, typename...Args, typename>
3793 inline RESULT_INLINE_VISIBILITY constexpr
3794 auto RESULT_NS_IMPL::fail(Args&&...args)
3795  noexcept(std::is_nothrow_constructible<E, Args...>::value)
3796  -> failure<E>
3797 {
3798  return failure<E>(in_place, detail::forward<Args>(args)...);
3799 }
3800 
3801 template <typename E, typename U, typename...Args, typename>
3802 inline RESULT_INLINE_VISIBILITY constexpr
3803 auto RESULT_NS_IMPL::fail(std::initializer_list<U> ilist, Args&&...args)
3805  -> failure<E>
3806 {
3807  return failure<E>(in_place, ilist, detail::forward<Args>(args)...);
3808 }
3809 
3810 template <typename E>
3812 auto RESULT_NS_IMPL::swap(failure<E>& lhs, failure<E>& rhs)
3813 #if __cplusplus >= 201703L
3814  noexcept(std::is_nothrow_swappable<E>::value) -> void
3815 #else
3817  -> void
3818 #endif
3819 {
3820  using std::swap;
3821 
3822  swap(lhs.error(), rhs.error());
3823 }
3824 
3825 //=============================================================================
3826 // class : detail::result_union<T, E, IsTrivial>
3827 //=============================================================================
3828 
3829 //-----------------------------------------------------------------------------
3830 // Constructors / Assignment
3831 //-----------------------------------------------------------------------------
3832 
3833 template <typename T, typename E, bool IsTrivial>
3835 RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>
3836  ::result_union(unit)
3837  noexcept
3838  : m_empty{}
3839 {
3840  // m_has_value intentionally not set
3841 }
3842 
3843 template <typename T, typename E, bool IsTrivial>
3844 template <typename...Args>
3845 inline RESULT_INLINE_VISIBILITY constexpr
3846 RESULT_NS_IMPL::detail::result_union<T,E,IsTrivial>
3847  ::result_union(in_place_t, Args&&...args)
3848  noexcept(std::is_nothrow_constructible<T, Args...>::value)
3849  : m_value(detail::forward<Args>(args)...),
3850  m_has_value{true}
3851 {
3852 }
3853 
3854 template <typename T, typename E, bool IsTrivial>
3855 template <typename...Args>
3856 inline RESULT_INLINE_VISIBILITY constexpr
3857 RESULT_NS_IMPL::detail::result_union<T,E,IsTrivial>
3858  ::result_union(in_place_error_t, Args&&...args)
3859  noexcept(std::is_nothrow_constructible<E, Args...>::value)
3860  : m_error(detail::forward<Args>(args)...),
3861  m_has_value{false}
3862 {
3863 }
3864 
3865 //-----------------------------------------------------------------------------
3866 // Modifiers
3867 //-----------------------------------------------------------------------------
3868 
3869 template <typename T, typename E, bool IsTrivial>
3871 auto RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>::destroy()
3872  const noexcept -> void
3873 {
3874  // do nothing
3875 }
3876 
3877 //=============================================================================
3878 // class : detail::result_union<T, E, false>
3879 //=============================================================================
3880 
3881 //-----------------------------------------------------------------------------
3882 // Constructors / Destructor / Assignment
3883 //-----------------------------------------------------------------------------
3884 
3885 template <typename T, typename E>
3887 RESULT_NS_IMPL::detail::result_union<T, E, false>
3888  ::result_union(unit)
3889  noexcept
3890  : m_empty{}
3891 {
3892  // m_has_value intentionally not set
3893 }
3894 
3895 template <typename T, typename E>
3896 template <typename...Args>
3897 inline RESULT_INLINE_VISIBILITY constexpr
3898 RESULT_NS_IMPL::detail::result_union<T,E,false>
3899  ::result_union(in_place_t, Args&&...args)
3900  noexcept(std::is_nothrow_constructible<T, Args...>::value)
3901  : m_value(detail::forward<Args>(args)...),
3902  m_has_value{true}
3903 {
3904 }
3905 
3906 template <typename T, typename E>
3907 template <typename...Args>
3908 inline RESULT_INLINE_VISIBILITY constexpr
3909 RESULT_NS_IMPL::detail::result_union<T,E,false>
3910  ::result_union(in_place_error_t, Args&&...args)
3911  noexcept(std::is_nothrow_constructible<E, Args...>::value)
3912  : m_error(detail::forward<Args>(args)...),
3913  m_has_value{false}
3914 {
3915 }
3916 
3917 //-----------------------------------------------------------------------------
3918 
3919 template <typename T, typename E>
3921 RESULT_NS_IMPL::detail::result_union<T,E,false>
3922  ::~result_union()
3923  noexcept(std::is_nothrow_destructible<T>::value && std::is_nothrow_destructible<E>::value)
3924 {
3925  destroy();
3926 }
3927 
3928 //-----------------------------------------------------------------------------
3929 // Modifiers
3930 //-----------------------------------------------------------------------------
3931 
3932 template <typename T, typename E>
3934 auto RESULT_NS_IMPL::detail::result_union<T, E, false>::destroy()
3935  -> void
3936 {
3937  if (m_has_value) {
3938  m_value.~underlying_value_type();
3939  } else {
3940  m_error.~underlying_error_type();
3941  }
3942 }
3943 
3944 //=============================================================================
3945 // class : result_construct_base<T, E>
3946 //=============================================================================
3947 
3948 //-----------------------------------------------------------------------------
3949 // Constructors / Assignment
3950 //-----------------------------------------------------------------------------
3951 
3952 template <typename T, typename E>
3954 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(unit)
3955  noexcept
3956  : storage{unit{}}
3957 {
3958 }
3959 
3960 template <typename T, typename E>
3961 template <typename...Args>
3962 inline constexpr RESULT_INLINE_VISIBILITY
3963 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(
3964  in_place_t,
3965  Args&&...args
3966 ) noexcept(std::is_nothrow_constructible<T, Args...>::value)
3967  : storage{in_place, detail::forward<Args>(args)...}
3968 {
3969 }
3970 
3971 template <typename T, typename E>
3972 template <typename...Args>
3973 inline constexpr RESULT_INLINE_VISIBILITY
3974 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(
3976  Args&&...args
3977 ) noexcept(std::is_nothrow_constructible<E, Args...>::value)
3978  : storage(in_place_error, detail::forward<Args>(args)...)
3979 {
3980 }
3981 
3982 //-----------------------------------------------------------------------------
3983 // Construction / Assignment
3984 //-----------------------------------------------------------------------------
3985 
3986 template <typename T, typename E>
3987 template <typename...Args>
3989 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value(Args&&...args)
3990  noexcept(std::is_nothrow_constructible<T,Args...>::value)
3991  -> void
3992 {
3993  using value_type = typename storage_type::underlying_value_type;
3994 
3995  auto* p = static_cast<void*>(std::addressof(storage.m_value));
3996  new (p) value_type(detail::forward<Args>(args)...);
3997  storage.m_has_value = true;
3998 }
3999 
4000 template <typename T, typename E>
4001 template <typename...Args>
4003 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_error(Args&&...args)
4004  noexcept(std::is_nothrow_constructible<E,Args...>::value)
4005  -> void
4006 {
4007  using error_type = typename storage_type::underlying_error_type;
4008 
4009  auto* p = static_cast<void*>(std::addressof(storage.m_error));
4010  new (p) error_type(detail::forward<Args>(args)...);
4011  storage.m_has_value = false;
4012 }
4013 
4014 template <typename T, typename E>
4015 template <typename Result>
4017 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_error_from_result(
4018  Result&& other
4019 ) -> void
4020 {
4021  if (other.storage.m_has_value) {
4022  construct_value();
4023  } else {
4024  construct_error(detail::forward<Result>(other).storage.m_error);
4025  }
4026 }
4027 
4028 
4029 template <typename T, typename E>
4030 template <typename Result>
4032 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_from_result(
4033  Result&& other
4034 ) -> void
4035 {
4036  if (other.storage.m_has_value) {
4037  construct_value_from_result_impl(
4038  std::is_lvalue_reference<T>{},
4039  detail::forward<Result>(other).storage.m_value
4040  );
4041  } else {
4042  construct_error(detail::forward<Result>(other).storage.m_error);
4043  }
4044 }
4045 
4046 template <typename T, typename E>
4047 template <typename Value>
4049 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value(Value&& value)
4050  noexcept(std::is_nothrow_assignable<T,Value>::value)
4051  -> void
4052 {
4053  if (!storage.m_has_value) {
4054  storage.destroy();
4055  construct_value(detail::forward<Value>(value));
4056  } else {
4057  storage.m_value = detail::forward<Value>(value);
4058  }
4059 }
4060 
4061 template <typename T, typename E>
4062 template <typename Error>
4064 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_error(Error&& error)
4065  noexcept(std::is_nothrow_assignable<E,Error>::value)
4066  -> void
4067 {
4068  if (storage.m_has_value) {
4069  storage.destroy();
4070  construct_error(detail::forward<Error>(error));
4071  } else {
4072  storage.m_error = detail::forward<Error>(error);
4073  }
4074 }
4075 
4076 template <typename T, typename E>
4077 template <typename Result>
4079 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_from_result(Result&& other)
4080  -> void
4081 {
4082  if (other.storage.m_has_value != storage.m_has_value) {
4083  storage.destroy();
4084  construct_from_result(detail::forward<Result>(other));
4085  } else if (storage.m_has_value) {
4086  assign_value_from_result_impl(
4087  std::is_lvalue_reference<T>{},
4088  detail::forward<Result>(other)
4089  );
4090  } else {
4091  storage.m_error = detail::forward<Result>(other).storage.m_error;
4092  }
4093 }
4094 
4095 template <typename T, typename E>
4096 template <typename ReferenceWrapper>
4098 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value_from_result_impl(
4099  std::true_type,
4100  ReferenceWrapper&& reference
4101 ) noexcept -> void
4102 {
4103  using value_type = typename storage_type::underlying_value_type;
4104 
4105  auto* p = static_cast<void*>(std::addressof(storage.m_value));
4106  new (p) value_type(reference.get());
4107  storage.m_has_value = true;
4108 }
4109 
4110 template <typename T, typename E>
4111 template <typename Value>
4113 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value_from_result_impl(
4114  std::false_type,
4115  Value&& value
4116 ) noexcept(std::is_nothrow_constructible<T,Value>::value) -> void
4117 {
4118  using value_type = typename storage_type::underlying_value_type;
4119 
4120  auto* p = static_cast<void*>(std::addressof(storage.m_value));
4121  new (p) value_type(detail::forward<Value>(value));
4122  storage.m_has_value = true;
4123 }
4124 
4125 template <typename T, typename E>
4126 template <typename Result>
4128 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value_from_result_impl(
4129  std::true_type,
4130  Result&& other
4131 ) -> void
4132 {
4133  // T is a reference; unwrap it
4134  storage.m_value = other.storage.m_value.get();
4135 }
4136 
4137 template <typename T, typename E>
4138 template <typename Result>
4140 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value_from_result_impl(
4141  std::false_type,
4142  Result&& other
4143 ) -> void
4144 {
4145  storage.m_value = detail::forward<Result>(other).storage.m_value;
4146 }
4147 
4148 
4149 //=============================================================================
4150 // class : result_trivial_copy_ctor_base_impl
4151 //=============================================================================
4152 
4153 template <typename T, typename E>
4155 RESULT_NS_IMPL::detail::result_trivial_copy_ctor_base_impl<T,E>
4156  ::result_trivial_copy_ctor_base_impl(const result_trivial_copy_ctor_base_impl& other)
4157  noexcept(std::is_nothrow_copy_constructible<T>::value &&
4158  std::is_nothrow_copy_constructible<E>::value)
4159  : base_type(unit{})
4160 {
4161  using ctor_base = result_construct_base<T,E>;
4162 
4163  ctor_base::construct_from_result(static_cast<const ctor_base&>(other));
4164 }
4165 
4166 //=============================================================================
4167 // class : result_trivial_move_ctor_base
4168 //=============================================================================
4169 
4170 template <typename T, typename E>
4172 RESULT_NS_IMPL::detail::result_trivial_move_ctor_base_impl<T, E>
4173  ::result_trivial_move_ctor_base_impl(result_trivial_move_ctor_base_impl&& other)
4174  noexcept(std::is_nothrow_move_constructible<T>::value &&
4175  std::is_nothrow_move_constructible<E>::value)
4176  : base_type(unit{})
4177 {
4178  using ctor_base = result_construct_base<T,E>;
4179 
4180  ctor_base::construct_from_result(static_cast<ctor_base&&>(other));
4181 }
4182 
4183 //=============================================================================
4184 // class : result_copy_assign_base
4185 //=============================================================================
4186 
4187 template <typename T, typename E>
4189 auto RESULT_NS_IMPL::detail::result_trivial_copy_assign_base_impl<T, E>
4190  ::operator=(const result_trivial_copy_assign_base_impl& other)
4191  noexcept(std::is_nothrow_copy_constructible<T>::value &&
4192  std::is_nothrow_copy_constructible<E>::value &&
4193  std::is_nothrow_copy_assignable<T>::value &&
4194  std::is_nothrow_copy_assignable<E>::value)
4195  -> result_trivial_copy_assign_base_impl&
4196 {
4197  using ctor_base = result_construct_base<T,E>;
4198 
4199  ctor_base::assign_from_result(static_cast<const ctor_base&>(other));
4200  return (*this);
4201 }
4202 
4203 //=========================================================================
4204 // class : result_move_assign_base
4205 //=========================================================================
4206 
4207 template <typename T, typename E>
4209 auto RESULT_NS_IMPL::detail::result_trivial_move_assign_base_impl<T, E>
4210  ::operator=(result_trivial_move_assign_base_impl&& other)
4211  noexcept(std::is_nothrow_move_constructible<T>::value &&
4212  std::is_nothrow_move_constructible<E>::value &&
4213  std::is_nothrow_move_assignable<T>::value &&
4214  std::is_nothrow_move_assignable<E>::value)
4215  -> result_trivial_move_assign_base_impl&
4216 {
4217  using ctor_base = result_construct_base<T,E>;
4218 
4219  ctor_base::assign_from_result(static_cast<ctor_base&&>(other));
4220  return (*this);
4221 }
4222 
4223 template <typename T, typename E>
4224 inline RESULT_INLINE_VISIBILITY constexpr
4225 auto RESULT_NS_IMPL::detail::result_error_extractor::get(const result<T,E>& exp)
4226  noexcept -> const E&
4227 {
4228  return exp.m_storage.storage.m_error;
4229 }
4230 
4231 template <typename T, typename E>
4232 inline RESULT_INLINE_VISIBILITY constexpr
4233 auto RESULT_NS_IMPL::detail::result_error_extractor::get(result<T,E>& exp)
4234  noexcept -> E&
4235 {
4236  return exp.m_storage.storage.m_error;
4237 }
4238 
4239 template <typename T, typename E>
4240 inline RESULT_INLINE_VISIBILITY constexpr
4241 auto RESULT_NS_IMPL::detail::extract_error(const result<T,E>& exp) noexcept -> const E&
4242 {
4243  return result_error_extractor::get(exp);
4244 }
4245 
4246 template <typename E>
4248 auto RESULT_NS_IMPL::detail::throw_bad_result_access(E&& error) -> void
4249 {
4250 #if defined(RESULT_DISABLE_EXCEPTIONS)
4251  std::fprintf(
4252  stderr,
4253  "error attempting to access value from result containing error\n"
4254  );
4255  std::abort();
4256 #else
4257  using exception_type = bad_result_access<
4258  typename std::remove_const<
4259  typename std::remove_reference<E>::type
4260  >::type
4261  >;
4262 
4263  throw exception_type{
4264  detail::forward<E>(error)
4265  };
4266 #endif
4267 }
4268 
4269 template <typename String, typename E>
4271 auto RESULT_NS_IMPL::detail::throw_bad_result_access_message(
4272  String&& message,
4273  E&& error
4274 ) -> void
4275 {
4276 #if defined(RESULT_DISABLE_EXCEPTIONS)
4277  const auto message_string = std::string{
4278  detail::forward<String>(message)
4279  };
4280  std::fprintf(stderr, "%s\n", message_string.c_str());
4281  std::abort();
4282 #else
4283  using exception_type = bad_result_access<
4284  typename std::remove_const<
4285  typename std::remove_reference<E>::type
4286  >::type
4287  >;
4288 
4289  throw exception_type{
4290  detail::forward<String>(message),
4291  detail::forward<E>(error)
4292  };
4293 #endif
4294 }
4295 
4296 //=============================================================================
4297 // class : result<T,E>
4298 //=============================================================================
4299 
4300 template <typename T, typename E>
4301 template <typename U, typename>
4302 inline RESULT_INLINE_VISIBILITY constexpr
4303 RESULT_NS_IMPL::result<T, E>::result()
4304  noexcept(std::is_nothrow_constructible<U>::value)
4305  : m_storage(in_place)
4306 {
4307 
4308 }
4309 
4310 template <typename T, typename E>
4311 template <typename T2, typename E2,
4312  typename std::enable_if<RESULT_NS_IMPL::detail::result_is_implicit_copy_convertible<T,E,T2,E2>::value,int>::type>
4314 RESULT_NS_IMPL::result<T, E>::result(const result<T2,E2>& other)
4315  noexcept(std::is_nothrow_constructible<T,const T2&>::value &&
4317  : m_storage(detail::unit{})
4318 {
4319  m_storage.construct_from_result(
4320  static_cast<const result<T2,E2>&>(other).m_storage
4321  );
4322 }
4323 
4324 template <typename T, typename E>
4325 template <typename T2, typename E2,
4326  typename std::enable_if<RESULT_NS_IMPL::detail::result_is_explicit_copy_convertible<T,E,T2,E2>::value,int>::type>
4328 RESULT_NS_IMPL::result<T, E>::result(const result<T2,E2>& other)
4329  noexcept(std::is_nothrow_constructible<T,const T2&>::value &&
4331  : m_storage(detail::unit{})
4332 {
4333  m_storage.construct_from_result(
4334  static_cast<const result<T2,E2>&>(other).m_storage
4335  );
4336 }
4337 
4338 template <typename T, typename E>
4339 template <typename T2, typename E2,
4340  typename std::enable_if<RESULT_NS_IMPL::detail::result_is_implicit_move_convertible<T,E,T2,E2>::value,int>::type>
4342 RESULT_NS_IMPL::result<T, E>::result(result<T2,E2>&& other)
4343  noexcept(std::is_nothrow_constructible<T,T2&&>::value &&
4345  : m_storage(detail::unit{})
4346 {
4347  m_storage.construct_from_result(
4348  static_cast<result<T2,E2>&&>(other).m_storage
4349  );
4350 }
4351 
4352 template <typename T, typename E>
4353 template <typename T2, typename E2,
4354  typename std::enable_if<RESULT_NS_IMPL::detail::result_is_explicit_move_convertible<T,E,T2,E2>::value,int>::type>
4356 RESULT_NS_IMPL::result<T, E>::result(result<T2,E2>&& other)
4357  noexcept(std::is_nothrow_constructible<T,T2&&>::value &&
4359  : m_storage(detail::unit{})
4360 {
4361  m_storage.construct_from_result(
4362  static_cast<result<T2,E2>&&>(other).m_storage
4363  );
4364 }
4365 
4366 //-----------------------------------------------------------------------------
4367 
4368 template <typename T, typename E>
4369 template <typename...Args, typename>
4370 inline RESULT_INLINE_VISIBILITY constexpr
4371 RESULT_NS_IMPL::result<T, E>::result(in_place_t, Args&&...args)
4372  noexcept(std::is_nothrow_constructible<T, Args...>::value)
4373  : m_storage(in_place, detail::forward<Args>(args)...)
4374 {
4375 
4376 }
4377 
4378 template <typename T, typename E>
4379 template <typename U, typename...Args, typename>
4380 inline RESULT_INLINE_VISIBILITY constexpr
4381 RESULT_NS_IMPL::result<T, E>::result(
4382  in_place_t,
4383  std::initializer_list<U> ilist,
4384  Args&&...args
4386  : m_storage(in_place, ilist, detail::forward<Args>(args)...)
4387 {
4388 
4389 }
4390 
4391 //-----------------------------------------------------------------------------
4392 
4393 template <typename T, typename E>
4394 template <typename...Args, typename>
4395 inline RESULT_INLINE_VISIBILITY constexpr
4396 RESULT_NS_IMPL::result<T, E>::result(in_place_error_t, Args&&...args)
4397  noexcept(std::is_nothrow_constructible<E, Args...>::value)
4398  : m_storage(in_place_error, detail::forward<Args>(args)...)
4399 {
4400 
4401 }
4402 
4403 template <typename T, typename E>
4404 template <typename U, typename...Args, typename>
4405 inline RESULT_INLINE_VISIBILITY constexpr
4406 RESULT_NS_IMPL::result<T, E>::result(
4408  std::initializer_list<U> ilist,
4409  Args&&...args
4411  : m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
4412 {
4413 
4414 }
4415 
4416 //-------------------------------------------------------------------------
4417 
4418 template <typename T, typename E>
4419 template <typename E2, typename>
4420 inline RESULT_INLINE_VISIBILITY constexpr
4421 RESULT_NS_IMPL::result<T, E>::result(const failure<E2>& e)
4422  noexcept(std::is_nothrow_constructible<E,const E2&>::value)
4423  : m_storage(in_place_error, e.error())
4424 {
4425 
4426 }
4427 
4428 template <typename T, typename E>
4429 template <typename E2, typename>
4430 inline RESULT_INLINE_VISIBILITY constexpr
4431 RESULT_NS_IMPL::result<T, E>::result(failure<E2>&& e)
4432  noexcept(std::is_nothrow_constructible<E,E2&&>::value)
4433  : m_storage(in_place_error, static_cast<E2&&>(e.error()))
4434 {
4435 
4436 }
4437 
4438 template <typename T, typename E>
4439 template <typename U,
4440  typename std::enable_if<RESULT_NS_IMPL::detail::result_is_explicit_value_convertible<T,U>::value,int>::type>
4441 inline RESULT_INLINE_VISIBILITY constexpr
4442 RESULT_NS_IMPL::result<T, E>::result(U&& value)
4443  noexcept(std::is_nothrow_constructible<T,U>::value)
4444  : m_storage(in_place, detail::forward<U>(value))
4445 {
4446 
4447 }
4448 
4449 template <typename T, typename E>
4450 template <typename U,
4451  typename std::enable_if<RESULT_NS_IMPL::detail::result_is_implicit_value_convertible<T,U>::value,int>::type>
4452 inline RESULT_INLINE_VISIBILITY constexpr
4453 RESULT_NS_IMPL::result<T, E>::result(U&& value)
4454  noexcept(std::is_nothrow_constructible<T,U>::value)
4455  : m_storage(in_place, detail::forward<U>(value))
4456 {
4457 
4458 }
4459 
4460 //-----------------------------------------------------------------------------
4461 
4462 template <typename T, typename E>
4463 template <typename T2, typename E2, typename>
4465 auto RESULT_NS_IMPL::result<T, E>::operator=(const result<T2,E2>& other)
4466  noexcept(std::is_nothrow_assignable<T, const T2&>::value &&
4467  std::is_nothrow_assignable<E, const E2&>::value)
4468  -> result&
4469 {
4470  m_storage.assign_from_result(
4471  static_cast<const result<T2,E2>&>(other).m_storage
4472  );
4473  return (*this);
4474 }
4475 
4476 template <typename T, typename E>
4477 template <typename T2, typename E2, typename>
4479 auto RESULT_NS_IMPL::result<T, E>::operator=(result<T2,E2>&& other)
4480  noexcept(std::is_nothrow_assignable<T, T2&&>::value &&
4482  -> result&
4483 {
4484  m_storage.assign_from_result(
4485  static_cast<result<T2,E2>&&>(other).m_storage
4486  );
4487  return (*this);
4488 }
4489 
4490 template <typename T, typename E>
4491 template <typename U, typename>
4493 auto RESULT_NS_IMPL::result<T, E>::operator=(U&& value)
4494  noexcept(std::is_nothrow_assignable<T, U>::value)
4495  -> result&
4496 {
4497  m_storage.assign_value(detail::forward<U>(value));
4498  return (*this);
4499 }
4500 
4501 template <typename T, typename E>
4502 template <typename E2, typename>
4504 auto RESULT_NS_IMPL::result<T, E>::operator=(const failure<E2>& other)
4505  noexcept(std::is_nothrow_assignable<E, const E2&>::value)
4506  -> result&
4507 {
4508  m_storage.assign_error(other.error());
4509  return (*this);
4510 }
4511 
4512 template <typename T, typename E>
4513 template <typename E2, typename>
4515 auto RESULT_NS_IMPL::result<T, E>::operator=(failure<E2>&& other)
4516  noexcept(std::is_nothrow_assignable<E, E2&&>::value)
4517  -> result&
4518 {
4519  m_storage.assign_error(static_cast<E2&&>(other.error()));
4520  return (*this);
4521 }
4522 
4523 //-----------------------------------------------------------------------------
4524 // Observers
4525 //-----------------------------------------------------------------------------
4526 
4527 template <typename T, typename E>
4529 auto RESULT_NS_IMPL::result<T, E>::operator->()
4530  noexcept -> typename std::remove_reference<T>::type*
4531 {
4532  // Prior to C++17, std::addressof was not `constexpr`.
4533  // Since `addressof` fixes a relatively obscure issue where users define a
4534  // custom `operator&`, the pre-C++17 implementation has been defined to be
4535  // `&(**this)` so that it may exist in constexpr contexts.
4536 #if __cplusplus >= 201703L
4537  return std::addressof(**this);
4538 #else
4539  return &(**this);
4540 #endif
4541 }
4542 
4543 template <typename T, typename E>
4544 inline RESULT_INLINE_VISIBILITY constexpr
4545 auto RESULT_NS_IMPL::result<T, E>::operator->()
4546  const noexcept -> typename std::remove_reference<typename std::add_const<T>::type>::type*
4547 {
4548 #if __cplusplus >= 201703L
4549  return std::addressof(**this);
4550 #else
4551  return &(**this);
4552 #endif
4553 }
4554 
4555 template <typename T, typename E>
4557 auto RESULT_NS_IMPL::result<T, E>::operator*()
4558  & noexcept -> typename std::add_lvalue_reference<T>::type
4559 {
4560  return m_storage.storage.m_value;
4561 }
4562 
4563 template <typename T, typename E>
4565 auto RESULT_NS_IMPL::result<T, E>::operator*()
4566  && noexcept -> typename std::add_rvalue_reference<T>::type
4567 {
4568  using reference = typename std::add_rvalue_reference<T>::type;
4569 
4570  return static_cast<reference>(m_storage.storage.m_value);
4571 }
4572 
4573 template <typename T, typename E>
4574 inline RESULT_INLINE_VISIBILITY constexpr
4575 auto RESULT_NS_IMPL::result<T, E>::operator*()
4576  const& noexcept -> typename std::add_lvalue_reference<typename std::add_const<T>::type>::type
4577 {
4578  return m_storage.storage.m_value;
4579 }
4580 
4581 template <typename T, typename E>
4582 inline RESULT_INLINE_VISIBILITY constexpr
4583 auto RESULT_NS_IMPL::result<T, E>::operator*()
4584  const&& noexcept -> typename std::add_rvalue_reference<typename std::add_const<T>::type>::type
4585 {
4586  using reference = typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
4587 
4588  return static_cast<reference>(m_storage.storage.m_value);
4589 }
4590 
4591 //-----------------------------------------------------------------------------
4592 
4593 template <typename T, typename E>
4594 inline RESULT_INLINE_VISIBILITY constexpr
4595 RESULT_NS_IMPL::result<T,E>::operator bool()
4596  const noexcept
4597 {
4598  return m_storage.storage.m_has_value;
4599 }
4600 
4601 template <typename T, typename E>
4602 inline RESULT_INLINE_VISIBILITY constexpr
4603 auto RESULT_NS_IMPL::result<T,E>::has_value()
4604  const noexcept -> bool
4605 {
4606  return m_storage.storage.m_has_value;
4607 }
4608 
4609 template <typename T, typename E>
4610 inline RESULT_INLINE_VISIBILITY constexpr
4611 auto RESULT_NS_IMPL::result<T,E>::has_error()
4612  const noexcept -> bool
4613 {
4614  return !m_storage.storage.m_has_value;
4615 }
4616 
4617 //-----------------------------------------------------------------------------
4618 
4619 // The `has_value()` expression below is incorrectly identified as an unused
4620 // value, which results in the `-Wunused-value` warning. This is suppressed
4621 // to prevent false-positives
4622 #if defined(__clang__)
4623 # pragma clang diagnostic push
4624 # pragma clang diagnostic ignored "-Wunused-value"
4625 #elif defined(__GNUC__)
4626 # pragma GCC diagnostic push
4627 # pragma GCC diagnostic ignored "-Wunused-value"
4628 #elif defined(_MSC_VER)
4629 // Older MSVC versions incorrectly warn on returning a reference to a temporary.
4630 // This has been suppressed
4631 # pragma warning(push)
4632 # pragma warning(disable:4172)
4633 #endif
4634 
4635 template <typename T, typename E>
4637 auto RESULT_NS_IMPL::result<T,E>::value()
4638  & -> typename std::add_lvalue_reference<T>::type
4639 {
4640  return (has_value() ||
4641  (detail::throw_bad_result_access(m_storage.storage.m_error), false),
4642  m_storage.storage.m_value
4643  );
4644 }
4645 
4646 template <typename T, typename E>
4648 auto RESULT_NS_IMPL::result<T,E>::value()
4649  && -> typename std::add_rvalue_reference<T>::type
4650 {
4651  using reference = typename std::add_rvalue_reference<T>::type;
4652 
4653  return (has_value() ||
4654  (detail::throw_bad_result_access(static_cast<E&&>(m_storage.storage.m_error)), true),
4655  static_cast<reference>(m_storage.storage.m_value)
4656  );
4657 }
4658 
4659 template <typename T, typename E>
4660 inline RESULT_INLINE_VISIBILITY constexpr
4661 auto RESULT_NS_IMPL::result<T,E>::value()
4662  const & -> typename std::add_lvalue_reference<typename std::add_const<T>::type>::type
4663 {
4664  return (has_value() ||
4665  (detail::throw_bad_result_access(m_storage.storage.m_error), true),
4666  m_storage.storage.m_value
4667  );
4668 }
4669 
4670 template <typename T, typename E>
4671 inline RESULT_INLINE_VISIBILITY constexpr
4672 auto RESULT_NS_IMPL::result<T,E>::value()
4673  const && -> typename std::add_rvalue_reference<typename std::add_const<T>::type>::type
4674 {
4675  using reference = typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
4676 
4677  return (has_value() ||
4678  (detail::throw_bad_result_access(static_cast<const E&&>(m_storage.storage.m_error)), true),
4679  (static_cast<reference>(m_storage.storage.m_value))
4680  );
4681 }
4682 
4683 #if defined(__clang__)
4684 # pragma clang diagnostic pop
4685 #elif defined(__GNUC__)
4686 # pragma GCC diagnostic pop
4687 #elif defined(_MSC_VER)
4688 # pragma warning(pop)
4689 #endif
4690 
4691 template <typename T, typename E>
4692 inline RESULT_INLINE_VISIBILITY constexpr
4693 auto RESULT_NS_IMPL::result<T,E>::error() const &
4694  noexcept(std::is_nothrow_constructible<E>::value &&
4696 {
4697  static_assert(
4698  std::is_default_constructible<E>::value,
4699  "E must be default-constructible if 'error()' checks are used. "
4700  "This is to allow for default-constructed error states to represent the "
4701  "'good' state"
4702  );
4703 
4704  return m_storage.storage.m_has_value
4705  ? E{}
4706  : m_storage.storage.m_error;
4707 }
4708 
4709 template <typename T, typename E>
4711 auto RESULT_NS_IMPL::result<T,E>::error() &&
4712  noexcept(std::is_nothrow_constructible<E>::value &&
4713  std::is_nothrow_move_constructible<E>::value) -> E
4714 {
4715  static_assert(
4716  std::is_default_constructible<E>::value,
4717  "E must be default-constructible if 'error()' checks are used. "
4718  "This is to allow for default-constructed error states to represent the "
4719  "'good' state"
4720  );
4721 
4722  return m_storage.storage.m_has_value
4723  ? E{}
4724  : static_cast<E&&>(m_storage.storage.m_error);
4725 }
4726 
4727 //-----------------------------------------------------------------------------
4728 
4729 template <typename T, typename E>
4730 template <typename String, typename>
4732 auto RESULT_NS_IMPL::result<T,E>::expect(String&& message)
4733  & -> typename std::add_lvalue_reference<T>::type
4734 {
4735  return (has_value() ||
4736  (detail::throw_bad_result_access_message(
4737  detail::forward<String>(message),
4738  m_storage.storage.m_error
4739  ), true),
4740  m_storage.storage.m_value
4741  );
4742 }
4743 
4744 template <typename T, typename E>
4745 template <typename String, typename>
4747 auto RESULT_NS_IMPL::result<T,E>::expect(String&& message)
4748  && -> typename std::add_rvalue_reference<T>::type
4749 {
4750  using reference = typename std::add_rvalue_reference<T>::type;
4751 
4752  return (has_value() ||
4753  (detail::throw_bad_result_access_message(
4754  detail::forward<String>(message),
4755  static_cast<E&&>(m_storage.storage.m_error)
4756  ), true),
4757  static_cast<reference>(m_storage.storage.m_value)
4758  );
4759 }
4760 
4761 template <typename T, typename E>
4762 template <typename String, typename>
4764 auto RESULT_NS_IMPL::result<T,E>::expect(String&& message)
4765  const & -> typename std::add_lvalue_reference<typename std::add_const<T>::type>::type
4766 {
4767  return (has_value() ||
4768  (detail::throw_bad_result_access_message(
4769  detail::forward<String>(message),
4770  m_storage.storage.m_error
4771  ), true),
4772  m_storage.storage.m_value
4773  );
4774 }
4775 
4776 template <typename T, typename E>
4777 template <typename String, typename>
4779 auto RESULT_NS_IMPL::result<T,E>::expect(String&& message)
4780  const && -> typename std::add_rvalue_reference<typename std::add_const<T>::type>::type
4781 {
4782  using reference = typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
4783 
4784  return (has_value() ||
4785  (detail::throw_bad_result_access_message(
4786  detail::forward<String>(message),
4787  static_cast<const E&&>(m_storage.storage.m_error)
4788  ), true),
4789  (static_cast<reference>(m_storage.storage.m_value))
4790  );
4791 }
4792 
4793 //-----------------------------------------------------------------------------
4794 // Monadic Functionalities
4795 //-----------------------------------------------------------------------------
4796 
4797 template <typename T, typename E>
4798 template <typename U>
4799 inline RESULT_INLINE_VISIBILITY constexpr
4800 auto RESULT_NS_IMPL::result<T, E>::value_or(U&& default_value)
4801  const& -> typename std::remove_reference<T>::type
4802 {
4803  return m_storage.storage.m_has_value
4804  ? m_storage.storage.m_value
4805  : detail::forward<U>(default_value);
4806 }
4807 
4808 template <typename T, typename E>
4809 template <typename U>
4811 auto RESULT_NS_IMPL::result<T, E>::value_or(U&& default_value)
4812  && -> typename std::remove_reference<T>::type
4813 {
4814  return m_storage.storage.m_has_value
4815  ? static_cast<T&&>(**this)
4816  : detail::forward<U>(default_value);
4817 }
4818 
4819 template <typename T, typename E>
4820 template <typename U>
4821 inline RESULT_INLINE_VISIBILITY constexpr
4822 auto RESULT_NS_IMPL::result<T, E>::error_or(U&& default_error)
4823  const& -> error_type
4824 {
4825  return m_storage.storage.m_has_value
4826  ? detail::forward<U>(default_error)
4827  : m_storage.storage.m_error;
4828 }
4829 
4830 template <typename T, typename E>
4831 template <typename U>
4833 auto RESULT_NS_IMPL::result<T, E>::error_or(U&& default_error)
4834  && -> error_type
4835 {
4836  return m_storage.storage.m_has_value
4837  ? detail::forward<U>(default_error)
4838  : static_cast<E&&>(m_storage.storage.m_error);
4839 }
4840 
4841 template <typename T, typename E>
4842 template <typename U>
4843 inline RESULT_INLINE_VISIBILITY constexpr
4844 auto RESULT_NS_IMPL::result<T, E>::and_then(U&& value)
4845  const -> result<typename std::decay<U>::type,E>
4846 {
4847  return map([&value](const T&){
4848  return detail::forward<U>(value);
4849  });
4850 }
4851 
4852 //-----------------------------------------------------------------------------
4853 
4854 template <typename T, typename E>
4855 template <typename Fn>
4856 inline RESULT_INLINE_VISIBILITY constexpr
4857 auto RESULT_NS_IMPL::result<T, E>::flat_map(Fn&& fn)
4858  const & -> detail::invoke_result_t<Fn, const T&>
4859 {
4860  using result_type = detail::invoke_result_t<Fn, const T&>;
4861 
4862  static_assert(
4863  is_result<result_type>::value,
4864  "flat_map must return a result type or the program is ill-formed"
4865  );
4866 
4867  return has_value()
4868  ? detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value)
4869  : result_type(in_place_error, m_storage.storage.m_error);
4870 }
4871 
4872 template <typename T, typename E>
4873 template <typename Fn>
4875 auto RESULT_NS_IMPL::result<T, E>::flat_map(Fn&& fn)
4876  && -> detail::invoke_result_t<Fn, T&&>
4877 {
4878  using result_type = detail::invoke_result_t<Fn, T&&>;
4879 
4880  static_assert(
4881  is_result<result_type>::value,
4882  "flat_map must return a result type or the program is ill-formed"
4883  );
4884 
4885  return has_value()
4886  ? detail::invoke(detail::forward<Fn>(fn), static_cast<T&&>(m_storage.storage.m_value))
4887  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4888 }
4889 
4890 template <typename T, typename E>
4891 template <typename Fn>
4892 inline RESULT_INLINE_VISIBILITY constexpr
4893 auto RESULT_NS_IMPL::result<T, E>::map(Fn&& fn)
4894  const & -> result<detail::invoke_result_t<Fn,const T&>,E>
4895 {
4896  using result_type = detail::invoke_result_t<Fn,const T&>;
4897 
4898  return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
4899 }
4900 
4901 template <typename T, typename E>
4902 template <typename Fn>
4904 auto RESULT_NS_IMPL::result<T, E>::map(Fn&& fn)
4905  && -> result<detail::invoke_result_t<Fn,T&&>,E>
4906 {
4907  using result_type = detail::invoke_result_t<Fn,T&&>;
4908 
4909  return static_cast<result<T,E>&&>(*this).map_impl(
4910  std::is_void<result_type>{},
4911  detail::forward<Fn>(fn)
4912  );
4913 }
4914 
4915 //-----------------------------------------------------------------------------
4916 
4917 template <typename T, typename E>
4918 template <typename Fn>
4919 inline RESULT_INLINE_VISIBILITY constexpr
4920 auto RESULT_NS_IMPL::result<T, E>::map_error(Fn&& fn)
4921  const & -> result<T, detail::invoke_result_t<Fn,const E&>>
4922 {
4923  using result_type = result<T, detail::invoke_result_t<Fn, const E&>>;
4924 
4925  return has_error()
4926  ? result_type(in_place_error, detail::invoke(
4927  detail::forward<Fn>(fn), m_storage.storage.m_error
4928  ))
4929  : result_type(in_place, m_storage.storage.m_value);
4930 }
4931 
4932 template <typename T, typename E>
4933 template <typename Fn>
4935 auto RESULT_NS_IMPL::result<T, E>::map_error(Fn&& fn)
4936  && -> result<T, detail::invoke_result_t<Fn,E&&>>
4937 {
4938  using result_type = result<T, detail::invoke_result_t<Fn, E&&>>;
4939 
4940  return has_error()
4941  ? result_type(in_place_error, detail::invoke(
4942  detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error)
4943  ))
4944  : result_type(static_cast<T&&>(m_storage.storage.m_value));
4945 }
4946 
4947 template <typename T, typename E>
4948 template <typename Fn>
4949 inline RESULT_INLINE_VISIBILITY constexpr
4950 auto RESULT_NS_IMPL::result<T, E>::flat_map_error(Fn&& fn)
4951  const & -> detail::invoke_result_t<Fn, const E&>
4952 {
4953  using result_type = detail::invoke_result_t<Fn, const E&>;
4954 
4955  static_assert(
4956  is_result<result_type>::value,
4957  "flat_map_error must return a result type or the program is ill-formed"
4958  );
4959 
4960  return has_value()
4961  ? result_type(in_place, m_storage.storage.m_value)
4962  : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
4963 }
4964 
4965 template <typename T, typename E>
4966 template <typename Fn>
4968 auto RESULT_NS_IMPL::result<T, E>::flat_map_error(Fn&& fn)
4969  && -> detail::invoke_result_t<Fn, E&&>
4970 {
4971  using result_type = detail::invoke_result_t<Fn, E&&>;
4972 
4973  static_assert(
4974  is_result<result_type>::value,
4975  "flat_map_error must return a result type or the program is ill-formed"
4976  );
4977 
4978  return has_value()
4979  ? result_type(in_place, static_cast<T&&>(m_storage.storage.m_value))
4980  : detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error));
4981 }
4982 
4983 //-----------------------------------------------------------------------------
4984 // Private Monadic Functions
4985 //-----------------------------------------------------------------------------
4986 
4987 template <typename T, typename E>
4988 template <typename Fn>
4989 inline RESULT_INLINE_VISIBILITY constexpr
4990 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type, Fn&& fn)
4991  const & -> result<void,E>
4992 {
4993  using result_type = result<void, E>;
4994 
4995  return has_value()
4996  ? (detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value), result_type{})
4997  : result_type(in_place_error, m_storage.storage.m_error);
4998 }
4999 
5000 template <typename T, typename E>
5001 template <typename Fn>
5002 inline RESULT_INLINE_VISIBILITY constexpr
5003 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type, Fn&& fn)
5004  const & -> result<detail::invoke_result_t<Fn,const T&>,E>
5005 {
5006  using invoke_result_type = detail::invoke_result_t<Fn,const T&>;
5007  using result_type = result<invoke_result_type, E>;
5008 
5009  return has_value()
5010  ? result_type(in_place, detail::invoke(
5011  detail::forward<Fn>(fn), m_storage.storage.m_value
5012  ))
5013  : result_type(in_place_error, m_storage.storage.m_error);
5014 }
5015 
5016 template <typename T, typename E>
5017 template <typename Fn>
5019 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type, Fn&& fn)
5020  && -> result<void,E>
5021 {
5022  using result_type = result<void, E>;
5023 
5024  return has_value()
5025  ? (detail::invoke(
5026  detail::forward<Fn>(fn), static_cast<T&&>(m_storage.storage.m_value)
5027  ), result_type{})
5028  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
5029 }
5030 
5031 template <typename T, typename E>
5032 template <typename Fn>
5034 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type, Fn&& fn)
5035  && -> result<detail::invoke_result_t<Fn,T&&>,E>
5036 {
5037  using invoke_result_type = detail::invoke_result_t<Fn,T&&>;
5038  using result_type = result<invoke_result_type, E>;
5039 
5040  return has_value()
5041  ? result_type(in_place, detail::invoke(
5042  detail::forward<Fn>(fn), static_cast<T&&>(m_storage.storage.m_value)
5043  ))
5044  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
5045 }
5046 
5047 //=============================================================================
5048 // class : result<void,E>
5049 //=============================================================================
5050 
5051 //-----------------------------------------------------------------------------
5052 // Constructor / Assignment
5053 //-----------------------------------------------------------------------------
5054 
5055 template <typename E>
5056 inline RESULT_INLINE_VISIBILITY constexpr
5057 RESULT_NS_IMPL::result<void, E>::result()
5058  noexcept
5059  : m_storage(in_place)
5060 {
5061 
5062 }
5063 
5064 template <typename E>
5065 template <typename U, typename E2, typename>
5067 RESULT_NS_IMPL::result<void, E>::result(const result<U,E2>& other)
5068  noexcept(std::is_nothrow_constructible<E,const E2&>::value)
5069  : m_storage(detail::unit{})
5070 {
5071  m_storage.construct_error_from_result(
5072  static_cast<const result<U,E2>&>(other).m_storage
5073  );
5074 }
5075 
5076 template <typename E>
5077 template <typename U, typename E2, typename>
5079 RESULT_NS_IMPL::result<void, E>::result(result<U,E2>&& other)
5080  noexcept(std::is_nothrow_constructible<E,E2&&>::value)
5081  : m_storage(detail::unit{})
5082 {
5083  m_storage.construct_error_from_result(
5084  static_cast<result<U,E2>&&>(other).m_storage
5085  );
5086 }
5087 
5088 
5089 //-----------------------------------------------------------------------------
5090 
5091 template <typename E>
5092 inline RESULT_INLINE_VISIBILITY constexpr
5093 RESULT_NS_IMPL::result<void, E>::result(in_place_t)
5094  noexcept
5095  : m_storage(in_place)
5096 {
5097 
5098 }
5099 
5100 template <typename E>
5101 template <typename...Args, typename>
5102 inline RESULT_INLINE_VISIBILITY constexpr
5103 RESULT_NS_IMPL::result<void, E>::result(in_place_error_t, Args&&...args)
5104  noexcept(std::is_nothrow_constructible<E, Args...>::value)
5105  : m_storage(in_place_error, detail::forward<Args>(args)...)
5106 {
5107 
5108 }
5109 
5110 template <typename E>
5111 template <typename U, typename...Args, typename>
5112 inline RESULT_INLINE_VISIBILITY constexpr
5113 RESULT_NS_IMPL::result<void, E>::result(in_place_error_t,
5114  std::initializer_list<U> ilist,
5115  Args&&...args)
5117  : m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
5118 {
5119 
5120 }
5121 
5122 //-----------------------------------------------------------------------------
5123 
5124 template <typename E>
5125 template <typename E2, typename>
5126 inline RESULT_INLINE_VISIBILITY constexpr
5127 RESULT_NS_IMPL::result<void, E>::result(const failure<E2>& e)
5128  noexcept(std::is_nothrow_constructible<E,const E2&>::value)
5129  : m_storage(in_place_error, e.error())
5130 {
5131 
5132 }
5133 
5134 template <typename E>
5135 template <typename E2, typename>
5136 inline RESULT_INLINE_VISIBILITY constexpr
5137 RESULT_NS_IMPL::result<void, E>::result(failure<E2>&& e)
5138  noexcept(std::is_nothrow_constructible<E,E2&&>::value)
5139  : m_storage(in_place_error, static_cast<E2&&>(e.error()))
5140 {
5141 
5142 }
5143 
5144 //-----------------------------------------------------------------------------
5145 
5146 template <typename E>
5147 template <typename E2, typename>
5149 auto RESULT_NS_IMPL::result<void, E>::operator=(const result<void,E2>& other)
5150  noexcept(std::is_nothrow_assignable<E, const E2&>::value)
5151  -> result&
5152 {
5153  m_storage.assign_from_result(other.m_storage);
5154  return (*this);
5155 }
5156 
5157 template <typename E>
5158 template <typename E2, typename>
5160 auto RESULT_NS_IMPL::result<void, E>::operator=(result<void,E2>&& other)
5161  noexcept(std::is_nothrow_assignable<E, E2&&>::value)
5162  -> result&
5163 {
5164  m_storage.assign_from_result(static_cast<result<void,E2>&&>(other).m_storage);
5165  return (*this);
5166 }
5167 
5168 template <typename E>
5169 template <typename E2, typename>
5171 auto RESULT_NS_IMPL::result<void, E>::operator=(const failure<E2>& other)
5172  noexcept(std::is_nothrow_assignable<E, const E2&>::value)
5173  -> result&
5174 {
5175  m_storage.assign_error(other.error());
5176  return (*this);
5177 }
5178 
5179 template <typename E>
5180 template <typename E2, typename>
5182 auto RESULT_NS_IMPL::result<void, E>::operator=(failure<E2>&& other)
5183  noexcept(std::is_nothrow_assignable<E, E2&&>::value)
5184  -> result&
5185 {
5186  m_storage.assign_error(static_cast<E2&&>(other.error()));
5187  return (*this);
5188 }
5189 
5190 //-----------------------------------------------------------------------------
5191 // Observers
5192 //-----------------------------------------------------------------------------
5193 
5194 template <typename E>
5195 inline RESULT_INLINE_VISIBILITY constexpr
5196 RESULT_NS_IMPL::result<void, E>::operator bool()
5197  const noexcept
5198 {
5199  return has_value();
5200 }
5201 
5202 template <typename E>
5203 inline RESULT_INLINE_VISIBILITY constexpr
5204 auto RESULT_NS_IMPL::result<void, E>::has_value()
5205  const noexcept -> bool
5206 {
5207  return m_storage.storage.m_has_value;
5208 }
5209 
5210 template <typename E>
5211 inline RESULT_INLINE_VISIBILITY constexpr
5212 auto RESULT_NS_IMPL::result<void, E>::has_error()
5213  const noexcept -> bool
5214 {
5215  return !has_value();
5216 }
5217 
5218 //-----------------------------------------------------------------------------
5219 
5220 template <typename E>
5222 auto RESULT_NS_IMPL::result<void, E>::value()
5223  const & -> void
5224 {
5225  static_cast<void>(
5226  has_value() ||
5227  (detail::throw_bad_result_access(m_storage.storage.m_error), true)
5228  );
5229 }
5230 
5231 template <typename E>
5233 auto RESULT_NS_IMPL::result<void, E>::value()
5234  && -> void
5235 {
5236  static_cast<void>(
5237  has_value() ||
5238  (detail::throw_bad_result_access(static_cast<E&&>(m_storage.storage.m_error)), true)
5239  );
5240 }
5241 
5242 template <typename E>
5243 inline RESULT_INLINE_VISIBILITY constexpr
5244 auto RESULT_NS_IMPL::result<void, E>::error()
5245  const &
5246  noexcept(std::is_nothrow_constructible<E>::value &&
5248 {
5249  return has_value() ? E{} : m_storage.storage.m_error;
5250 }
5251 
5252 template <typename E>
5254 auto RESULT_NS_IMPL::result<void, E>::error()
5255  && noexcept(std::is_nothrow_constructible<E>::value &&
5257 {
5258  return has_value() ? E{} : static_cast<E&&>(m_storage.storage.m_error);
5259 }
5260 
5261 //-----------------------------------------------------------------------------
5262 
5263 template <typename E>
5264 template <typename String, typename>
5266 auto RESULT_NS_IMPL::result<void,E>::expect(String&& message)
5267  const & -> void
5268 {
5269  if (has_error()) {
5270  detail::throw_bad_result_access_message(
5271  detail::forward<String>(message),
5272  m_storage.storage.m_error
5273  );
5274  }
5275 }
5276 
5277 template <typename E>
5278 template <typename String, typename>
5280 auto RESULT_NS_IMPL::result<void,E>::expect(String&& message)
5281  && -> void
5282 {
5283  if (has_error()) {
5284  detail::throw_bad_result_access_message(
5285  detail::forward<String>(message),
5286  static_cast<E&&>(m_storage.storage.m_error)
5287  );
5288  }
5289 }
5290 
5291 //-----------------------------------------------------------------------------
5292 // Monadic Functionalities
5293 //-----------------------------------------------------------------------------
5294 
5295 template <typename E>
5296 template <typename U>
5297 inline RESULT_INLINE_VISIBILITY constexpr
5298 auto RESULT_NS_IMPL::result<void, E>::error_or(U&& default_error)
5299  const & -> error_type
5300 {
5301  return has_value()
5302  ? detail::forward<U>(default_error)
5303  : m_storage.storage.m_error;
5304 }
5305 
5306 template <typename E>
5307 template <typename U>
5309 auto RESULT_NS_IMPL::result<void, E>::error_or(U&& default_error)
5310  && -> error_type
5311 {
5312  return has_value()
5313  ? detail::forward<U>(default_error)
5314  : static_cast<E&&>(m_storage.storage.m_error);
5315 }
5316 
5317 template <typename E>
5318 template <typename U>
5319 inline RESULT_INLINE_VISIBILITY constexpr
5320 auto RESULT_NS_IMPL::result<void, E>::and_then(U&& value)
5321  const -> result<typename std::decay<U>::type,E>
5322 {
5323  return map([&value]{
5324  return detail::forward<U>(value);
5325  });
5326 }
5327 
5328 //-----------------------------------------------------------------------------
5329 
5330 template <typename E>
5331 template <typename Fn>
5332 inline RESULT_INLINE_VISIBILITY constexpr
5333 auto RESULT_NS_IMPL::result<void, E>::flat_map(Fn&& fn)
5334  const & -> detail::invoke_result_t<Fn>
5335 {
5336  using result_type = detail::invoke_result_t<Fn>;
5337 
5338  static_assert(
5339  is_result<result_type>::value,
5340  "flat_map must return a result type or the program is ill-formed"
5341  );
5342 
5343  return has_value()
5344  ? detail::invoke(detail::forward<Fn>(fn))
5345  : result_type(in_place_error, m_storage.storage.m_error);
5346 }
5347 
5348 template <typename E>
5349 template <typename Fn>
5351 auto RESULT_NS_IMPL::result<void, E>::flat_map(Fn&& fn)
5352  && -> detail::invoke_result_t<Fn>
5353 {
5354  using result_type = detail::invoke_result_t<Fn>;
5355 
5356  static_assert(
5357  is_result<result_type>::value,
5358  "flat_map must return a result type or the program is ill-formed"
5359  );
5360 
5361  return has_value()
5362  ? detail::invoke(detail::forward<Fn>(fn))
5363  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
5364 }
5365 
5366 template <typename E>
5367 template <typename Fn>
5368 inline RESULT_INLINE_VISIBILITY constexpr
5369 auto RESULT_NS_IMPL::result<void, E>::map(Fn&& fn)
5370  const & -> result<detail::invoke_result_t<Fn>,E>
5371 {
5372  using result_type = detail::invoke_result_t<Fn>;
5373 
5374  return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
5375 }
5376 
5377 template <typename E>
5378 template <typename Fn>
5380 auto RESULT_NS_IMPL::result<void, E>::map(Fn&& fn)
5381  && -> result<detail::invoke_result_t<Fn>,E>
5382 {
5383  using result_type = detail::invoke_result_t<Fn>;
5384 
5385  return static_cast<result<void,E>&&>(*this).map_impl(
5386  std::is_void<result_type>{},
5387  detail::forward<Fn>(fn)
5388  );
5389 }
5390 
5391 //-----------------------------------------------------------------------------
5392 
5393 template <typename E>
5394 template <typename Fn>
5395 inline RESULT_INLINE_VISIBILITY constexpr
5396 auto RESULT_NS_IMPL::result<void, E>::map_error(Fn&& fn)
5397  const & -> result<void, detail::invoke_result_t<Fn,const E&>>
5398 {
5399  using result_type = result<void, detail::invoke_result_t<Fn, const E&>>;
5400 
5401  return has_value()
5402  ? result_type{}
5403  : result_type(in_place_error, detail::invoke(
5404  detail::forward<Fn>(fn), m_storage.storage.m_error
5405  ));
5406 }
5407 
5408 template <typename E>
5409 template <typename Fn>
5411 auto RESULT_NS_IMPL::result<void, E>::map_error(Fn&& fn)
5412  && -> result<void, detail::invoke_result_t<Fn,E&&>>
5413 {
5414  using result_type = result<void, detail::invoke_result_t<Fn, E&&>>;
5415 
5416  return has_value()
5417  ? result_type{}
5418  : result_type(in_place_error,
5419  detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error)
5420  ));
5421 }
5422 
5423 template <typename E>
5424 template <typename Fn>
5425 inline RESULT_INLINE_VISIBILITY constexpr
5426 auto RESULT_NS_IMPL::result<void, E>::flat_map_error(Fn&& fn)
5427  const & -> detail::invoke_result_t<Fn,const E&>
5428 {
5429  using result_type = detail::invoke_result_t<Fn,const E&>;
5430 
5431  static_assert(
5432  is_result<result_type>::value,
5433  "flat_map_error must return a result type or the program is ill-formed"
5434  );
5435  static_assert(
5436  std::is_default_constructible<typename result_type::value_type>::value,
5437  "flat_map_error for result<void,E> requires the new T type to be default-"
5438  "constructible"
5439  );
5440 
5441  return has_value()
5442  ? result_type{}
5443  : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
5444 }
5445 
5446 template <typename E>
5447 template <typename Fn>
5449 auto RESULT_NS_IMPL::result<void, E>::flat_map_error(Fn&& fn)
5450  && -> detail::invoke_result_t<Fn,E&&>
5451 {
5452  using result_type = detail::invoke_result_t<Fn,E&&>;
5453 
5454  static_assert(
5455  is_result<result_type>::value,
5456  "flat_map_error must return a result type or the program is ill-formed"
5457  );
5458  static_assert(
5459  std::is_default_constructible<typename result_type::value_type>::value,
5460  "flat_map_error for result<void,E> requires the new T type to be default-"
5461  "constructible"
5462  );
5463 
5464  return has_value()
5465  ? result_type{}
5466  : detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error));
5467 }
5468 
5469 //-----------------------------------------------------------------------------
5470 // Private Monadic Functions
5471 //-----------------------------------------------------------------------------
5472 
5473 template <typename E>
5474 template <typename Fn>
5475 inline RESULT_INLINE_VISIBILITY constexpr
5476 auto RESULT_NS_IMPL::result<void, E>::map_impl(std::true_type, Fn&& fn)
5477  const & -> result<void,E>
5478 {
5479  using result_type = result<void, E>;
5480 
5481  return has_value()
5482  ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
5483  : result_type(in_place_error, m_storage.storage.m_error);
5484 }
5485 
5486 template <typename E>
5487 template <typename Fn>
5488 inline RESULT_INLINE_VISIBILITY constexpr
5489 auto RESULT_NS_IMPL::result<void, E>::map_impl(std::false_type, Fn&& fn)
5490  const & -> result<detail::invoke_result_t<Fn>,E>
5491 {
5492  using invoke_result_type = detail::invoke_result_t<Fn>;
5493  using result_type = result<invoke_result_type, E>;
5494 
5495  return has_value()
5496  ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
5497  : result_type(in_place_error, m_storage.storage.m_error);
5498 }
5499 
5500 template <typename E>
5501 template <typename Fn>
5503 auto RESULT_NS_IMPL::result<void, E>::map_impl(std::true_type, Fn&& fn)
5504  && -> result<void,E>
5505 {
5506  using result_type = result<void, E>;
5507 
5508  return has_value()
5509  ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
5510  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
5511 }
5512 
5513 template <typename E>
5514 template <typename Fn>
5516 auto RESULT_NS_IMPL::result<void, E>::map_impl(std::false_type, Fn&& fn)
5517  && -> result<detail::invoke_result_t<Fn>,E>
5518 {
5519  using invoke_result_type = detail::invoke_result_t<Fn>;
5520  using result_type = result<invoke_result_type, E>;
5521 
5522  return has_value()
5523  ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
5524  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
5525 }
5526 
5527 //=============================================================================
5528 // non-member functions : class : result
5529 //=============================================================================
5530 
5531 //-----------------------------------------------------------------------------
5532 // Comparison
5533 //-----------------------------------------------------------------------------
5534 
5535 template <typename T1, typename E1, typename T2, typename E2>
5536 inline RESULT_INLINE_VISIBILITY constexpr
5537 auto RESULT_NS_IMPL::operator==(const result<T1,E1>& lhs,
5538  const result<T2,E2>& rhs)
5539  noexcept -> bool
5540 {
5541  return (lhs.has_value() == rhs.has_value())
5542  ? (
5543  lhs.has_value()
5544  ? *lhs == *rhs
5545  : detail::extract_error(lhs) == detail::extract_error(rhs)
5546  )
5547  : false;
5548 }
5549 
5550 template <typename T1, typename E1, typename T2, typename E2>
5551 inline RESULT_INLINE_VISIBILITY constexpr
5552 auto RESULT_NS_IMPL::operator!=(const result<T1,E1>& lhs,
5553  const result<T2,E2>& rhs)
5554  noexcept -> bool
5555 {
5556  return (lhs.has_value() == rhs.has_value())
5557  ? (
5558  lhs.has_value()
5559  ? *lhs != *rhs
5560  : detail::extract_error(lhs) != detail::extract_error(rhs)
5561  )
5562  : true;
5563 }
5564 
5565 template <typename T1, typename E1, typename T2, typename E2>
5566 inline RESULT_INLINE_VISIBILITY constexpr
5567 auto RESULT_NS_IMPL::operator>=(const result<T1,E1>& lhs,
5568  const result<T2,E2>& rhs)
5569  noexcept -> bool
5570 {
5571  return (lhs.has_value() == rhs.has_value())
5572  ? (
5573  lhs.has_value()
5574  ? *lhs >= *rhs
5575  : detail::extract_error(lhs) >= detail::extract_error(rhs)
5576  )
5577  : static_cast<int>(static_cast<bool>(lhs)) >= static_cast<int>(static_cast<bool>(rhs));
5578 }
5579 
5580 template <typename T1, typename E1, typename T2, typename E2>
5581 inline RESULT_INLINE_VISIBILITY constexpr
5582 auto RESULT_NS_IMPL::operator<=(const result<T1,E1>& lhs,
5583  const result<T2,E2>& rhs)
5584  noexcept -> bool
5585 {
5586  return (lhs.has_value() == rhs.has_value())
5587  ? (
5588  lhs.has_value()
5589  ? *lhs <= *rhs
5590  : detail::extract_error(lhs) <= detail::extract_error(rhs)
5591  )
5592  : static_cast<int>(static_cast<bool>(lhs)) <= static_cast<int>(static_cast<bool>(rhs));
5593 }
5594 
5595 template <typename T1, typename E1, typename T2, typename E2>
5596 inline RESULT_INLINE_VISIBILITY constexpr
5597 auto RESULT_NS_IMPL::operator>(const result<T1,E1>& lhs,
5598  const result<T2,E2>& rhs)
5599  noexcept -> bool
5600 {
5601  return (lhs.has_value() == rhs.has_value())
5602  ? (
5603  lhs.has_value()
5604  ? *lhs > *rhs
5605  : detail::extract_error(lhs) > detail::extract_error(rhs)
5606  )
5607  : static_cast<int>(static_cast<bool>(lhs)) > static_cast<int>(static_cast<bool>(rhs));
5608 }
5609 
5610 template <typename T1, typename E1, typename T2, typename E2>
5611 inline RESULT_INLINE_VISIBILITY constexpr
5612 auto RESULT_NS_IMPL::operator<(const result<T1,E1>& lhs,
5613  const result<T2,E2>& rhs)
5614  noexcept -> bool
5615 {
5616  return (lhs.has_value() == rhs.has_value())
5617  ? (
5618  lhs.has_value()
5619  ? *lhs < *rhs
5620  : detail::extract_error(lhs) < detail::extract_error(rhs)
5621  )
5622  : static_cast<int>(static_cast<bool>(lhs)) < static_cast<int>(static_cast<bool>(rhs));
5623 }
5624 
5625 
5626 //-----------------------------------------------------------------------------
5627 
5628 template <typename E1, typename E2>
5629 inline RESULT_INLINE_VISIBILITY constexpr
5630 auto RESULT_NS_IMPL::operator==(const result<void,E1>& lhs,
5631  const result<void,E2>& rhs)
5632  noexcept -> bool
5633 {
5634  return lhs.has_value() == rhs.has_value()
5635  ? (
5636  lhs.has_value()
5637  ? true
5638  : detail::extract_error(lhs) == detail::extract_error(rhs)
5639  )
5640  : false;
5641 }
5642 
5643 template <typename E1, typename E2>
5644 inline RESULT_INLINE_VISIBILITY constexpr
5645 auto RESULT_NS_IMPL::operator!=(const result<void,E1>& lhs,
5646  const result<void,E2>& rhs)
5647  noexcept -> bool
5648 {
5649  return lhs.has_value() == rhs.has_value()
5650  ? (
5651  lhs.has_value()
5652  ? false
5653  : detail::extract_error(lhs) != detail::extract_error(rhs)
5654  )
5655  : true;
5656 }
5657 
5658 template <typename E1, typename E2>
5659 inline RESULT_INLINE_VISIBILITY constexpr
5660 auto RESULT_NS_IMPL::operator>=(const result<void,E1>& lhs,
5661  const result<void,E2>& rhs)
5662  noexcept -> bool
5663 {
5664  return lhs.has_value() == rhs.has_value()
5665  ? (
5666  lhs.has_value()
5667  ? true
5668  : detail::extract_error(lhs) >= detail::extract_error(rhs)
5669  )
5670  : static_cast<int>(static_cast<bool>(lhs)) >= static_cast<int>(static_cast<bool>(rhs));
5671 }
5672 
5673 template <typename E1, typename E2>
5674 inline RESULT_INLINE_VISIBILITY constexpr
5675 auto RESULT_NS_IMPL::operator<=(const result<void,E1>& lhs,
5676  const result<void,E2>& rhs)
5677  noexcept -> bool
5678 {
5679  return lhs.has_value() == rhs.has_value()
5680  ? (
5681  lhs.has_value()
5682  ? true
5683  : detail::extract_error(lhs) <= detail::extract_error(rhs)
5684  )
5685  : static_cast<int>(static_cast<bool>(lhs)) <= static_cast<int>(static_cast<bool>(rhs));
5686 }
5687 
5688 template <typename E1, typename E2>
5689 inline RESULT_INLINE_VISIBILITY constexpr
5690 auto RESULT_NS_IMPL::operator>(const result<void,E1>& lhs,
5691  const result<void,E2>& rhs)
5692  noexcept -> bool
5693 {
5694  return lhs.has_value() == rhs.has_value()
5695  ? (
5696  lhs.has_value()
5697  ? false
5698  : detail::extract_error(lhs) > detail::extract_error(rhs)
5699  )
5700  : static_cast<int>(static_cast<bool>(lhs)) > static_cast<int>(static_cast<bool>(rhs));
5701 }
5702 
5703 template <typename E1, typename E2>
5704 inline RESULT_INLINE_VISIBILITY constexpr
5705 auto RESULT_NS_IMPL::operator<(const result<void,E1>& lhs,
5706  const result<void,E2>& rhs)
5707  noexcept -> bool
5708 {
5709  return lhs.has_value() == rhs.has_value()
5710  ? (
5711  lhs.has_value()
5712  ? false
5713  : detail::extract_error(lhs) < detail::extract_error(rhs)
5714  )
5715  : static_cast<int>(static_cast<bool>(lhs)) < static_cast<int>(static_cast<bool>(rhs));
5716 }
5717 
5718 
5719 //-----------------------------------------------------------------------------
5720 
5721 template <typename T, typename E, typename U, typename>
5722 inline RESULT_INLINE_VISIBILITY constexpr
5723 auto RESULT_NS_IMPL::operator==(const result<T,E>& exp, const U& value)
5724  noexcept -> bool
5725 {
5726  return (exp.has_value() && *exp == value);
5727 }
5728 
5729 template <typename T, typename U, typename E, typename>
5730 inline RESULT_INLINE_VISIBILITY constexpr
5731 auto RESULT_NS_IMPL::operator==(const T& value, const result<U,E>& exp)
5732  noexcept -> bool
5733 {
5734  return (exp.has_value() && *exp == value);
5735 }
5736 
5737 template <typename T, typename E, typename U, typename>
5738 inline RESULT_INLINE_VISIBILITY constexpr
5739 auto RESULT_NS_IMPL::operator!=(const result<T,E>& exp, const U& value)
5740  noexcept -> bool
5741 {
5742  return exp.has_value() ? *exp != value : true;
5743 }
5744 
5745 template <typename T, typename U, typename E, typename>
5746 inline RESULT_INLINE_VISIBILITY constexpr
5747 auto RESULT_NS_IMPL::operator!=(const T& value, const result<U,E>& exp)
5748  noexcept -> bool
5749 {
5750  return exp.has_value() ? value != *exp : true;
5751 }
5752 
5753 template <typename T, typename E, typename U, typename>
5754 inline RESULT_INLINE_VISIBILITY constexpr
5755 auto RESULT_NS_IMPL::operator<=(const result<T,E>& exp, const U& value)
5756  noexcept -> bool
5757 {
5758  return exp.has_value() ? *exp <= value : false;
5759 }
5760 
5761 template <typename T, typename U, typename E, typename>
5762 inline RESULT_INLINE_VISIBILITY constexpr
5763 auto RESULT_NS_IMPL::operator<=(const T& value, const result<U,E>& exp)
5764  noexcept -> bool
5765 {
5766  return exp.has_value() ? value <= *exp : true;
5767 }
5768 
5769 template <typename T, typename E, typename U, typename>
5770 inline RESULT_INLINE_VISIBILITY constexpr
5771 auto RESULT_NS_IMPL::operator>=(const result<T,E>& exp, const U& value)
5772  noexcept -> bool
5773 {
5774  return exp.has_value() ? *exp >= value : true;
5775 }
5776 
5777 template <typename T, typename U, typename E, typename>
5778 inline RESULT_INLINE_VISIBILITY constexpr
5779 auto RESULT_NS_IMPL::operator>=(const T& value, const result<U,E>& exp)
5780  noexcept -> bool
5781 {
5782  return exp.has_value() ? value >= *exp : false;
5783 }
5784 
5785 template <typename T, typename E, typename U, typename>
5786 inline RESULT_INLINE_VISIBILITY constexpr
5787 auto RESULT_NS_IMPL::operator<(const result<T,E>& exp, const U& value)
5788  noexcept -> bool
5789 {
5790  return exp.has_value() ? *exp < value : false;
5791 }
5792 
5793 template <typename T, typename U, typename E, typename>
5794 inline RESULT_INLINE_VISIBILITY constexpr
5795 auto RESULT_NS_IMPL::operator<(const T& value, const result<U,E>& exp)
5796  noexcept -> bool
5797 {
5798  return exp.has_value() ? value < *exp : true;
5799 }
5800 
5801 template <typename T, typename E, typename U, typename>
5802 inline RESULT_INLINE_VISIBILITY constexpr
5803 auto RESULT_NS_IMPL::operator>(const result<T,E>& exp, const U& value)
5804  noexcept -> bool
5805 {
5806  return exp.has_value() ? *exp > value : false;
5807 }
5808 
5809 template <typename T, typename U, typename E, typename>
5810 inline RESULT_INLINE_VISIBILITY constexpr
5811 auto RESULT_NS_IMPL::operator>(const T& value, const result<U,E>& exp)
5812  noexcept -> bool
5813 {
5814  return exp.has_value() ? value > *exp : true;
5815 }
5816 
5817 //-----------------------------------------------------------------------------
5818 
5819 template <typename T, typename E, typename U>
5820 inline RESULT_INLINE_VISIBILITY constexpr
5821 auto RESULT_NS_IMPL::operator==(const result<T,E>& exp, const failure<U>& error)
5822  noexcept -> bool
5823 {
5824  return exp.has_error() ? detail::extract_error(exp) == error.error() : false;
5825 }
5826 
5827 template <typename T, typename U, typename E>
5828 inline RESULT_INLINE_VISIBILITY constexpr
5829 auto RESULT_NS_IMPL::operator==(const failure<T>& error, const result<E,U>& exp)
5830  noexcept -> bool
5831 {
5832  return exp.has_error() ? error.error() == detail::extract_error(exp) : false;
5833 }
5834 
5835 template <typename T, typename E, typename U>
5836 inline RESULT_INLINE_VISIBILITY constexpr
5837 auto RESULT_NS_IMPL::operator!=(const result<T,E>& exp, const failure<U>& error)
5838  noexcept -> bool
5839 {
5840  return exp.has_error() ? detail::extract_error(exp) != error.error() : true;
5841 }
5842 
5843 template <typename T, typename U, typename E>
5844 inline RESULT_INLINE_VISIBILITY constexpr
5845 auto RESULT_NS_IMPL::operator!=(const failure<T>& error, const result<E,U>& exp)
5846  noexcept -> bool
5847 {
5848  return exp.has_error() ? error.error() != detail::extract_error(exp) : true;
5849 }
5850 
5851 template <typename T, typename E, typename U>
5852 inline RESULT_INLINE_VISIBILITY constexpr
5853 auto RESULT_NS_IMPL::operator<=(const result<T,E>& exp, const failure<U>& error)
5854  noexcept -> bool
5855 {
5856  return exp.has_error() ? detail::extract_error(exp) <= error.error() : true;
5857 }
5858 
5859 template <typename T, typename U, typename E>
5860 inline RESULT_INLINE_VISIBILITY constexpr
5861 auto RESULT_NS_IMPL::operator<=(const failure<T>& error, const result<E,U>& exp)
5862  noexcept -> bool
5863 {
5864  return exp.has_error() ? error.error() <= detail::extract_error(exp) : false;
5865 }
5866 
5867 template <typename T, typename E, typename U>
5868 inline RESULT_INLINE_VISIBILITY constexpr
5869 auto RESULT_NS_IMPL::operator>=(const result<T,E>& exp, const failure<U>& error)
5870  noexcept -> bool
5871 {
5872  return exp.has_error() ? detail::extract_error(exp) >= error.error() : false;
5873 }
5874 
5875 template <typename T, typename U, typename E>
5876 inline RESULT_INLINE_VISIBILITY constexpr
5877 auto RESULT_NS_IMPL::operator>=(const failure<T>& error, const result<E,U>& exp)
5878  noexcept -> bool
5879 {
5880  return exp.has_error() ? error.error() >= detail::extract_error(exp) : true;
5881 }
5882 
5883 template <typename T, typename E, typename U>
5884 inline RESULT_INLINE_VISIBILITY constexpr
5885 auto RESULT_NS_IMPL::operator<(const result<T,E>& exp, const failure<U>& error)
5886  noexcept -> bool
5887 {
5888  return exp.has_error() ? detail::extract_error(exp) < error.error() : true;
5889 }
5890 
5891 template <typename T, typename U, typename E>
5892 inline RESULT_INLINE_VISIBILITY constexpr
5893 auto RESULT_NS_IMPL::operator<(const failure<T>& error, const result<E,U>& exp)
5894  noexcept -> bool
5895 {
5896  return exp.has_error() ? error.error() < detail::extract_error(exp) : false;
5897 }
5898 
5899 template <typename T, typename E, typename U>
5900 inline RESULT_INLINE_VISIBILITY constexpr
5901 auto RESULT_NS_IMPL::operator>(const result<T,E>& exp, const failure<U>& error)
5902  noexcept -> bool
5903 {
5904  return exp.has_error() ? detail::extract_error(exp) > error.error() : false;
5905 }
5906 
5907 template <typename T, typename U, typename E>
5908 inline RESULT_INLINE_VISIBILITY constexpr
5909 auto RESULT_NS_IMPL::operator>(const failure<T>& error, const result<E,U>& exp)
5910  noexcept -> bool
5911 {
5912  return exp.has_error() ? error.error() > detail::extract_error(exp) : true;
5913 }
5914 
5915 //-----------------------------------------------------------------------------
5916 // Utilities
5917 //-----------------------------------------------------------------------------
5918 
5919 template <typename T, typename E>
5921 auto RESULT_NS_IMPL::swap(result<T,E>& lhs, result<T,E>& rhs)
5922 #if __cplusplus >= 201703L
5927 #else
5930 #endif
5931  -> void
5932 {
5933  using std::swap;
5934 
5935  if (lhs.has_value() == rhs.has_value()) {
5936  if (lhs.has_value()) {
5937  swap(*lhs, *rhs);
5938  } else {
5939  auto& lhs_error = detail::result_error_extractor::get(lhs);
5940  auto& rhs_error = detail::result_error_extractor::get(rhs);
5941 
5942  swap(lhs_error, rhs_error);
5943  }
5944  // If both `result`s contain values, do nothing
5945  } else {
5946  auto temp = static_cast<result<T,E>&&>(lhs);
5947  lhs = static_cast<result<T,E>&&>(rhs);
5948  rhs = static_cast<result<T,E>&&>(temp);
5949  }
5950 }
5951 
5952 template <typename E>
5954 auto RESULT_NS_IMPL::swap(result<void,E>& lhs, result<void,E>& rhs)
5955 #if __cplusplus >= 201703L
5956  noexcept(std::is_nothrow_move_constructible<result<void,E>>::value &&
5959 #else
5960  noexcept(std::is_nothrow_move_constructible<result<void,E>>::value &&
5962 #endif
5963  -> void
5964 {
5965  using std::swap;
5966 
5967  if (lhs.has_value() == rhs.has_value()) {
5968  if (lhs.has_error()) {
5969  auto& lhs_error = detail::result_error_extractor::get(lhs);
5970  auto& rhs_error = detail::result_error_extractor::get(rhs);
5971 
5972  swap(lhs_error, rhs_error);
5973  }
5974  // If both `result`s contain values, do nothing
5975  } else {
5976  auto temp = static_cast<result<void,E>&&>(lhs);
5977  lhs = static_cast<result<void,E>&&>(rhs);
5978  rhs = static_cast<result<void,E>&&>(temp);
5979  }
5980 }
5981 
5982 #if defined(__clang__)
5983 # pragma clang diagnostic pop
5984 #endif
5985 
5986 #undef RESULT_NAMESPACE_INTERNAL
5987 #undef RESULT_NS_IMPL
5988 #undef RESULT_CPP14_CONSTEXPR
5989 #undef RESULT_CPP17_INLINE
5990 #undef RESULT_INLINE_VISIBILITY
5991 #undef RESULT_NODISCARD
5992 #undef RESULT_WARN_UNUSED
5993 
5994 #endif /* RESULT_RESULT_HPP */
cpp::bitwizeshift::failure::failure
failure(failure &&other)=default
Constructs this failure by moving the contents of an existing one.
cpp::bitwizeshift::result< void, E >::result
constexpr result(const result &other)=default
Copy constructs this result.
cpp::bitwizeshift::result< void, E >::expect
RESULT_CPP14_CONSTEXPR auto expect(String &&message) &&-> void
}
cpp::bitwizeshift::result< void, E >::result
constexpr result(result &&other)=default
Move constructs a result.
cpp::bitwizeshift::result< void, E >::map_error
RESULT_CPP14_CONSTEXPR auto map_error(Fn &&fn) &&-> result< void, detail::invoke_result_t< Fn, E && >>
Invokes the function fn with the error of this result as the argument.
cpp::bitwizeshift::failure::error
constexpr auto error() const &noexcept -> typename std::add_lvalue_reference< typename std::add_const< E >::type >::type
Gets the underlying error.
cpp::bitwizeshift::result< void, E >::value
RESULT_CPP14_CONSTEXPR auto value() &&-> void
Throws an exception if (*this) is in an error state.
cpp::bitwizeshift::result< void, E >::operator=
auto operator=(result &&other) -> result &=default
Move assigns the result stored in other.
RESULT_NODISCARD
#define RESULT_NODISCARD
Definition: result.hpp:85
cpp::bitwizeshift::bad_result_access::error
auto error() const &noexcept -> const E &
Gets the underlying error.
cpp::bitwizeshift::result< void, E >::error
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto error() &&noexcept(std::is_nothrow_constructible< E >::value &&std::is_nothrow_copy_constructible< E >::value) -> E
Returns the contained error, if one exists, or a default-constructed error value.
cpp::bitwizeshift::result::result
constexpr result() noexcept(std::is_nothrow_constructible< U >::value)
Default-constructs a result with the underlying value type active.
cpp::bitwizeshift::result::operator->
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto operator->() noexcept -> typename std::remove_reference< T >::type *
Retrieves a pointer to the contained value.
cpp::bitwizeshift::fail
constexpr RESULT_WARN_UNUSED auto fail(std::reference_wrapper< E > e) noexcept -> failure< E & >
Deduces a failure reference from a reverence_wrapper.
cpp::bitwizeshift::failure::error
RESULT_CPP14_CONSTEXPR auto error() &noexcept -> typename std::add_lvalue_reference< E >::type
Gets the underlying error.
cpp::bitwizeshift::in_place_error_t
A structure for representing in-place construction of an error type.
Definition: result.hpp:294
cpp::bitwizeshift::result::operator->
constexpr RESULT_WARN_UNUSED auto operator->() const noexcept -> typename std::remove_reference< typename std::add_const< T >::type >::type *
Retrieves a pointer to the contained value.
cpp::bitwizeshift::result::result
result(const result< T2, E2 > &other) noexcept(std::is_nothrow_constructible< T, const T2 & >::value &&std::is_nothrow_constructible< E, const E2 & >::value)
Converting copy constructor.
cpp::bitwizeshift::result< void, E >::operator=
auto operator=(failure< E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 && >::value) -> result &
Perfect-forwarded assignment.
cpp::bitwizeshift::result< void, E >::map_error
constexpr auto map_error(Fn &&fn) const &-> result< void, detail::invoke_result_t< Fn, const E & >>
Invokes the function fn with the error of this result as the argument.
cpp::bitwizeshift::is_failure
Definition: result.hpp:319
RESULT_NS_IMPL
#define RESULT_NS_IMPL
Definition: result.hpp:93
cpp::bitwizeshift::result::result
constexpr result(in_place_t, std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< T, std::initializer_list< U >, Args... >::value)
Constructs a result object that contains a value.
cpp::bitwizeshift::result::result
result(result< T2, E2 > &&other) noexcept(std::is_nothrow_constructible< T, T2 && >::value &&std::is_nothrow_constructible< E, E2 && >::value)
Converting move constructor.
cpp::bitwizeshift::result< void, E >::map
constexpr RESULT_WARN_UNUSED auto map(Fn &&fn) const &-> result< detail::invoke_result_t< Fn >, E >
Invokes the function fn if (*this) contains no value.
cpp::bitwizeshift::result< void, E >::result
constexpr result(in_place_error_t, Args &&... args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
Constructs a result object that contains an error.
cpp::bitwizeshift::result::result
constexpr result(in_place_t, Args &&... args) noexcept(std::is_nothrow_constructible< T, Args... >::value)
Constructs a result object that contains a value.
cpp::bitwizeshift::bad_result_access::error
auto error() &&noexcept -> E &&
Gets the underlying error.
cpp::bitwizeshift::swap
auto swap(failure< E > &lhs, failure< E > &rhs) noexcept(std::is_nothrow_move_constructible< E >::value) -> void
Swaps the contents of two failure values.
cpp::bitwizeshift::result< void, E >::operator=
auto operator=(const failure< E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 & >::value) -> result &
Perfect-forwarded assignment.
cpp::bitwizeshift::failure::operator=
RESULT_CPP14_CONSTEXPR auto operator=(const failure< E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 & >::value) -> failure &
Assigns the contents of other to this by copy conversion.
cpp::bitwizeshift::result< void, E >::error_or
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto error_or(U &&default_error) &&-> error_type
Returns the contained error if *this has an error, otherwise returns default_error.
cpp::bitwizeshift::fail
constexpr RESULT_WARN_UNUSED auto fail(Args &&...args) noexcept(std::is_nothrow_constructible< E, Args... >::value) -> failure< E >
Constructs a failure type from a series of arguments.
cpp::bitwizeshift::swap
auto swap(result< void, E > &lhs, result< void, E > &rhs) noexcept(std::is_nothrow_move_constructible< result< void, E >>::value &&std::is_nothrow_move_assignable< result< void, E >>::value) -> void
Swaps the contents of lhs with rhs.
cpp::bitwizeshift::result::operator=
auto operator=(U &&value) noexcept(std::is_nothrow_assignable< T, U >::value) -> result &
Perfect-forwarded assignment.
cpp::bitwizeshift::result< void, E >::expect
RESULT_CPP14_CONSTEXPR auto expect(String &&message) const &-> void
}
cpp::bitwizeshift::fail
constexpr RESULT_WARN_UNUSED auto fail(E &&e) noexcept(std::is_nothrow_constructible< typename std::decay< E >::type, E >::value) -> failure< typename std::decay< E >::type >
Deduces and constructs a failure type from e.
cpp::bitwizeshift::result::result
constexpr result(const result &other)=default
Copy constructs this result.
cpp::bitwizeshift::result::result
constexpr result(const failure< E2 > &e) noexcept(std::is_nothrow_constructible< E, const E2 & >::value)
Constructs the underlying error of this result.
cpp::bitwizeshift::failure::error
RESULT_CPP14_CONSTEXPR auto error() &&noexcept -> typename std::add_rvalue_reference< E >::type
Gets the underlying error.
cpp::bitwizeshift::result< void, E >::has_value
constexpr RESULT_WARN_UNUSED auto has_value() const noexcept -> bool
Returns true if *this contains a value.
cpp::bitwizeshift::result< void, E >::flat_map_error
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto flat_map_error(Fn &&fn) &&-> detail::invoke_result_t< Fn, E && >
Invokes the function fn with the error of this result as the argument.
cpp::bitwizeshift::fail
constexpr RESULT_WARN_UNUSED auto fail(std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U >, Args... >::value) -> failure< E >
Constructs a failure type from an initializer list and series of arguments.
cpp::bitwizeshift::result::value_or
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto value_or(U &&default_value) &&-> typename std::remove_reference< T >::type
Returns the contained value if *this has a value, otherwise returns default_value.
cpp::bitwizeshift::result< void, E >::result
result(result< U, E2 > &&other) noexcept(std::is_nothrow_constructible< E, E2 && >::value)
Converting move constructor.
cpp::bitwizeshift::result::result
constexpr result(in_place_error_t, Args &&... args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
Constructs a result object that contains an error.
cpp::bitwizeshift::failure::failure
constexpr failure(E2 &&error) noexcept(std::is_nothrow_constructible< E, E2 >::value)
Constructs a failure from the given error.
cpp::bitwizeshift::result< void, E >::flat_map
constexpr RESULT_WARN_UNUSED auto flat_map(Fn &&fn) const &-> detail::invoke_result_t< Fn >
Invokes the function fn if (*this) contains no value.
RESULT_NAMESPACE_INTERNAL
#define RESULT_NAMESPACE_INTERNAL
Definition: result.hpp:91
cpp::bitwizeshift::result< void, E >::operator=
auto operator=(const result &other) -> result &=default
Copy assigns the result stored in other.
cpp::bitwizeshift::result< void, E >::operator=
auto operator=(result< void, E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 && >::value) -> result &
Move-converts the state of other.
cpp::bitwizeshift::failure::failure
constexpr failure(failure< E2 > &&other) noexcept(std::is_nothrow_constructible< E, E2 && >::value)
Constructs this failure by move-converting other.
cpp::bitwizeshift::result::operator=
auto operator=(result &&other) -> result &=default
Move assigns the result stored in other.
cpp::bitwizeshift::result::operator=
auto operator=(failure< E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 && >::value) -> result &
Perfect-forwarded assignment.
cpp::bitwizeshift::bad_result_access::bad_result_access
bad_result_access(const char *what_arg, E2 &&error)
Constructs this exception using the underlying error type for the error and a message.
cpp::bitwizeshift::result::error
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto error() &&noexcept(std::is_nothrow_constructible< E >::value &&std::is_nothrow_move_constructible< E >::value) -> E
Returns the contained error, if one exists, or a default-constructed error value.
cpp::bitwizeshift::result< void, E >::result
constexpr result(in_place_error_t, std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U >, Args... >::value)
Constructs a result object that contains an error.
cpp::bitwizeshift::is_result
Definition: result.hpp:324
cpp::bitwizeshift::result< void, E >::result
constexpr result(in_place_t) noexcept
Constructs a result object in a value state.
RESULT_CPP17_INLINE
#define RESULT_CPP17_INLINE
Definition: result.hpp:59
cpp::bitwizeshift::result< void, E >::operator bool
constexpr RESULT_WARN_UNUSED operator bool() const noexcept
Contextually convertible to true if *this does not contain an error.
cpp::bitwizeshift::result< void, E >::map
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto map(Fn &&fn) &&-> result< detail::invoke_result_t< Fn >, E >
Invokes the function fn if (*this) contains no value.
cpp::bitwizeshift::failure::failure
failure()=default
Constructs a failure via default construction.
cpp::bitwizeshift::failure::failure
constexpr failure(in_place_t, Args &&...args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
Constructs a failure by delegating construction to the underlying constructor.
cpp::bitwizeshift::result< void, E >::result
constexpr result() noexcept
Constructs a result object in a value state.
cpp::bitwizeshift::bad_result_access::bad_result_access
bad_result_access(const std::string &what_arg, E2 &&error)
Constructs this exception using the underlying error type for the error and a message.
RESULT_INLINE_VISIBILITY
#define RESULT_INLINE_VISIBILITY
Definition: result.hpp:69
cpp::bitwizeshift::result::operator*
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto operator*() &noexcept -> typename std::add_lvalue_reference< T >::type
Retrieves a reference to the contained value.
cpp::bitwizeshift::result< void, E >::result
result(const result< U, E2 > &other) noexcept(std::is_nothrow_constructible< E, const E2 & >::value)
Converting copy constructor.
cpp::bitwizeshift::failure::failure
failure(const failure &other)=default
Constructs this failure by copying the contents of an existing one.
cpp::bitwizeshift::result::value
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto value() &&-> typename std::add_rvalue_reference< T >::type
Returns a reference to the contained value.
cpp::bitwizeshift::result::operator=
auto operator=(result< T2, E2 > &&other) noexcept(std::is_nothrow_assignable< T, T2 && >::value &&std::is_nothrow_assignable< E, E2 && >::value) -> result &
Move-converts the state of other.
cpp::bitwizeshift::result< void, E >::result
constexpr result(failure< E2 > &&e) noexcept(std::is_nothrow_constructible< E, E2 && >::value)
Constructs the underlying error of this result.
cpp::bitwizeshift::swap
auto swap(result< T, E > &lhs, result< T, E > &rhs) noexcept(std::is_nothrow_move_constructible< result< T, E >>::value &&std::is_nothrow_move_assignable< result< T, E >>::value) -> void
Swaps the contents of lhs with rhs.
cpp::bitwizeshift::result< void, E >::and_then
constexpr RESULT_WARN_UNUSED auto and_then(U &&value) const -> result< typename std::decay< U >::type, E >
Returns a result containing value if this result contains a value, otherwise returns a result contain...
cpp::bitwizeshift::result::result
constexpr result(in_place_error_t, std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U >, Args... >::value)
Constructs a result object that contains an error.
RESULT_CPP14_CONSTEXPR
#define RESULT_CPP14_CONSTEXPR
Definition: result.hpp:53
cpp::bitwizeshift::bad_result_access::error
auto error() const &&noexcept -> const E &&
Gets the underlying error.
cpp::bitwizeshift::bad_result_access::error
auto error() &noexcept -> E &
Gets the underlying error.
cpp::bitwizeshift::result< void, E >::flat_map_error
constexpr RESULT_WARN_UNUSED auto flat_map_error(Fn &&fn) const &-> detail::invoke_result_t< Fn, const E & >
Invokes the function fn with the error of this result as the argument.
RESULT_WARN_UNUSED
#define RESULT_WARN_UNUSED
Definition: result.hpp:84
cpp::bitwizeshift::result::result
constexpr result(result &&other)=default
Move constructs a result.
cpp::bitwizeshift::result::operator=
auto operator=(const result< T2, E2 > &other) noexcept(std::is_nothrow_assignable< T, const T2 & >::value &&std::is_nothrow_assignable< E, const E2 & >::value) -> result &
Copy-converts the state of other.
cpp::bitwizeshift::in_place_t
A structure for representing in-place construction.
Definition: result.hpp:282
cpp::bitwizeshift::failure::error
constexpr auto error() const &&noexcept -> typename std::add_rvalue_reference< typename std::add_const< E >::type >::type
Gets the underlying error.
cpp::bitwizeshift::result< void, E >::error
constexpr RESULT_WARN_UNUSED auto error() const &noexcept(std::is_nothrow_constructible< E >::value &&std::is_nothrow_copy_constructible< E >::value) -> E
Returns the contained error, if one exists, or a default-constructed error value.
cpp::bitwizeshift::failure::operator=
auto operator=(failure &&other) -> failure &=default
Assigns the contents of other to this by move-assignment.
cpp::bitwizeshift::result< void, E >::has_error
constexpr RESULT_WARN_UNUSED auto has_error() const noexcept -> bool
Returns true if *this contains an error.
cpp::bitwizeshift::result< void, E >::flat_map
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto flat_map(Fn &&fn) &&-> detail::invoke_result_t< Fn >
Invokes the function fn if (*this) contains no value.
cpp::bitwizeshift::result::result
constexpr result(failure< E2 > &&e) noexcept(std::is_nothrow_constructible< E, E2 && >::value)
Constructs the underlying error of this result.
cpp::bitwizeshift::failure::failure
constexpr failure(const failure< E2 > &other) noexcept(std::is_nothrow_constructible< E, const E2 & >::value)
Constructs this failure by copy-converting other.
cpp::bitwizeshift::failure::operator=
RESULT_CPP14_CONSTEXPR auto operator=(failure< E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 && >::value) -> failure &
Assigns the contents of other to this by move conversion.
cpp::bitwizeshift::result< void, E >::result
constexpr result(const failure< E2 > &e) noexcept(std::is_nothrow_constructible< E, const E2 & >::value)
Constructs the underlying error of this result.
cpp::bitwizeshift::failure::operator=
auto operator=(const failure &other) -> failure &=default
Assigns the contents of other to this by copy-assignment.
cpp::bitwizeshift::bad_result_access::bad_result_access
bad_result_access(E2 &&error)
Constructs this exception using the underlying error type for the error type.
cpp::bitwizeshift::result::result
constexpr result(U &&value) noexcept(std::is_nothrow_constructible< T, U >::value)
Constructs a result object that contains a value.
cpp::bitwizeshift::result::operator=
auto operator=(const result &other) -> result &=default
Copy assigns the result stored in other.
cpp::bitwizeshift::failure::failure
constexpr failure(in_place_t, std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U >, Args... >::value)
Constructs a failure by delegating construction to the underlying constructor.
cpp::bitwizeshift::result< void, E >::error_or
constexpr RESULT_WARN_UNUSED auto error_or(U &&default_error) const &-> error_type
Returns the contained error if *this has an error, otherwise returns default_error.
cpp::bitwizeshift::result< void, E >::value
RESULT_CPP14_CONSTEXPR auto value() const &-> void
Throws an exception if (*this) is in an error state.
cpp::bitwizeshift::result< void, E >::operator=
auto operator=(const result< void, E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 & >::value) -> result &
Copy-converts the state of other.
cpp::bitwizeshift::failure::operator=
RESULT_CPP14_CONSTEXPR auto operator=(E2 &&error) noexcept(std::is_nothrow_assignable< E, E2 >::value||std::is_lvalue_reference< E >::value) -> failure &
Assigns the value of error to this failure through move-assignment.
cpp::bitwizeshift::result::operator=
auto operator=(const failure< E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 & >::value) -> result &
Perfect-forwarded assignment.