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  template <typename String,
2381  typename = typename std::enable_if<(
2382  std::is_convertible<String,const std::string&>::value &&
2383  std::is_copy_constructible<E>::value
2384  )>::type>
2385  RESULT_CPP14_CONSTEXPR auto expect(String&& message) const & -> void;
2386  template <typename String,
2387  typename = typename std::enable_if<(
2388  std::is_convertible<String,const std::string&>::value &&
2389  std::is_move_constructible<E>::value
2390  )>::type>
2391  RESULT_CPP14_CONSTEXPR auto expect(String&& message) && -> void;
2392  /// \}
2393 
2394  //-------------------------------------------------------------------------
2395  // Monadic Functionalities
2396  //-------------------------------------------------------------------------
2397  public:
2398 
2399  /// \{
2400  /// \brief Returns the contained value if `*this` has a value,
2401  /// otherwise returns \p default_value.
2402  ///
2403  /// ### Examples
2404  ///
2405  /// Basic Usage:
2406  ///
2407  /// ```cpp
2408  /// auto r = cpp::result<int,int>{42};
2409  /// assert(r.value_or(0) == 42);
2410  ///
2411  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2412  /// assert(r.value_or(0) == 0);
2413  /// ```
2414  ///
2415  /// \param default_value the value to use in case `*this` contains an error
2416  /// \return the contained value or \p default_value
2417  template <typename U>
2419  constexpr auto value_or(U&& default_value)
2420  const & -> typename std::remove_reference<T>::type;
2421  template <typename U>
2423  RESULT_CPP14_CONSTEXPR auto value_or(U&& default_value)
2424  && -> typename std::remove_reference<T>::type;
2425  /// \}
2426 
2427  /// \{
2428  /// \brief Returns the contained error if `*this` has an error,
2429  /// otherwise returns \p default_error.
2430  ///
2431  /// ### Examples
2432  ///
2433  /// Basic Usage:
2434  ///
2435  /// ```cpp
2436  /// auto r = cpp::result<int,int>{42};
2437  /// assert(r.error_or(0) == cpp::fail(0));
2438  ///
2439  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2440  /// assert(r.error_or(0) == cpp::fail(42));
2441  /// ```
2442  ///
2443  /// \param default_error the error to use in case `*this` is empty
2444  /// \return the contained value or \p default_error
2445  template <typename U>
2447  constexpr auto error_or(U&& default_error) const & -> error_type;
2448  template <typename U>
2450  RESULT_CPP14_CONSTEXPR auto error_or(U&& default_error) && -> error_type;
2451  /// \}
2452 
2453  //-------------------------------------------------------------------------
2454 
2455  /// \brief Returns a result containing \p value if this result contains
2456  /// a value, otherwise returns a result containing the current
2457  /// error.
2458  ///
2459  /// ### Examples
2460  ///
2461  /// Basic Usage:
2462  ///
2463  /// ```cpp
2464  /// auto r = cpp::result<int,int>{42};
2465  /// assert(r.and_then(100) == 100);
2466  ///
2467  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2468  /// assert(r.and_then(100) == cpp::fail(42));
2469  /// ```
2470  ///
2471  /// \param value the value to return as a result
2472  /// \return a result of \p value if this contains a value
2473  template <typename U>
2475  constexpr auto and_then(U&& value) const -> result<typename std::decay<U>::type,E>;
2476 
2477  /// \{
2478  /// \brief Invokes the function \p fn with the value of this result as
2479  /// the argument
2480  ///
2481  /// If this result contains an error, a result of the error is returned
2482  ///
2483  /// The function being called must return a `result` type or the program
2484  /// is ill-formed
2485  ///
2486  /// If this is called on an rvalue of `result` which contains an error,
2487  /// the returned `result` is constructed from an rvalue of that error.
2488  ///
2489  /// ### Examples
2490  ///
2491  /// Basic Usage:
2492  ///
2493  /// ```cpp
2494  /// auto to_string(int) -> cpp::result<std::string,int>;
2495  /// auto r = cpp::result<int,int>{42};
2496  /// assert(r.flat_map(to_string) == "42");
2497  ///
2498  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2499  /// assert(r.flat_map(to_string) == cpp::fail(42));
2500  /// ```
2501  ///
2502  /// \param fn the function to invoke with this
2503  /// \return The result of the function being called
2504  template <typename Fn>
2506  constexpr auto flat_map(Fn&& fn) const & -> detail::invoke_result_t<Fn, const T&>;
2507  template <typename Fn>
2509  RESULT_CPP14_CONSTEXPR auto flat_map(Fn&& fn) && -> detail::invoke_result_t<Fn, T&&>;
2510  /// \}
2511 
2512  /// \{
2513  /// \brief Invokes the function \p fn with the value of this result as
2514  /// the argument
2515  ///
2516  /// If this result is an error, the result of this function is that
2517  /// error. Otherwise this function wraps the result and returns it as an
2518  /// result.
2519  ///
2520  /// If this is called on an rvalue of `result` which contains an error,
2521  /// the returned `result` is constructed from an rvalue of that error.
2522  ///
2523  /// ### Examples
2524  ///
2525  /// Basic Usage:
2526  ///
2527  /// ```cpp
2528  /// auto to_string(int) -> std::string;
2529  /// auto r = cpp::result<int,int>{42};
2530  /// assert(r.map(to_string) == "42");
2531  ///
2532  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2533  /// assert(r.map(to_string) == cpp::fail(42));
2534  /// ```
2535  ///
2536  /// \param fn the function to invoke with this
2537  /// \return The result result of the function invoked
2538  template <typename Fn>
2540  constexpr auto map(Fn&& fn) const & -> result<detail::invoke_result_t<Fn,const T&>,E>;
2541  template <typename Fn>
2543  RESULT_CPP14_CONSTEXPR auto map(Fn&& fn) && -> result<detail::invoke_result_t<Fn,T&&>,E>;
2544  /// \}
2545 
2546  /// \{
2547  /// \brief Invokes the function \p fn with the error of this result as
2548  /// the argument
2549  ///
2550  /// If this result contains a value, the result of this function is that
2551  /// value. Otherwise the function is called with that error and returns the
2552  /// result as a result.
2553  ///
2554  /// If this is called on an rvalue of `result` which contains a value,
2555  /// the returned `result` is constructed from an rvalue of that value.
2556  ///
2557  /// ### Examples
2558  ///
2559  /// Basic Usage:
2560  ///
2561  /// ```cpp
2562  /// auto to_string(int) -> std::string;
2563  /// auto r = cpp::result<int,int>{42};
2564  /// assert(r.map_error(to_string) == 42);
2565  ///
2566  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2567  /// assert(r.map_error(to_string) == cpp::fail("42"));
2568  ///
2569  /// auto r = cpp::result<std::string,int>{};
2570  /// auto s = r.map(std::string::size); // 's' contains 'result<size_t,int>'
2571  /// ```
2572  ///
2573  /// \param fn the function to invoke with this
2574  /// \return The result result of the function invoked
2575  template <typename Fn>
2577  constexpr auto map_error(Fn&& fn)
2578  const & -> result<T, detail::invoke_result_t<Fn,const E&>>;
2579  template <typename Fn>
2581  RESULT_CPP14_CONSTEXPR auto map_error(Fn&& fn)
2582  && -> result<T, detail::invoke_result_t<Fn,E&&>>;
2583  /// \}
2584 
2585  /// \{
2586  /// \brief Invokes the function \p fn with the error of this result as
2587  /// the argument
2588  ///
2589  /// If this result contains a value, a result of the value is returned
2590  ///
2591  /// The function being called must return a `result` type or the program
2592  /// is ill-formed
2593  ///
2594  /// If this is called on an rvalue of `result` which contains an error,
2595  /// the returned `result` is constructed from an rvalue of that error.
2596  ///
2597  /// ### Examples
2598  ///
2599  /// Basic Usage:
2600  ///
2601  /// ```cpp
2602  /// auto to_string(int) -> cpp::result<int,std::string>;
2603  /// auto r = cpp::result<int,int>{42};
2604  /// assert(r.flat_map(to_string) == 42);
2605  ///
2606  /// auto r = cpp::result<int,int>{cpp::fail(42)};
2607  /// assert(r.flat_map(to_string) == cpp::fail("42"));
2608  /// ```
2609  ///
2610  /// \param fn the function to invoke with this
2611  /// \return The result of the function being called
2612  template <typename Fn>
2614  constexpr auto flat_map_error(Fn&& fn)
2615  const & -> detail::invoke_result_t<Fn, const E&>;
2616  template <typename Fn>
2618  RESULT_CPP14_CONSTEXPR auto flat_map_error(Fn&& fn)
2619  && -> detail::invoke_result_t<Fn, E&&>;
2620  /// \}
2621 
2622  //-------------------------------------------------------------------------
2623  // Private Members
2624  //-------------------------------------------------------------------------
2625  private:
2626 
2627  detail::result_storage<T,E> m_storage;
2628 
2629  //-------------------------------------------------------------------------
2630  // Private Monadic Functions
2631  //-------------------------------------------------------------------------
2632  private:
2633 
2634  /// \{
2635  /// \brief Map implementations for void and non-void functions
2636  ///
2637  /// \param fn the function
2638  template <typename Fn>
2639  constexpr auto map_impl(std::true_type, Fn&& fn) const & -> result<void,E>;
2640  template <typename Fn>
2641  constexpr auto map_impl(std::false_type, Fn&& fn) const & -> result<detail::invoke_result_t<Fn,const T&>,E>;
2642  template <typename Fn>
2643  RESULT_CPP14_CONSTEXPR auto map_impl(std::true_type, Fn&& fn) && -> result<void,E>;
2644  template <typename Fn>
2645  RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn,T&&>,E>;
2646  /// \}
2647  };
2648 
2649  //===========================================================================
2650  // class : result<void,E>
2651  //===========================================================================
2652 
2653  /////////////////////////////////////////////////////////////////////////////
2654  /// \brief Partial specialization of `result<void, E>`
2655  ///
2656  /// \tparam E the underlying error type
2657  /////////////////////////////////////////////////////////////////////////////
2658  template <typename E>
2659  class RESULT_NODISCARD result<void,E>
2660  {
2661  // Type requirements
2662 
2663  static_assert(
2664  !std::is_void<typename std::decay<E>::type>::value,
2665  "It is ill-formed for E to be (possibly CV-qualified) void type"
2666  );
2667  static_assert(
2668  !std::is_abstract<E>::value,
2669  "It is ill-formed for E to be abstract type"
2670  );
2671  static_assert(
2672  !is_failure<typename std::decay<E>::type>::value,
2673  "It is ill-formed for E to be a (possibly CV-qualified) 'failure' type"
2674  );
2675  static_assert(
2676  !std::is_reference<E>::value,
2677  "It is ill-formed for E to be a reference type. "
2678  "Only T types may be lvalue references"
2679  );
2680 
2681  // Friendship
2682 
2683  friend detail::result_error_extractor;
2684 
2685  template <typename T2, typename E2>
2686  friend class result;
2687 
2688  //-------------------------------------------------------------------------
2689  // Public Member Types
2690  //-------------------------------------------------------------------------
2691  public:
2692 
2693  using value_type = void; ///< The value type of this result
2694  using error_type = E; ///< The error type of this result
2695  using failure_type = failure<E>; ///< The failure type
2696 
2697  template <typename U>
2698  using rebind = result<U,E>; ///< Rebinds the result type
2699 
2700  //-------------------------------------------------------------------------
2701  // Constructor / Assignment
2702  //-------------------------------------------------------------------------
2703  public:
2704 
2705  /// \brief Constructs a `result` object in a value state
2706  ///
2707  /// ### Examples
2708  ///
2709  /// Basic Usage:
2710  ///
2711  /// ```cpp
2712  /// auto r = cpp::result<void,int>{};
2713  /// ```
2714  constexpr result() noexcept;
2715 
2716  /// \brief Copy constructs this result
2717  ///
2718  /// If other contains an error, constructs an object that contains a copy
2719  /// of that error.
2720  ///
2721  /// \note This constructor is defined as deleted if
2722  /// `std::is_copy_constructible<E>::value` is `false`
2723  ///
2724  /// \note This constructor is defined as trivial if both
2725  /// `std::is_trivially_copy_constructible<E>::value` are `true`
2726  ///
2727  /// ### Examples
2728  ///
2729  /// Basic Usage:
2730  ///
2731  /// ```cpp
2732  /// const auto r = cpp::result<void,int>{};
2733  /// const auto s = r;
2734  /// ```
2735  ///
2736  /// \param other the result to copy
2737  constexpr result(const result& other) = default;
2738 
2739  /// \brief Move constructs a result
2740  ///
2741  /// If other contains an error, move-constructs this result from that
2742  /// error.
2743  ///
2744  /// \note This constructor is defined as deleted if
2745  /// `std::is_move_constructible<E>::value` is `false`
2746  ///
2747  /// \note This constructor is defined as trivial if both
2748  /// `std::is_trivially_move_constructible<E>::value` are `true`
2749  ///
2750  /// ### Examples
2751  ///
2752  /// Basic Usage:
2753  ///
2754  /// ```cpp
2755  /// auto r = cpp::result<void,std::string>{};
2756  /// auto s = std::move(r);
2757  /// ```
2758  ///
2759  /// \param other the result to move
2760  constexpr result(result&& other) = default;
2761 
2762  /// \brief Converting copy constructor
2763  ///
2764  /// If \p other contains a value, constructs a result object that is not
2765  /// in an error state -- ignoring the value.
2766  ///
2767  /// If \p other contains an error, constructs a result object that
2768  /// contains an error, initialized as if direct-initializing
2769  /// (but not direct-list-initializing) an object of type `E`.
2770  ///
2771  /// \note This constructor does not participate in overload resolution
2772  /// unless the following conditions are met:
2773  /// - `std::is_constructible_v<E, const E2&>` is `true`
2774  ///
2775  /// ### Examples
2776  ///
2777  /// Basic Usage:
2778  ///
2779  /// ```cpp
2780  /// const auto r = cpp::result<int,int>{42};
2781  /// const auto s = cpp::result<void,int>{r};
2782  /// ```
2783  ///
2784  /// \param other the other type to convert
2785  template <typename U, typename E2,
2786  typename = typename std::enable_if<std::is_constructible<E,E2>::value>::type>
2787  explicit result(const result<U,E2>& other)
2788  noexcept(std::is_nothrow_constructible<E,const E2&>::value);
2789 
2790  /// \brief Converting move constructor
2791  ///
2792  /// If \p other contains an error, constructs a result object that
2793  /// contains an error, initialized as if direct-initializing
2794  /// (but not direct-list-initializing) an object of type E&&.
2795  ///
2796  /// \note This constructor does not participate in overload resolution
2797  /// unless the following conditions are met:
2798  /// - `std::is_constructible_v<E, const E2&>` is `true`
2799  ///
2800  /// ### Examples
2801  ///
2802  /// Basic Usage:
2803  ///
2804  /// ```cpp
2805  /// auto r = cpp::result<int,std::string>{42};
2806  /// auto s = cpp::result<void,std::string>{
2807  /// std::move(r)
2808  /// };
2809  /// ```
2810  ///
2811  /// \param other the other type to convert
2812  template <typename U, typename E2,
2813  typename = typename std::enable_if<std::is_constructible<E,E2>::value>::type>
2814  explicit result(result<U,E2>&& other)
2815  noexcept(std::is_nothrow_constructible<E,E2&&>::value);
2816 
2817  //-------------------------------------------------------------------------
2818 
2819  /// \brief Constructs a result object in a value state
2820  ///
2821  /// This constructor exists primarily for symmetry with the `result<T,E>`
2822  /// constructor. Unlike the `T` overload, no variadic arguments may be
2823  /// supplied.
2824  ///
2825  /// ### Examples
2826  ///
2827  /// Basic Usage:
2828  ///
2829  /// ```cpp
2830  /// auto r = cpp::result<void,std::string>{cpp::in_place};
2831  /// ```
2832  constexpr explicit result(in_place_t) noexcept;
2833 
2834  /// \brief Constructs a result object that contains an error
2835  ///
2836  /// the value is initialized as if direct-initializing (but not
2837  /// direct-list-initializing) an object of type `E` from the arguments
2838  /// `std::forward<Args>(args)...`
2839  ///
2840  /// ### Examples
2841  ///
2842  /// Basic Usage:
2843  ///
2844  /// ```cpp
2845  /// auto r = cpp::result<void,std::string>{
2846  /// cpp::in_place_error, "Hello world"
2847  /// };
2848  /// ```
2849  ///
2850  /// \param args the arguments to pass to `E`'s constructor
2851  template <typename...Args,
2852  typename = typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
2853  constexpr explicit result(in_place_error_t, Args&&... args)
2854  noexcept(std::is_nothrow_constructible<E, Args...>::value);
2855 
2856  /// \brief Constructs a result object that contains an error
2857  ///
2858  /// The value is initialized as if direct-initializing (but not
2859  /// direct-list-initializing) an object of type `E` from the arguments
2860  /// `std::forward<std::initializer_list<U>>(ilist)`,
2861  /// `std::forward<Args>(args)...`
2862  ///
2863  /// ### Examples
2864  ///
2865  /// Basic Usage:
2866  ///
2867  /// ```cpp
2868  /// auto r = cpp::result<void,std::string>{
2869  /// cpp::in_place_error, {'H','e','l','l','o'}
2870  /// };
2871  /// ```
2872  ///
2873  /// \param ilist An initializer list of entries to forward
2874  /// \param args the arguments to pass to Es constructor
2875  template <typename U, typename...Args,
2876  typename = typename std::enable_if<std::is_constructible<E, std::initializer_list<U>&, Args...>::value>::type>
2877  constexpr explicit result(in_place_error_t,
2878  std::initializer_list<U> ilist,
2879  Args&&...args)
2881 
2882  //-------------------------------------------------------------------------
2883 
2884  /// \{
2885  /// \brief Constructs the underlying error of this result
2886  ///
2887  /// \note This constructor only participates in overload resolution if
2888  /// `E` is constructible from \p e
2889  ///
2890  /// ### Examples
2891  ///
2892  /// Basic Usage:
2893  ///
2894  /// ```cpp
2895  /// cpp::result<void,int> r = cpp::fail(42);
2896  ///
2897  /// auto get_error_result() -> cpp::result<void,std::string> {
2898  /// return cpp::fail("hello world!");
2899  /// }
2900  /// ```
2901  ///
2902  /// \param e the failure error
2903  template <typename E2,
2904  typename = typename std::enable_if<std::is_constructible<E,const E2&>::value>::type>
2905  constexpr /* implicit */ result(const failure<E2>& e)
2906  noexcept(std::is_nothrow_constructible<E,const E2&>::value);
2907  template <typename E2,
2908  typename = typename std::enable_if<std::is_constructible<E,E2&&>::value>::type>
2909  constexpr /* implicit */ result(failure<E2>&& e)
2910  noexcept(std::is_nothrow_constructible<E,E2&&>::value);
2911  /// \}
2912 
2913  //-------------------------------------------------------------------------
2914 
2915  /// \brief Copy assigns the result stored in \p other
2916  ///
2917  /// \note The function does not participate in overload resolution unless
2918  /// - `std::is_nothrow_copy_constructible_v<E>` is `true`
2919  /// this restriction guarantees that no 'valueless_by_exception` state
2920  /// may occur.
2921  ///
2922  /// \note This assignment operator is defined as trivial if the following
2923  /// conditions are all `true`:
2924  /// - `std::is_trivially_copy_constructible<E>::value`
2925  /// - `std::is_trivially_copy_assignable<E>::value`
2926  /// - `std::is_trivially_destructible<E>::value`
2927  ///
2928  /// \param other the other result to copy
2929  auto operator=(const result& other) -> result& = default;
2930 
2931  /// \brief Move assigns the result stored in \p other
2932  ///
2933  /// \note The function does not participate in overload resolution unless
2934  /// - `std::is_nothrow_copy_constructible_v<E>` is `true`
2935  /// this restriction guarantees that no 'valueless_by_exception` state
2936  /// may occur.
2937  ///
2938  /// \note This assignment operator is defined as trivial if the following
2939  /// conditions are all `true`:
2940  /// - `std::is_trivially_move_constructible<E>::value`
2941  /// - `std::is_trivially_move_assignable<E>::value`
2942  /// - `std::is_trivially_destructible<E>::value`
2943  ///
2944  /// \param other the other result to copy
2945  auto operator=(result&& other) -> result& = default;
2946 
2947  /// \brief Copy-converts the state of \p other
2948  ///
2949  /// If both this and \p other contain an error, the underlying error is
2950  /// assigned through copy-assignment.
2951  ///
2952  /// If \p other contains a value state, this result is constructed in a
2953  /// value state.
2954  ///
2955  /// If \p other contans an error state, and this contains a value state,
2956  /// the underlying error is constructed through copy-construction.
2957  ///
2958  /// \note The function does not participate in overload resolution unless
2959  /// - `std::is_nothrow_constructible_v<E, const E2&>`,
2960  /// `std::is_assignable_v<E&, const E2&>` are all `true`.
2961  ///
2962  /// \param other the other result object to convert
2963  /// \return reference to `(*this)`
2964  template <typename E2,
2965  typename = typename std::enable_if<std::is_nothrow_constructible<E,const E2&>::value &&
2966  std::is_assignable<E&,const E2&>::value>::type>
2967  auto operator=(const result<void,E2>& other)
2968  noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> result&;
2969 
2970  /// \brief Move-converts the state of \p other
2971  ///
2972  /// If both this and \p other contain an error, the underlying error is
2973  /// assigned through move-assignment.
2974  ///
2975  /// If \p other contains a value state, this result is constructed in a
2976  /// value state.
2977  ///
2978  /// If \p other contans an error state, and this contains a value state,
2979  /// the underlying error is constructed through move-construction.
2980  ///
2981  /// \note The function does not participate in overload resolution unless
2982  /// - `std::is_nothrow_constructible_v<E, E2&&>`,
2983  /// `std::is_assignable_v<E&, E2&&>` are all `true`.
2984  ///
2985  /// \param other the other result object to convert
2986  /// \return reference to `(*this)`
2987  template <typename E2,
2988  typename = typename std::enable_if<std::is_nothrow_constructible<E,E2&&>::value &&
2989  std::is_assignable<E&,E2&&>::value>::type>
2990  auto operator=(result<void,E2>&& other)
2991  noexcept(std::is_nothrow_assignable<E, E2&&>::value) -> result&;
2992 
2993  /// \{
2994  /// \brief Perfect-forwarded assignment
2995  ///
2996  /// Depending on whether `*this` contains an error before the call, the
2997  /// contained error is either direct-initialized via forwarding the error,
2998  /// or assigned from forwarding the error
2999  ///
3000  /// \note The function does not participate in overload resolution unless
3001  /// - `std::is_nothrow_constructible_v<E, E2>` is `true`, and
3002  /// - `std::is_assignable_v<E&, E2>` is `true`
3003  ///
3004  /// \param other the failure value to assign to this
3005  /// \return reference to `(*this)`
3006  template <typename E2,
3007  typename = typename std::enable_if<detail::result_is_failure_assignable<E,const E2&>::value>::type>
3008  auto operator=(const failure<E2>& other)
3009  noexcept(std::is_nothrow_assignable<E, const E2&>::value) -> result&;
3010  template <typename E2,
3011  typename = typename std::enable_if<detail::result_is_failure_assignable<E,E2&&>::value>::type>
3012  auto operator=(failure<E2>&& other)
3013  noexcept(std::is_nothrow_assignable<E, E2&&>::value) -> result&;
3014  /// \}
3015 
3016  //-------------------------------------------------------------------------
3017  // Observers
3018  //-------------------------------------------------------------------------
3019  public:
3020 
3021 
3022  /// \brief Contextually convertible to `true` if `*this` does not contain
3023  /// an error
3024  ///
3025  /// This function exists to allow for simple, terse checks for containing
3026  /// a value.
3027  ///
3028  /// ### Examples
3029  ///
3030  /// Basic Usage:
3031  ///
3032  /// ```cpp
3033  /// auto get_result() -> cpp::result<void, int>;
3034  /// auto r = get_result();
3035  /// if (r) { ... }
3036  ///
3037  /// assert(static_cast<bool>(cpp::result<void,int>{}));
3038  ///
3039  /// assert(!static_cast<bool>(cpp::result<void,int>{cpp::fail(42)}));
3040  /// ```
3041  ///
3042  /// \return `true` if `*this` contains a value, `false` if `*this`
3043  /// does not contain a value
3045  constexpr explicit operator bool() const noexcept;
3046 
3047  /// \copydoc result<T,E>::has_value
3049  constexpr auto has_value() const noexcept -> bool;
3050 
3051  /// \copydoc result<T,E>::has_error
3053  constexpr auto has_error() const noexcept -> bool;
3054 
3055  //-------------------------------------------------------------------------
3056 
3057  /// \{
3058  /// \brief Throws an exception if `(*this)` is in an error state
3059  ///
3060  /// This function exists for symmetry with `cpp::result<T,E>` objects where
3061  /// `T` contains a value.
3062  ///
3063  /// If this contains an error, an exception is thrown containing the
3064  /// underlying error. The error is consumed propagating the same constness
3065  /// and refness of this result.
3066  ///
3067  /// ### Examples
3068  ///
3069  /// Basic Usage:
3070  ///
3071  /// ```cpp
3072  /// cpp::result<void,int>{}.value(); // no exception
3073  ///
3074  /// auto r = cpp::result<void,std::unique_ptr<int>>{
3075  /// cpp::fail(std::make_unique<int>(42))
3076  /// };
3077  /// std::move(r).value(); // throws bad_result_access<std::unique_ptr<int>>
3078  ///
3079  /// try {
3080  /// auto r = cpp::result<void,int>{ cpp::fail(42) }.value();
3081  /// } catch (const cpp::bad_result_access<int>& e) {
3082  /// assert(e.error() == 42);
3083  /// }
3084  /// ```
3085  ///
3086  /// \throws bad_result_access<E> if `*this` does not contain a value.
3087  RESULT_CPP14_CONSTEXPR auto value() && -> void;
3088  RESULT_CPP14_CONSTEXPR auto value() const & -> void;
3089  /// \}
3090 
3091  /// \{
3092  /// \copydoc result<T,E>::error
3094  constexpr auto error() const &
3095  noexcept(std::is_nothrow_constructible<E>::value &&
3098  RESULT_CPP14_CONSTEXPR auto error() &&
3099  noexcept(std::is_nothrow_constructible<E>::value &&
3101  /// \}
3102 
3103  /// \{
3104  /// \copydoc result<T,E>::expect
3105  template <typename String,
3106  typename = typename std::enable_if<(
3107  std::is_convertible<String,const std::string&>::value &&
3108  std::is_copy_constructible<E>::value
3109  )>::type>
3110  RESULT_CPP14_CONSTEXPR auto expect(String&& message) const & -> void;
3111  template <typename String,
3112  typename = typename std::enable_if<(
3113  std::is_convertible<String,const std::string&>::value &&
3114  std::is_move_constructible<E>::value
3115  )>::type>
3116  RESULT_CPP14_CONSTEXPR auto expect(String&& message) && -> void;
3117  /// \}
3118 
3119  //-------------------------------------------------------------------------
3120  // Monadic Functionalities
3121  //-------------------------------------------------------------------------
3122  public:
3123 
3124  /// \{
3125  /// \copydoc result<T,E>::error_or
3126  template <typename U>
3128  constexpr auto error_or(U&& default_error) const & -> error_type;
3129  template <typename U>
3131  RESULT_CPP14_CONSTEXPR auto error_or(U&& default_error) && -> error_type;
3132  /// \}
3133 
3134  //-------------------------------------------------------------------------
3135 
3136  /// \copydoc result<T,E>::and_then
3137  template <typename U>
3139  constexpr auto and_then(U&& value) const -> result<typename std::decay<U>::type,E>;
3140 
3141  /// \{
3142  /// \brief Invokes the function \p fn if `(*this)` contains no value
3143  ///
3144  /// If this result contains an error, a result of the error is returned
3145  ///
3146  /// The function being called must return a `result` type or the program
3147  /// is ill-formed
3148  ///
3149  /// If this is called on an rvalue of `result` which contains an error,
3150  /// the returned `result` is constructed from an rvalue of that error.
3151  ///
3152  /// ### Examples
3153  ///
3154  /// Basic Usage:
3155  ///
3156  /// ```cpp
3157  /// auto generate_int() -> cpp::result<int,int> { return 42; }
3158  /// auto r = cpp::result<void,int>{};
3159  /// assert(r.flat_map(generate_int) == 42);
3160  ///
3161  /// auto r = cpp::result<void,int>{cpp::fail(42)};
3162  /// assert(r.flat_map(generate_int) == cpp::fail(42));
3163  /// ```
3164  ///
3165  /// \param fn the function to invoke with this
3166  /// \return The result of the function being called
3167  template <typename Fn>
3169  constexpr auto flat_map(Fn&& fn) const & -> detail::invoke_result_t<Fn>;
3170  template <typename Fn>
3172  RESULT_CPP14_CONSTEXPR auto flat_map(Fn&& fn) && -> detail::invoke_result_t<Fn>;
3173  /// \}
3174 
3175  /// \{
3176  /// \brief Invokes the function \p fn if `(*this)` contains no value
3177  ///
3178  /// If this result is an error, the result of this function is that
3179  /// error. Otherwise this function wraps the result and returns it as an
3180  /// result.
3181  ///
3182  /// If this is called on an rvalue of `result` which contains an error,
3183  /// the returned `result` is constructed from an rvalue of that error.
3184  ///
3185  /// ### Examples
3186  ///
3187  /// Basic Usage:
3188  ///
3189  /// ```cpp
3190  /// auto generate_int() -> int { return 42; }
3191  /// auto r = cpp::result<void,int>{};
3192  /// assert(r.map(generate_int) == 42);
3193  ///
3194  /// auto r = cpp::result<void,int>{cpp::fail(42)};
3195  /// assert(r.map(generate_int) == cpp::fail(42));
3196  /// ```
3197  ///
3198  /// \param fn the function to invoke with this
3199  /// \return The result result of the function invoked
3200  template <typename Fn>
3202  constexpr auto map(Fn&& fn) const & -> result<detail::invoke_result_t<Fn>,E>;
3203  template <typename Fn>
3205  RESULT_CPP14_CONSTEXPR auto map(Fn&& fn) && -> result<detail::invoke_result_t<Fn>,E>;
3206  /// \}
3207 
3208  /// \{
3209  /// \copydoc result<T,E>::map_error
3210  template <typename Fn>
3211  constexpr auto map_error(Fn&& fn) const & -> result<void, detail::invoke_result_t<Fn,const E&>>;
3212  template <typename Fn>
3214  auto map_error(Fn&& fn) && -> result<void, detail::invoke_result_t<Fn,E&&>>;
3215  /// \}
3216 
3217 
3218  /// \{
3219  /// \copydoc result<T,E>::flat_map_error
3220  template <typename Fn>
3222  constexpr auto flat_map_error(Fn&& fn) const & -> detail::invoke_result_t<Fn, const E&>;
3223  template <typename Fn>
3225  RESULT_CPP14_CONSTEXPR auto flat_map_error(Fn&& fn) && -> detail::invoke_result_t<Fn, E&&>;
3226  /// \}
3227 
3228  //-------------------------------------------------------------------------
3229  // Private Members
3230  //-------------------------------------------------------------------------
3231  private:
3232 
3233  detail::result_storage<detail::unit,E> m_storage;
3234 
3235  //-------------------------------------------------------------------------
3236  // Private Monadic Functions
3237  //-------------------------------------------------------------------------
3238  private:
3239 
3240  /// \{
3241  /// \brief Map implementations for void and non-void functions
3242  ///
3243  /// \param fn the function
3244  template <typename Fn>
3245  constexpr auto map_impl(std::true_type, Fn&& fn) const & -> result<void,E>;
3246  template <typename Fn>
3247  constexpr auto map_impl(std::false_type, Fn&& fn) const & -> result<detail::invoke_result_t<Fn>,E>;
3248  template <typename Fn>
3249  RESULT_CPP14_CONSTEXPR auto map_impl(std::true_type, Fn&& fn) && -> result<void,E>;
3250  template <typename Fn>
3251  RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn>,E>;
3252  /// \}
3253  };
3254 
3255  //===========================================================================
3256  // non-member functions : class : result
3257  //===========================================================================
3258 
3259  //---------------------------------------------------------------------------
3260  // Comparison
3261  //---------------------------------------------------------------------------
3262 
3263  template <typename T1, typename E1, typename T2, typename E2>
3264  constexpr auto operator==(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3265  noexcept -> bool;
3266  template <typename T1, typename E1, typename T2, typename E2>
3267  constexpr auto operator!=(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3268  noexcept -> bool;
3269  template <typename T1, typename E1, typename T2, typename E2>
3270  constexpr auto operator>=(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3271  noexcept -> bool;
3272  template <typename T1, typename E1, typename T2, typename E2>
3273  constexpr auto operator<=(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3274  noexcept -> bool;
3275  template <typename T1, typename E1, typename T2, typename E2>
3276  constexpr auto operator>(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3277  noexcept -> bool;
3278  template <typename T1, typename E1, typename T2, typename E2>
3279  constexpr auto operator<(const result<T1,E1>& lhs, const result<T2,E2>& rhs)
3280  noexcept -> bool;
3281 
3282  //---------------------------------------------------------------------------
3283 
3284  template <typename E1, typename E2>
3285  constexpr auto operator==(const result<void,E1>& lhs, const result<void,E2>& rhs)
3286  noexcept -> bool;
3287  template <typename E1, typename E2>
3288  constexpr auto operator!=(const result<void,E1>& lhs, const result<void,E2>& rhs)
3289  noexcept -> bool;
3290  template <typename E1, typename E2>
3291  constexpr auto operator>=(const result<void,E1>& lhs, const result<void,E2>& rhs)
3292  noexcept -> bool;
3293  template <typename E1, typename E2>
3294  constexpr auto operator<=(const result<void,E1>& lhs, const result<void,E2>& rhs)
3295  noexcept -> bool;
3296  template <typename E1, typename E2>
3297  constexpr auto operator>(const result<void,E1>& lhs, const result<void,E2>& rhs)
3298  noexcept -> bool;
3299  template <typename E1, typename E2>
3300  constexpr auto operator<(const result<void,E1>& lhs, const result<void,E2>& rhs)
3301  noexcept -> bool;
3302 
3303  //---------------------------------------------------------------------------
3304 
3305  template <typename T, typename E, typename U,
3306  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3307  constexpr auto operator==(const result<T,E>& exp, const U& value)
3308  noexcept -> bool;
3309  template <typename T, typename U, typename E,
3310  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3311  constexpr auto operator==(const T& value, const result<U,E>& exp)
3312  noexcept -> bool;
3313  template <typename T, typename E, typename U,
3314  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3315  constexpr auto operator!=(const result<T,E>& exp, const U& value)
3316  noexcept -> bool;
3317  template <typename T, typename U, typename E,
3318  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3319  constexpr auto operator!=(const T& value, const result<U,E>& exp)
3320  noexcept -> bool;
3321  template <typename T, typename E, typename U,
3322  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3323  constexpr auto operator<=(const result<T,E>& exp, const U& value)
3324  noexcept -> bool;
3325  template <typename T, typename U, typename E,
3326  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3327  constexpr auto operator<=(const T& value, const result<U,E>& exp)
3328  noexcept -> bool;
3329  template <typename T, typename E, typename U,
3330  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3331  constexpr auto operator>=(const result<T,E>& exp, const U& value)
3332  noexcept -> bool;
3333  template <typename T, typename U, typename E,
3334  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3335  constexpr auto operator>=(const T& value, const result<U,E>& exp)
3336  noexcept -> bool;
3337  template <typename T, typename E, typename U,
3338  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3339  constexpr auto operator<(const result<T,E>& exp, const U& value)
3340  noexcept -> bool;
3341  template <typename T, typename U, typename E,
3342  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3343  constexpr auto operator<(const T& value, const result<U,E>& exp)
3344  noexcept -> bool;
3345  template <typename T, typename E, typename U,
3346  typename = typename std::enable_if<!std::is_same<T,void>::value>::type>
3347  constexpr auto operator>(const result<T,E>& exp, const U& value)
3348  noexcept -> bool;
3349  template <typename T, typename U, typename E,
3350  typename = typename std::enable_if<!std::is_same<U,void>::value>::type>
3351  constexpr auto operator>(const T& value, const result<U,E>& exp)
3352  noexcept -> bool;
3353 
3354  //---------------------------------------------------------------------------
3355 
3356  template <typename T, typename E, typename U>
3357  constexpr auto operator==(const result<T,E>& exp, const failure<U>& value)
3358  noexcept -> bool;
3359  template <typename T, typename U, typename E>
3360  constexpr auto operator==(const failure<T>& value, const result<E,U>& exp)
3361  noexcept -> bool;
3362  template <typename T, typename E, typename U>
3363  constexpr auto operator!=(const result<T,E>& exp, const failure<U>& value)
3364  noexcept -> bool;
3365  template <typename T, typename U, typename E>
3366  constexpr auto operator!=(const failure<T>& value, const result<E,U>& exp)
3367  noexcept -> bool;
3368  template <typename T, typename E, typename U>
3369  constexpr auto operator<=(const result<T,E>& exp, const failure<U>& value)
3370  noexcept -> bool;
3371  template <typename T, typename U, typename E>
3372  constexpr auto operator<=(const failure<T>& value, const result<E,U>& exp)
3373  noexcept -> bool;
3374  template <typename T, typename E, typename U>
3375  constexpr auto operator>=(const result<T,E>& exp, const failure<U>& value)
3376  noexcept -> bool;
3377  template <typename T, typename U, typename E>
3378  constexpr auto operator>=(const failure<T>& value, const result<E,U>& exp)
3379  noexcept -> bool;
3380  template <typename T, typename E, typename U>
3381  constexpr auto operator<(const result<T,E>& exp, const failure<U>& value)
3382  noexcept -> bool;
3383  template <typename T, typename U, typename E>
3384  constexpr auto operator<(const failure<T>& value, const result<E,U>& exp)
3385  noexcept -> bool;
3386  template <typename T, typename E, typename U>
3387  constexpr auto operator>(const result<T,E>& exp, const failure<U>& value)
3388  noexcept -> bool;
3389  template <typename T, typename U, typename E>
3390  constexpr auto operator>(const failure<T>& value, const result<E,U>& exp)
3391  noexcept -> bool;
3392 
3393  //---------------------------------------------------------------------------
3394  // Utilities
3395  //---------------------------------------------------------------------------
3396 
3397  /// \{
3398  /// \brief Swaps the contents of \p lhs with \p rhs
3399  ///
3400  /// \param lhs the left result
3401  /// \param rhs the right result
3402  template <typename T, typename E>
3403  auto swap(result<T,E>& lhs, result<T,E>& rhs)
3404 #if __cplusplus >= 201703L
3409 #else
3412 #endif
3413  -> void;
3414  template <typename E>
3415  auto swap(result<void,E>& lhs, result<void,E>& rhs)
3416 #if __cplusplus >= 201703L
3417  noexcept(std::is_nothrow_move_constructible<result<void,E>>::value &&
3420 #else
3421  noexcept(std::is_nothrow_move_constructible<result<void,E>>::value &&
3423 #endif
3424  -> void;
3425  /// \}
3426 
3427 } // inline namespace bitwizeshift
3428 } // namespace EXPECTED_NAMESPACE
3429 
3430 namespace std {
3431 
3432  template <typename T, typename E>
3433  struct hash<::RESULT_NS_IMPL::result<T,E>>
3434  {
3435  auto operator()(const RESULT_NS_IMPL::result<T,E>& x) const -> std::size_t
3436  {
3437  if (x.has_value()) {
3438  return std::hash<T>{}(*x) + 1; // add '1' to differentiate from error case
3439  }
3440  return std::hash<E>{}(::RESULT_NS_IMPL::detail::extract_error(x));
3441  }
3442  };
3443 
3444  template <typename E>
3445  struct hash<::RESULT_NS_IMPL::result<void,E>>
3446  {
3447  auto operator()(const RESULT_NS_IMPL::result<void,E>& x) const -> std::size_t
3448  {
3449  if (x.has_value()) {
3450  return 0;
3451  }
3452  return std::hash<E>{}(::RESULT_NS_IMPL::detail::extract_error(x));
3453  }
3454  };
3455 
3456 } // namespace std
3457 
3458 #if !defined(RESULT_DISABLE_EXCEPTIONS)
3459 
3460 //=============================================================================
3461 // class : bad_result_access
3462 //=============================================================================
3463 
3464 //-----------------------------------------------------------------------------
3465 // Constructors
3466 //-----------------------------------------------------------------------------
3467 
3468 template <typename E>
3469 template <typename E2, typename>
3471 RESULT_NS_IMPL::bad_result_access<E>::bad_result_access(E2&& error)
3472  : logic_error{"error attempting to access value from result containing error"},
3473  m_error(detail::forward<E2>(error))
3474 {
3475 
3476 }
3477 
3478 template <typename E>
3479 template <typename E2, typename>
3481 RESULT_NS_IMPL::bad_result_access<E>::bad_result_access(
3482  const char* what_arg,
3483  E2&& error
3484 ) : logic_error{what_arg},
3485  m_error(detail::forward<E2>(error))
3486 {
3487 
3488 }
3489 
3490 template <typename E>
3491 template <typename E2, typename>
3493 RESULT_NS_IMPL::bad_result_access<E>::bad_result_access(
3494  const std::string& what_arg,
3495  E2&& error
3496 ) : logic_error{what_arg},
3497  m_error(detail::forward<E2>(error))
3498 {
3499 
3500 }
3501 
3502 //-----------------------------------------------------------------------------
3503 // Observers
3504 //-----------------------------------------------------------------------------
3505 
3506 template <typename E>
3508 auto RESULT_NS_IMPL::bad_result_access<E>::error()
3509  & noexcept -> E&
3510 {
3511  return m_error;
3512 }
3513 
3514 template <typename E>
3516 auto RESULT_NS_IMPL::bad_result_access<E>::error()
3517  && noexcept -> E&&
3518 {
3519  return static_cast<E&&>(m_error);
3520 }
3521 
3522 template <typename E>
3524 auto RESULT_NS_IMPL::bad_result_access<E>::error()
3525  const & noexcept -> const E&
3526 {
3527  return m_error;
3528 }
3529 
3530 template <typename E>
3532 auto RESULT_NS_IMPL::bad_result_access<E>::error()
3533  const && noexcept -> const E&&
3534 {
3535  return static_cast<const E&&>(m_error);
3536 }
3537 
3538 #endif
3539 
3540 //=============================================================================
3541 // class : failure
3542 //=============================================================================
3543 
3544 //-----------------------------------------------------------------------------
3545 // Constructors
3546 //-----------------------------------------------------------------------------
3547 
3548 template <typename E>
3549 template <typename...Args, typename>
3550 inline RESULT_INLINE_VISIBILITY constexpr
3551 RESULT_NS_IMPL::failure<E>::failure(in_place_t, Args&&...args)
3552  noexcept(std::is_nothrow_constructible<E, Args...>::value)
3553  : m_failure(detail::forward<Args>(args)...)
3554 {
3555 
3556 }
3557 
3558 template <typename E>
3559 template <typename U, typename...Args, typename>
3560 inline RESULT_INLINE_VISIBILITY constexpr
3561 RESULT_NS_IMPL::failure<E>::failure(
3562  in_place_t,
3563  std::initializer_list<U> ilist,
3564  Args&&...args
3566  : m_failure(ilist, detail::forward<Args>(args)...)
3567 {
3568 
3569 }
3570 
3571 template <typename E>
3572 template <typename E2,
3573  typename std::enable_if<RESULT_NS_IMPL::detail::failure_is_explicit_value_convertible<E,E2>::value,int>::type>
3574 inline RESULT_INLINE_VISIBILITY constexpr
3575 RESULT_NS_IMPL::failure<E>::failure(E2&& error)
3576  noexcept(std::is_nothrow_constructible<E,E2>::value)
3577  : m_failure(detail::forward<E2>(error))
3578 {
3579 
3580 }
3581 
3582 template <typename E>
3583 template <typename E2,
3584  typename std::enable_if<RESULT_NS_IMPL::detail::failure_is_implicit_value_convertible<E,E2>::value,int>::type>
3585 inline RESULT_INLINE_VISIBILITY constexpr
3586 RESULT_NS_IMPL::failure<E>::failure(E2&& error)
3587  noexcept(std::is_nothrow_constructible<E,E2>::value)
3588  : m_failure(detail::forward<E2>(error))
3589 {
3590 
3591 }
3592 
3593 template <typename E>
3594 template <typename E2, typename>
3595 inline RESULT_INLINE_VISIBILITY constexpr
3596 RESULT_NS_IMPL::failure<E>::failure(const failure<E2>& other)
3597  noexcept(std::is_nothrow_constructible<E,const E2&>::value)
3598  : m_failure(other.error())
3599 {
3600 
3601 }
3602 
3603 template <typename E>
3604 template <typename E2, typename>
3605 inline RESULT_INLINE_VISIBILITY constexpr
3606 RESULT_NS_IMPL::failure<E>::failure(failure<E2>&& other)
3607  noexcept(std::is_nothrow_constructible<E,E2&&>::value)
3608  : m_failure(static_cast<failure<E2>&&>(other).error())
3609 {
3610 
3611 }
3612 
3613 //-----------------------------------------------------------------------------
3614 
3615 template <typename E>
3616 template <typename E2, typename>
3618 auto RESULT_NS_IMPL::failure<E>::operator=(E2&& error)
3619  noexcept(
3622  ) -> failure&
3623 {
3624  m_failure = detail::forward<E2>(error);
3625 
3626  return (*this);
3627 }
3628 
3629 template <typename E>
3630 template <typename E2, typename>
3632 auto RESULT_NS_IMPL::failure<E>::operator=(const failure<E2>& other)
3633  noexcept(std::is_nothrow_assignable<E,const E2&>::value)
3634  -> failure&
3635 {
3636  m_failure = other.error();
3637 
3638  return (*this);
3639 }
3640 
3641 template <typename E>
3642 template <typename E2, typename>
3644 auto RESULT_NS_IMPL::failure<E>::operator=(failure<E2>&& other)
3645  noexcept(std::is_nothrow_assignable<E,E2&&>::value)
3646  -> failure&
3647 {
3648  m_failure = static_cast<failure<E2>&&>(other).error();
3649 
3650  return (*this);
3651 }
3652 
3653 //-----------------------------------------------------------------------------
3654 // Observers
3655 //-----------------------------------------------------------------------------
3656 
3657 template <typename E>
3659 auto RESULT_NS_IMPL::failure<E>::error()
3660  & noexcept -> typename std::add_lvalue_reference<E>::type
3661 {
3662  return m_failure;
3663 }
3664 
3665 template <typename E>
3667 auto RESULT_NS_IMPL::failure<E>::error()
3668  && noexcept -> typename std::add_rvalue_reference<E>::type
3669 {
3670  using reference = typename std::add_rvalue_reference<E>::type;
3671 
3672  return static_cast<reference>(m_failure);
3673 }
3674 
3675 template <typename E>
3676 inline RESULT_INLINE_VISIBILITY constexpr
3677 auto RESULT_NS_IMPL::failure<E>::error()
3678  const & noexcept
3679  -> typename std::add_lvalue_reference<typename std::add_const<E>::type>::type
3680 {
3681  return m_failure;
3682 }
3683 
3684 template <typename E>
3685 inline RESULT_INLINE_VISIBILITY constexpr
3686 auto RESULT_NS_IMPL::failure<E>::error()
3687  const && noexcept
3688  -> typename std::add_rvalue_reference<typename std::add_const<E>::type>::type
3689 {
3690  using reference = typename std::add_rvalue_reference<typename std::add_const<E>::type>::type;
3691 
3692  return static_cast<reference>(m_failure);
3693 }
3694 
3695 //=============================================================================
3696 // non-member functions : class : failure
3697 //=============================================================================
3698 
3699 //-----------------------------------------------------------------------------
3700 // Comparison
3701 //-----------------------------------------------------------------------------
3702 
3703 template <typename E1, typename E2>
3704 inline RESULT_INLINE_VISIBILITY constexpr
3705 auto RESULT_NS_IMPL::operator==(const failure<E1>& lhs, const failure<E2>& rhs)
3706  noexcept -> bool
3707 {
3708  return lhs.error() == rhs.error();
3709 }
3710 
3711 template <typename E1, typename E2>
3712 inline RESULT_INLINE_VISIBILITY constexpr
3713 auto RESULT_NS_IMPL::operator!=(const failure<E1>& lhs, const failure<E2>& rhs)
3714  noexcept -> bool
3715 {
3716  return lhs.error() != rhs.error();
3717 }
3718 
3719 template <typename E1, typename E2>
3720 inline RESULT_INLINE_VISIBILITY constexpr
3721 auto RESULT_NS_IMPL::operator<(const failure<E1>& lhs, const failure<E2>& rhs)
3722  noexcept -> bool
3723 {
3724  return lhs.error() < rhs.error();
3725 }
3726 
3727 template <typename E1, typename E2>
3728 inline RESULT_INLINE_VISIBILITY constexpr
3729 auto RESULT_NS_IMPL::operator>(const failure<E1>& lhs, const failure<E2>& rhs)
3730  noexcept -> bool
3731 {
3732  return lhs.error() > rhs.error();
3733 }
3734 
3735 template <typename E1, typename E2>
3736 inline RESULT_INLINE_VISIBILITY constexpr
3737 auto RESULT_NS_IMPL::operator<=(const failure<E1>& lhs, const failure<E2>& rhs)
3738  noexcept -> bool
3739 {
3740  return lhs.error() <= rhs.error();
3741 }
3742 
3743 template <typename E1, typename E2>
3744 inline RESULT_INLINE_VISIBILITY constexpr
3745 auto RESULT_NS_IMPL::operator>=(const failure<E1>& lhs, const failure<E2>& rhs)
3746  noexcept -> bool
3747 {
3748  return lhs.error() >= rhs.error();
3749 }
3750 
3751 //-----------------------------------------------------------------------------
3752 // Utilities
3753 //-----------------------------------------------------------------------------
3754 
3755 template <typename E>
3756 inline RESULT_INLINE_VISIBILITY constexpr
3757 auto RESULT_NS_IMPL::fail(E&& e)
3758  noexcept(std::is_nothrow_constructible<typename std::decay<E>::type,E>::value)
3759  -> failure<typename std::decay<E>::type>
3760 {
3761  using result_type = failure<typename std::decay<E>::type>;
3762 
3763  return result_type(
3764  detail::forward<E>(e)
3765  );
3766 }
3767 
3768 template <typename E>
3769 inline RESULT_INLINE_VISIBILITY constexpr
3770 auto RESULT_NS_IMPL::fail(std::reference_wrapper<E> e)
3771  noexcept -> failure<E&>
3772 {
3773  using result_type = failure<E&>;
3774 
3775  return result_type{e.get()};
3776 }
3777 
3778 template <typename E, typename...Args, typename>
3779 inline RESULT_INLINE_VISIBILITY constexpr
3780 auto RESULT_NS_IMPL::fail(Args&&...args)
3781  noexcept(std::is_nothrow_constructible<E, Args...>::value)
3782  -> failure<E>
3783 {
3784  return failure<E>(in_place, detail::forward<Args>(args)...);
3785 }
3786 
3787 template <typename E, typename U, typename...Args, typename>
3788 inline RESULT_INLINE_VISIBILITY constexpr
3789 auto RESULT_NS_IMPL::fail(std::initializer_list<U> ilist, Args&&...args)
3791  -> failure<E>
3792 {
3793  return failure<E>(in_place, ilist, detail::forward<Args>(args)...);
3794 }
3795 
3796 template <typename E>
3798 auto RESULT_NS_IMPL::swap(failure<E>& lhs, failure<E>& rhs)
3799 #if __cplusplus >= 201703L
3800  noexcept(std::is_nothrow_swappable<E>::value) -> void
3801 #else
3803  -> void
3804 #endif
3805 {
3806  using std::swap;
3807 
3808  swap(lhs.error(), rhs.error());
3809 }
3810 
3811 //=============================================================================
3812 // class : detail::result_union<T, E, IsTrivial>
3813 //=============================================================================
3814 
3815 //-----------------------------------------------------------------------------
3816 // Constructors / Assignment
3817 //-----------------------------------------------------------------------------
3818 
3819 template <typename T, typename E, bool IsTrivial>
3821 RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>
3822  ::result_union(unit)
3823  noexcept
3824  : m_empty{}
3825 {
3826  // m_has_value intentionally not set
3827 }
3828 
3829 template <typename T, typename E, bool IsTrivial>
3830 template <typename...Args>
3831 inline RESULT_INLINE_VISIBILITY constexpr
3832 RESULT_NS_IMPL::detail::result_union<T,E,IsTrivial>
3833  ::result_union(in_place_t, Args&&...args)
3834  noexcept(std::is_nothrow_constructible<T, Args...>::value)
3835  : m_value(detail::forward<Args>(args)...),
3836  m_has_value{true}
3837 {
3838 }
3839 
3840 template <typename T, typename E, bool IsTrivial>
3841 template <typename...Args>
3842 inline RESULT_INLINE_VISIBILITY constexpr
3843 RESULT_NS_IMPL::detail::result_union<T,E,IsTrivial>
3844  ::result_union(in_place_error_t, Args&&...args)
3845  noexcept(std::is_nothrow_constructible<E, Args...>::value)
3846  : m_error(detail::forward<Args>(args)...),
3847  m_has_value{false}
3848 {
3849 }
3850 
3851 //-----------------------------------------------------------------------------
3852 // Modifiers
3853 //-----------------------------------------------------------------------------
3854 
3855 template <typename T, typename E, bool IsTrivial>
3857 auto RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>::destroy()
3858  const noexcept -> void
3859 {
3860  // do nothing
3861 }
3862 
3863 //=============================================================================
3864 // class : detail::result_union<T, E, false>
3865 //=============================================================================
3866 
3867 //-----------------------------------------------------------------------------
3868 // Constructors / Destructor / Assignment
3869 //-----------------------------------------------------------------------------
3870 
3871 template <typename T, typename E>
3873 RESULT_NS_IMPL::detail::result_union<T, E, false>
3874  ::result_union(unit)
3875  noexcept
3876  : m_empty{}
3877 {
3878  // m_has_value intentionally not set
3879 }
3880 
3881 template <typename T, typename E>
3882 template <typename...Args>
3883 inline RESULT_INLINE_VISIBILITY constexpr
3884 RESULT_NS_IMPL::detail::result_union<T,E,false>
3885  ::result_union(in_place_t, Args&&...args)
3886  noexcept(std::is_nothrow_constructible<T, Args...>::value)
3887  : m_value(detail::forward<Args>(args)...),
3888  m_has_value{true}
3889 {
3890 }
3891 
3892 template <typename T, typename E>
3893 template <typename...Args>
3894 inline RESULT_INLINE_VISIBILITY constexpr
3895 RESULT_NS_IMPL::detail::result_union<T,E,false>
3896  ::result_union(in_place_error_t, Args&&...args)
3897  noexcept(std::is_nothrow_constructible<E, Args...>::value)
3898  : m_error(detail::forward<Args>(args)...),
3899  m_has_value{false}
3900 {
3901 }
3902 
3903 //-----------------------------------------------------------------------------
3904 
3905 template <typename T, typename E>
3907 RESULT_NS_IMPL::detail::result_union<T,E,false>
3908  ::~result_union()
3909  noexcept(std::is_nothrow_destructible<T>::value && std::is_nothrow_destructible<E>::value)
3910 {
3911  destroy();
3912 }
3913 
3914 //-----------------------------------------------------------------------------
3915 // Modifiers
3916 //-----------------------------------------------------------------------------
3917 
3918 template <typename T, typename E>
3920 auto RESULT_NS_IMPL::detail::result_union<T, E, false>::destroy()
3921  -> void
3922 {
3923  if (m_has_value) {
3924  m_value.~underlying_value_type();
3925  } else {
3926  m_error.~underlying_error_type();
3927  }
3928 }
3929 
3930 //=============================================================================
3931 // class : result_construct_base<T, E>
3932 //=============================================================================
3933 
3934 //-----------------------------------------------------------------------------
3935 // Constructors / Assignment
3936 //-----------------------------------------------------------------------------
3937 
3938 template <typename T, typename E>
3940 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(unit)
3941  noexcept
3942  : storage{unit{}}
3943 {
3944 }
3945 
3946 template <typename T, typename E>
3947 template <typename...Args>
3948 inline constexpr RESULT_INLINE_VISIBILITY
3949 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(
3950  in_place_t,
3951  Args&&...args
3952 ) noexcept(std::is_nothrow_constructible<T, Args...>::value)
3953  : storage{in_place, detail::forward<Args>(args)...}
3954 {
3955 }
3956 
3957 template <typename T, typename E>
3958 template <typename...Args>
3959 inline constexpr RESULT_INLINE_VISIBILITY
3960 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(
3962  Args&&...args
3963 ) noexcept(std::is_nothrow_constructible<E, Args...>::value)
3964  : storage(in_place_error, detail::forward<Args>(args)...)
3965 {
3966 }
3967 
3968 //-----------------------------------------------------------------------------
3969 // Construction / Assignment
3970 //-----------------------------------------------------------------------------
3971 
3972 template <typename T, typename E>
3973 template <typename...Args>
3975 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value(Args&&...args)
3976  noexcept(std::is_nothrow_constructible<T,Args...>::value)
3977  -> void
3978 {
3979  using value_type = typename storage_type::underlying_value_type;
3980 
3981  auto* p = static_cast<void*>(std::addressof(storage.m_value));
3982  new (p) value_type(detail::forward<Args>(args)...);
3983  storage.m_has_value = true;
3984 }
3985 
3986 template <typename T, typename E>
3987 template <typename...Args>
3989 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_error(Args&&...args)
3990  noexcept(std::is_nothrow_constructible<E,Args...>::value)
3991  -> void
3992 {
3993  using error_type = typename storage_type::underlying_error_type;
3994 
3995  auto* p = static_cast<void*>(std::addressof(storage.m_error));
3996  new (p) error_type(detail::forward<Args>(args)...);
3997  storage.m_has_value = false;
3998 }
3999 
4000 template <typename T, typename E>
4001 template <typename Result>
4003 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_error_from_result(
4004  Result&& other
4005 ) -> void
4006 {
4007  if (other.storage.m_has_value) {
4008  construct_value();
4009  } else {
4010  construct_error(detail::forward<Result>(other).storage.m_error);
4011  }
4012 }
4013 
4014 
4015 template <typename T, typename E>
4016 template <typename Result>
4018 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_from_result(
4019  Result&& other
4020 ) -> void
4021 {
4022  if (other.storage.m_has_value) {
4023  construct_value_from_result_impl(
4024  std::is_lvalue_reference<T>{},
4025  detail::forward<Result>(other).storage.m_value
4026  );
4027  } else {
4028  construct_error(detail::forward<Result>(other).storage.m_error);
4029  }
4030 }
4031 
4032 template <typename T, typename E>
4033 template <typename Value>
4035 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value(Value&& value)
4036  noexcept(std::is_nothrow_assignable<T,Value>::value)
4037  -> void
4038 {
4039  if (!storage.m_has_value) {
4040  storage.destroy();
4041  construct_value(detail::forward<Value>(value));
4042  } else {
4043  storage.m_value = detail::forward<Value>(value);
4044  }
4045 }
4046 
4047 template <typename T, typename E>
4048 template <typename Error>
4050 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_error(Error&& error)
4051  noexcept(std::is_nothrow_assignable<E,Error>::value)
4052  -> void
4053 {
4054  if (storage.m_has_value) {
4055  storage.destroy();
4056  construct_error(detail::forward<Error>(error));
4057  } else {
4058  storage.m_error = detail::forward<Error>(error);
4059  }
4060 }
4061 
4062 template <typename T, typename E>
4063 template <typename Result>
4065 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_from_result(Result&& other)
4066  -> void
4067 {
4068  if (other.storage.m_has_value != storage.m_has_value) {
4069  storage.destroy();
4070  construct_from_result(detail::forward<Result>(other));
4071  } else if (storage.m_has_value) {
4072  assign_value_from_result_impl(
4073  std::is_lvalue_reference<T>{},
4074  detail::forward<Result>(other)
4075  );
4076  } else {
4077  storage.m_error = detail::forward<Result>(other).storage.m_error;
4078  }
4079 }
4080 
4081 template <typename T, typename E>
4082 template <typename ReferenceWrapper>
4084 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value_from_result_impl(
4085  std::true_type,
4086  ReferenceWrapper&& reference
4087 ) noexcept -> void
4088 {
4089  using value_type = typename storage_type::underlying_value_type;
4090 
4091  auto* p = static_cast<void*>(std::addressof(storage.m_value));
4092  new (p) value_type(reference.get());
4093  storage.m_has_value = true;
4094 }
4095 
4096 template <typename T, typename E>
4097 template <typename Value>
4099 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value_from_result_impl(
4100  std::false_type,
4101  Value&& value
4102 ) noexcept(std::is_nothrow_constructible<T,Value>::value) -> void
4103 {
4104  using value_type = typename storage_type::underlying_value_type;
4105 
4106  auto* p = static_cast<void*>(std::addressof(storage.m_value));
4107  new (p) value_type(detail::forward<Value>(value));
4108  storage.m_has_value = true;
4109 }
4110 
4111 template <typename T, typename E>
4112 template <typename Result>
4114 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value_from_result_impl(
4115  std::true_type,
4116  Result&& other
4117 ) -> void
4118 {
4119  // T is a reference; unwrap it
4120  storage.m_value = other.storage.m_value.get();
4121 }
4122 
4123 template <typename T, typename E>
4124 template <typename Result>
4126 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value_from_result_impl(
4127  std::false_type,
4128  Result&& other
4129 ) -> void
4130 {
4131  storage.m_value = detail::forward<Result>(other).storage.m_value;
4132 }
4133 
4134 
4135 //=============================================================================
4136 // class : result_trivial_copy_ctor_base_impl
4137 //=============================================================================
4138 
4139 template <typename T, typename E>
4141 RESULT_NS_IMPL::detail::result_trivial_copy_ctor_base_impl<T,E>
4142  ::result_trivial_copy_ctor_base_impl(const result_trivial_copy_ctor_base_impl& other)
4143  noexcept(std::is_nothrow_copy_constructible<T>::value &&
4144  std::is_nothrow_copy_constructible<E>::value)
4145  : base_type(unit{})
4146 {
4147  using ctor_base = result_construct_base<T,E>;
4148 
4149  ctor_base::construct_from_result(static_cast<const ctor_base&>(other));
4150 }
4151 
4152 //=============================================================================
4153 // class : result_trivial_move_ctor_base
4154 //=============================================================================
4155 
4156 template <typename T, typename E>
4158 RESULT_NS_IMPL::detail::result_trivial_move_ctor_base_impl<T, E>
4159  ::result_trivial_move_ctor_base_impl(result_trivial_move_ctor_base_impl&& other)
4160  noexcept(std::is_nothrow_move_constructible<T>::value &&
4161  std::is_nothrow_move_constructible<E>::value)
4162  : base_type(unit{})
4163 {
4164  using ctor_base = result_construct_base<T,E>;
4165 
4166  ctor_base::construct_from_result(static_cast<ctor_base&&>(other));
4167 }
4168 
4169 //=============================================================================
4170 // class : result_copy_assign_base
4171 //=============================================================================
4172 
4173 template <typename T, typename E>
4175 auto RESULT_NS_IMPL::detail::result_trivial_copy_assign_base_impl<T, E>
4176  ::operator=(const result_trivial_copy_assign_base_impl& other)
4177  noexcept(std::is_nothrow_copy_constructible<T>::value &&
4178  std::is_nothrow_copy_constructible<E>::value &&
4179  std::is_nothrow_copy_assignable<T>::value &&
4180  std::is_nothrow_copy_assignable<E>::value)
4181  -> result_trivial_copy_assign_base_impl&
4182 {
4183  using ctor_base = result_construct_base<T,E>;
4184 
4185  ctor_base::assign_from_result(static_cast<const ctor_base&>(other));
4186  return (*this);
4187 }
4188 
4189 //=========================================================================
4190 // class : result_move_assign_base
4191 //=========================================================================
4192 
4193 template <typename T, typename E>
4195 auto RESULT_NS_IMPL::detail::result_trivial_move_assign_base_impl<T, E>
4196  ::operator=(result_trivial_move_assign_base_impl&& other)
4197  noexcept(std::is_nothrow_move_constructible<T>::value &&
4198  std::is_nothrow_move_constructible<E>::value &&
4199  std::is_nothrow_move_assignable<T>::value &&
4200  std::is_nothrow_move_assignable<E>::value)
4201  -> result_trivial_move_assign_base_impl&
4202 {
4203  using ctor_base = result_construct_base<T,E>;
4204 
4205  ctor_base::assign_from_result(static_cast<ctor_base&&>(other));
4206  return (*this);
4207 }
4208 
4209 template <typename T, typename E>
4210 inline RESULT_INLINE_VISIBILITY constexpr
4211 auto RESULT_NS_IMPL::detail::result_error_extractor::get(const result<T,E>& exp)
4212  noexcept -> const E&
4213 {
4214  return exp.m_storage.storage.m_error;
4215 }
4216 
4217 template <typename T, typename E>
4218 inline RESULT_INLINE_VISIBILITY constexpr
4219 auto RESULT_NS_IMPL::detail::result_error_extractor::get(result<T,E>& exp)
4220  noexcept -> E&
4221 {
4222  return exp.m_storage.storage.m_error;
4223 }
4224 
4225 template <typename T, typename E>
4226 inline RESULT_INLINE_VISIBILITY constexpr
4227 auto RESULT_NS_IMPL::detail::extract_error(const result<T,E>& exp) noexcept -> const E&
4228 {
4229  return result_error_extractor::get(exp);
4230 }
4231 
4232 template <typename E>
4234 auto RESULT_NS_IMPL::detail::throw_bad_result_access(E&& error) -> void
4235 {
4236 #if defined(RESULT_DISABLE_EXCEPTIONS)
4237  std::fprintf(
4238  stderr,
4239  "error attempting to access value from result containing error\n"
4240  );
4241  std::abort();
4242 #else
4243  using exception_type = bad_result_access<
4244  typename std::remove_const<
4245  typename std::remove_reference<E>::type
4246  >::type
4247  >;
4248 
4249  throw exception_type{
4250  detail::forward<E>(error)
4251  };
4252 #endif
4253 }
4254 
4255 template <typename String, typename E>
4257 auto RESULT_NS_IMPL::detail::throw_bad_result_access_message(
4258  String&& message,
4259  E&& error
4260 ) -> void
4261 {
4262 #if defined(RESULT_DISABLE_EXCEPTIONS)
4263  const auto message_string = std::string{
4264  detail::forward<String>(message)
4265  };
4266  std::fprintf(stderr, "%s\n", message_string.c_str());
4267  std::abort();
4268 #else
4269  using exception_type = bad_result_access<
4270  typename std::remove_const<
4271  typename std::remove_reference<E>::type
4272  >::type
4273  >;
4274 
4275  throw exception_type{
4276  detail::forward<String>(message),
4277  detail::forward<E>(error)
4278  };
4279 #endif
4280 }
4281 
4282 //=============================================================================
4283 // class : result<T,E>
4284 //=============================================================================
4285 
4286 template <typename T, typename E>
4287 template <typename U, typename>
4288 inline RESULT_INLINE_VISIBILITY constexpr
4289 RESULT_NS_IMPL::result<T, E>::result()
4290  noexcept(std::is_nothrow_constructible<U>::value)
4291  : m_storage(in_place)
4292 {
4293 
4294 }
4295 
4296 template <typename T, typename E>
4297 template <typename T2, typename E2,
4298  typename std::enable_if<RESULT_NS_IMPL::detail::result_is_implicit_copy_convertible<T,E,T2,E2>::value,int>::type>
4300 RESULT_NS_IMPL::result<T, E>::result(const result<T2,E2>& other)
4301  noexcept(std::is_nothrow_constructible<T,const T2&>::value &&
4303  : m_storage(detail::unit{})
4304 {
4305  m_storage.construct_from_result(
4306  static_cast<const result<T2,E2>&>(other).m_storage
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_explicit_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_implicit_move_convertible<T,E,T2,E2>::value,int>::type>
4328 RESULT_NS_IMPL::result<T, E>::result(result<T2,E2>&& other)
4329  noexcept(std::is_nothrow_constructible<T,T2&&>::value &&
4331  : m_storage(detail::unit{})
4332 {
4333  m_storage.construct_from_result(
4334  static_cast<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_explicit_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 //-----------------------------------------------------------------------------
4353 
4354 template <typename T, typename E>
4355 template <typename...Args, typename>
4356 inline RESULT_INLINE_VISIBILITY constexpr
4357 RESULT_NS_IMPL::result<T, E>::result(in_place_t, Args&&...args)
4358  noexcept(std::is_nothrow_constructible<T, Args...>::value)
4359  : m_storage(in_place, detail::forward<Args>(args)...)
4360 {
4361 
4362 }
4363 
4364 template <typename T, typename E>
4365 template <typename U, typename...Args, typename>
4366 inline RESULT_INLINE_VISIBILITY constexpr
4367 RESULT_NS_IMPL::result<T, E>::result(
4368  in_place_t,
4369  std::initializer_list<U> ilist,
4370  Args&&...args
4372  : m_storage(in_place, ilist, detail::forward<Args>(args)...)
4373 {
4374 
4375 }
4376 
4377 //-----------------------------------------------------------------------------
4378 
4379 template <typename T, typename E>
4380 template <typename...Args, typename>
4381 inline RESULT_INLINE_VISIBILITY constexpr
4382 RESULT_NS_IMPL::result<T, E>::result(in_place_error_t, Args&&...args)
4383  noexcept(std::is_nothrow_constructible<E, Args...>::value)
4384  : m_storage(in_place_error, detail::forward<Args>(args)...)
4385 {
4386 
4387 }
4388 
4389 template <typename T, typename E>
4390 template <typename U, typename...Args, typename>
4391 inline RESULT_INLINE_VISIBILITY constexpr
4392 RESULT_NS_IMPL::result<T, E>::result(
4394  std::initializer_list<U> ilist,
4395  Args&&...args
4397  : m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
4398 {
4399 
4400 }
4401 
4402 //-------------------------------------------------------------------------
4403 
4404 template <typename T, typename E>
4405 template <typename E2, typename>
4406 inline RESULT_INLINE_VISIBILITY constexpr
4407 RESULT_NS_IMPL::result<T, E>::result(const failure<E2>& e)
4408  noexcept(std::is_nothrow_constructible<E,const E2&>::value)
4409  : m_storage(in_place_error, e.error())
4410 {
4411 
4412 }
4413 
4414 template <typename T, typename E>
4415 template <typename E2, typename>
4416 inline RESULT_INLINE_VISIBILITY constexpr
4417 RESULT_NS_IMPL::result<T, E>::result(failure<E2>&& e)
4418  noexcept(std::is_nothrow_constructible<E,E2&&>::value)
4419  : m_storage(in_place_error, static_cast<E2&&>(e.error()))
4420 {
4421 
4422 }
4423 
4424 template <typename T, typename E>
4425 template <typename U,
4426  typename std::enable_if<RESULT_NS_IMPL::detail::result_is_explicit_value_convertible<T,U>::value,int>::type>
4427 inline RESULT_INLINE_VISIBILITY constexpr
4428 RESULT_NS_IMPL::result<T, E>::result(U&& value)
4429  noexcept(std::is_nothrow_constructible<T,U>::value)
4430  : m_storage(in_place, detail::forward<U>(value))
4431 {
4432 
4433 }
4434 
4435 template <typename T, typename E>
4436 template <typename U,
4437  typename std::enable_if<RESULT_NS_IMPL::detail::result_is_implicit_value_convertible<T,U>::value,int>::type>
4438 inline RESULT_INLINE_VISIBILITY constexpr
4439 RESULT_NS_IMPL::result<T, E>::result(U&& value)
4440  noexcept(std::is_nothrow_constructible<T,U>::value)
4441  : m_storage(in_place, detail::forward<U>(value))
4442 {
4443 
4444 }
4445 
4446 //-----------------------------------------------------------------------------
4447 
4448 template <typename T, typename E>
4449 template <typename T2, typename E2, typename>
4451 auto RESULT_NS_IMPL::result<T, E>::operator=(const result<T2,E2>& other)
4452  noexcept(std::is_nothrow_assignable<T, const T2&>::value &&
4453  std::is_nothrow_assignable<E, const E2&>::value)
4454  -> result&
4455 {
4456  m_storage.assign_from_result(
4457  static_cast<const result<T2,E2>&>(other).m_storage
4458  );
4459  return (*this);
4460 }
4461 
4462 template <typename T, typename E>
4463 template <typename T2, typename E2, typename>
4465 auto RESULT_NS_IMPL::result<T, E>::operator=(result<T2,E2>&& other)
4466  noexcept(std::is_nothrow_assignable<T, T2&&>::value &&
4468  -> result&
4469 {
4470  m_storage.assign_from_result(
4471  static_cast<result<T2,E2>&&>(other).m_storage
4472  );
4473  return (*this);
4474 }
4475 
4476 template <typename T, typename E>
4477 template <typename U, typename>
4479 auto RESULT_NS_IMPL::result<T, E>::operator=(U&& value)
4480  noexcept(std::is_nothrow_assignable<T, U>::value)
4481  -> result&
4482 {
4483  m_storage.assign_value(detail::forward<U>(value));
4484  return (*this);
4485 }
4486 
4487 template <typename T, typename E>
4488 template <typename E2, typename>
4490 auto RESULT_NS_IMPL::result<T, E>::operator=(const failure<E2>& other)
4491  noexcept(std::is_nothrow_assignable<E, const E2&>::value)
4492  -> result&
4493 {
4494  m_storage.assign_error(other.error());
4495  return (*this);
4496 }
4497 
4498 template <typename T, typename E>
4499 template <typename E2, typename>
4501 auto RESULT_NS_IMPL::result<T, E>::operator=(failure<E2>&& other)
4502  noexcept(std::is_nothrow_assignable<E, E2&&>::value)
4503  -> result&
4504 {
4505  m_storage.assign_error(static_cast<E2&&>(other.error()));
4506  return (*this);
4507 }
4508 
4509 //-----------------------------------------------------------------------------
4510 // Observers
4511 //-----------------------------------------------------------------------------
4512 
4513 template <typename T, typename E>
4515 auto RESULT_NS_IMPL::result<T, E>::operator->()
4516  noexcept -> typename std::remove_reference<T>::type*
4517 {
4518  // Prior to C++17, std::addressof was not `constexpr`.
4519  // Since `addressof` fixes a relatively obscure issue where users define a
4520  // custom `operator&`, the pre-C++17 implementation has been defined to be
4521  // `&(**this)` so that it may exist in constexpr contexts.
4522 #if __cplusplus >= 201703L
4523  return std::addressof(**this);
4524 #else
4525  return &(**this);
4526 #endif
4527 }
4528 
4529 template <typename T, typename E>
4530 inline RESULT_INLINE_VISIBILITY constexpr
4531 auto RESULT_NS_IMPL::result<T, E>::operator->()
4532  const noexcept -> typename std::remove_reference<typename std::add_const<T>::type>::type*
4533 {
4534 #if __cplusplus >= 201703L
4535  return std::addressof(**this);
4536 #else
4537  return &(**this);
4538 #endif
4539 }
4540 
4541 template <typename T, typename E>
4543 auto RESULT_NS_IMPL::result<T, E>::operator*()
4544  & noexcept -> typename std::add_lvalue_reference<T>::type
4545 {
4546  return m_storage.storage.m_value;
4547 }
4548 
4549 template <typename T, typename E>
4551 auto RESULT_NS_IMPL::result<T, E>::operator*()
4552  && noexcept -> typename std::add_rvalue_reference<T>::type
4553 {
4554  using reference = typename std::add_rvalue_reference<T>::type;
4555 
4556  return static_cast<reference>(m_storage.storage.m_value);
4557 }
4558 
4559 template <typename T, typename E>
4560 inline RESULT_INLINE_VISIBILITY constexpr
4561 auto RESULT_NS_IMPL::result<T, E>::operator*()
4562  const& noexcept -> typename std::add_lvalue_reference<typename std::add_const<T>::type>::type
4563 {
4564  return m_storage.storage.m_value;
4565 }
4566 
4567 template <typename T, typename E>
4568 inline RESULT_INLINE_VISIBILITY constexpr
4569 auto RESULT_NS_IMPL::result<T, E>::operator*()
4570  const&& noexcept -> typename std::add_rvalue_reference<typename std::add_const<T>::type>::type
4571 {
4572  using reference = typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
4573 
4574  return static_cast<reference>(m_storage.storage.m_value);
4575 }
4576 
4577 //-----------------------------------------------------------------------------
4578 
4579 template <typename T, typename E>
4580 inline RESULT_INLINE_VISIBILITY constexpr
4581 RESULT_NS_IMPL::result<T,E>::operator bool()
4582  const noexcept
4583 {
4584  return m_storage.storage.m_has_value;
4585 }
4586 
4587 template <typename T, typename E>
4588 inline RESULT_INLINE_VISIBILITY constexpr
4589 auto RESULT_NS_IMPL::result<T,E>::has_value()
4590  const noexcept -> bool
4591 {
4592  return m_storage.storage.m_has_value;
4593 }
4594 
4595 template <typename T, typename E>
4596 inline RESULT_INLINE_VISIBILITY constexpr
4597 auto RESULT_NS_IMPL::result<T,E>::has_error()
4598  const noexcept -> bool
4599 {
4600  return !m_storage.storage.m_has_value;
4601 }
4602 
4603 //-----------------------------------------------------------------------------
4604 
4605 // The `has_value()` expression below is incorrectly identified as an unused
4606 // value, which results in the `-Wunused-value` warning. This is suppressed
4607 // to prevent false-positives
4608 #if defined(__clang__)
4609 # pragma clang diagnostic push
4610 # pragma clang diagnostic ignored "-Wunused-value"
4611 #elif defined(__GNUC__)
4612 # pragma GCC diagnostic push
4613 # pragma GCC diagnostic ignored "-Wunused-value"
4614 #elif defined(_MSC_VER)
4615 // Older MSVC versions incorrectly warn on returning a reference to a temporary.
4616 // This has been suppressed
4617 # pragma warning(push)
4618 # pragma warning(disable:4172)
4619 #endif
4620 
4621 template <typename T, typename E>
4623 auto RESULT_NS_IMPL::result<T,E>::value()
4624  & -> typename std::add_lvalue_reference<T>::type
4625 {
4626  return (has_value() ||
4627  (detail::throw_bad_result_access(m_storage.storage.m_error), false),
4628  m_storage.storage.m_value
4629  );
4630 }
4631 
4632 template <typename T, typename E>
4634 auto RESULT_NS_IMPL::result<T,E>::value()
4635  && -> typename std::add_rvalue_reference<T>::type
4636 {
4637  using reference = typename std::add_rvalue_reference<T>::type;
4638 
4639  return (has_value() ||
4640  (detail::throw_bad_result_access(static_cast<E&&>(m_storage.storage.m_error)), true),
4641  static_cast<reference>(m_storage.storage.m_value)
4642  );
4643 }
4644 
4645 template <typename T, typename E>
4646 inline RESULT_INLINE_VISIBILITY constexpr
4647 auto RESULT_NS_IMPL::result<T,E>::value()
4648  const & -> typename std::add_lvalue_reference<typename std::add_const<T>::type>::type
4649 {
4650  return (has_value() ||
4651  (detail::throw_bad_result_access(m_storage.storage.m_error), true),
4652  m_storage.storage.m_value
4653  );
4654 }
4655 
4656 template <typename T, typename E>
4657 inline RESULT_INLINE_VISIBILITY constexpr
4658 auto RESULT_NS_IMPL::result<T,E>::value()
4659  const && -> typename std::add_rvalue_reference<typename std::add_const<T>::type>::type
4660 {
4661  using reference = typename std::add_rvalue_reference<typename std::add_const<T>::type>::type;
4662 
4663  return (has_value() ||
4664  (detail::throw_bad_result_access(static_cast<const E&&>(m_storage.storage.m_error)), true),
4665  (static_cast<reference>(m_storage.storage.m_value))
4666  );
4667 }
4668 
4669 #if defined(__clang__)
4670 # pragma clang diagnostic pop
4671 #elif defined(__GNUC__)
4672 # pragma GCC diagnostic pop
4673 #elif defined(_MSC_VER)
4674 # pragma warning(pop)
4675 #endif
4676 
4677 template <typename T, typename E>
4678 inline RESULT_INLINE_VISIBILITY constexpr
4679 auto RESULT_NS_IMPL::result<T,E>::error() const &
4680  noexcept(std::is_nothrow_constructible<E>::value &&
4682 {
4683  static_assert(
4684  std::is_default_constructible<E>::value,
4685  "E must be default-constructible if 'error()' checks are used. "
4686  "This is to allow for default-constructed error states to represent the "
4687  "'good' state"
4688  );
4689 
4690  return m_storage.storage.m_has_value
4691  ? E{}
4692  : m_storage.storage.m_error;
4693 }
4694 
4695 template <typename T, typename E>
4697 auto RESULT_NS_IMPL::result<T,E>::error() &&
4698  noexcept(std::is_nothrow_constructible<E>::value &&
4699  std::is_nothrow_move_constructible<E>::value) -> E
4700 {
4701  static_assert(
4702  std::is_default_constructible<E>::value,
4703  "E must be default-constructible if 'error()' checks are used. "
4704  "This is to allow for default-constructed error states to represent the "
4705  "'good' state"
4706  );
4707 
4708  return m_storage.storage.m_has_value
4709  ? E{}
4710  : static_cast<E&&>(m_storage.storage.m_error);
4711 }
4712 
4713 //-----------------------------------------------------------------------------
4714 
4715 template <typename T, typename E>
4716 template <typename String, typename>
4718 auto RESULT_NS_IMPL::result<T,E>::expect(String&& message)
4719  const & -> void
4720 {
4721  if (has_error()) {
4722  detail::throw_bad_result_access_message(
4723  detail::forward<String>(message),
4724  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  && -> void
4734 {
4735  if (has_error()) {
4736  detail::throw_bad_result_access_message(
4737  detail::forward<String>(message),
4738  static_cast<E&&>(m_storage.storage.m_error)
4739  );
4740  }
4741 }
4742 
4743 //-----------------------------------------------------------------------------
4744 // Monadic Functionalities
4745 //-----------------------------------------------------------------------------
4746 
4747 template <typename T, typename E>
4748 template <typename U>
4749 inline RESULT_INLINE_VISIBILITY constexpr
4750 auto RESULT_NS_IMPL::result<T, E>::value_or(U&& default_value)
4751  const& -> typename std::remove_reference<T>::type
4752 {
4753  return m_storage.storage.m_has_value
4754  ? m_storage.storage.m_value
4755  : detail::forward<U>(default_value);
4756 }
4757 
4758 template <typename T, typename E>
4759 template <typename U>
4761 auto RESULT_NS_IMPL::result<T, E>::value_or(U&& default_value)
4762  && -> typename std::remove_reference<T>::type
4763 {
4764  return m_storage.storage.m_has_value
4765  ? static_cast<T&&>(**this)
4766  : detail::forward<U>(default_value);
4767 }
4768 
4769 template <typename T, typename E>
4770 template <typename U>
4771 inline RESULT_INLINE_VISIBILITY constexpr
4772 auto RESULT_NS_IMPL::result<T, E>::error_or(U&& default_error)
4773  const& -> error_type
4774 {
4775  return m_storage.storage.m_has_value
4776  ? detail::forward<U>(default_error)
4777  : m_storage.storage.m_error;
4778 }
4779 
4780 template <typename T, typename E>
4781 template <typename U>
4783 auto RESULT_NS_IMPL::result<T, E>::error_or(U&& default_error)
4784  && -> error_type
4785 {
4786  return m_storage.storage.m_has_value
4787  ? detail::forward<U>(default_error)
4788  : static_cast<E&&>(m_storage.storage.m_error);
4789 }
4790 
4791 template <typename T, typename E>
4792 template <typename U>
4793 inline RESULT_INLINE_VISIBILITY constexpr
4794 auto RESULT_NS_IMPL::result<T, E>::and_then(U&& value)
4795  const -> result<typename std::decay<U>::type,E>
4796 {
4797  return map([&value](const T&){
4798  return detail::forward<U>(value);
4799  });
4800 }
4801 
4802 //-----------------------------------------------------------------------------
4803 
4804 template <typename T, typename E>
4805 template <typename Fn>
4806 inline RESULT_INLINE_VISIBILITY constexpr
4807 auto RESULT_NS_IMPL::result<T, E>::flat_map(Fn&& fn)
4808  const & -> detail::invoke_result_t<Fn, const T&>
4809 {
4810  using result_type = detail::invoke_result_t<Fn, const T&>;
4811 
4812  static_assert(
4813  is_result<result_type>::value,
4814  "flat_map must return a result type or the program is ill-formed"
4815  );
4816 
4817  return has_value()
4818  ? detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value)
4819  : result_type(in_place_error, m_storage.storage.m_error);
4820 }
4821 
4822 template <typename T, typename E>
4823 template <typename Fn>
4825 auto RESULT_NS_IMPL::result<T, E>::flat_map(Fn&& fn)
4826  && -> detail::invoke_result_t<Fn, T&&>
4827 {
4828  using result_type = detail::invoke_result_t<Fn, T&&>;
4829 
4830  static_assert(
4831  is_result<result_type>::value,
4832  "flat_map must return a result type or the program is ill-formed"
4833  );
4834 
4835  return has_value()
4836  ? detail::invoke(detail::forward<Fn>(fn), static_cast<T&&>(m_storage.storage.m_value))
4837  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4838 }
4839 
4840 template <typename T, typename E>
4841 template <typename Fn>
4842 inline RESULT_INLINE_VISIBILITY constexpr
4843 auto RESULT_NS_IMPL::result<T, E>::map(Fn&& fn)
4844  const & -> result<detail::invoke_result_t<Fn,const T&>,E>
4845 {
4846  using result_type = detail::invoke_result_t<Fn,const T&>;
4847 
4848  return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
4849 }
4850 
4851 template <typename T, typename E>
4852 template <typename Fn>
4854 auto RESULT_NS_IMPL::result<T, E>::map(Fn&& fn)
4855  && -> result<detail::invoke_result_t<Fn,T&&>,E>
4856 {
4857  using result_type = detail::invoke_result_t<Fn,T&&>;
4858 
4859  return static_cast<result<T,E>&&>(*this).map_impl(
4860  std::is_void<result_type>{},
4861  detail::forward<Fn>(fn)
4862  );
4863 }
4864 
4865 //-----------------------------------------------------------------------------
4866 
4867 template <typename T, typename E>
4868 template <typename Fn>
4869 inline RESULT_INLINE_VISIBILITY constexpr
4870 auto RESULT_NS_IMPL::result<T, E>::map_error(Fn&& fn)
4871  const & -> result<T, detail::invoke_result_t<Fn,const E&>>
4872 {
4873  using result_type = result<T, detail::invoke_result_t<Fn, const E&>>;
4874 
4875  return has_error()
4876  ? result_type(in_place_error, detail::invoke(
4877  detail::forward<Fn>(fn), m_storage.storage.m_error
4878  ))
4879  : result_type(in_place, m_storage.storage.m_value);
4880 }
4881 
4882 template <typename T, typename E>
4883 template <typename Fn>
4885 auto RESULT_NS_IMPL::result<T, E>::map_error(Fn&& fn)
4886  && -> result<T, detail::invoke_result_t<Fn,E&&>>
4887 {
4888  using result_type = result<T, detail::invoke_result_t<Fn, E&&>>;
4889 
4890  return has_error()
4891  ? result_type(in_place_error, detail::invoke(
4892  detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error)
4893  ))
4894  : result_type(static_cast<T&&>(m_storage.storage.m_value));
4895 }
4896 
4897 template <typename T, typename E>
4898 template <typename Fn>
4899 inline RESULT_INLINE_VISIBILITY constexpr
4900 auto RESULT_NS_IMPL::result<T, E>::flat_map_error(Fn&& fn)
4901  const & -> detail::invoke_result_t<Fn, const E&>
4902 {
4903  using result_type = detail::invoke_result_t<Fn, const E&>;
4904 
4905  static_assert(
4906  is_result<result_type>::value,
4907  "flat_map_error must return a result type or the program is ill-formed"
4908  );
4909 
4910  return has_value()
4911  ? result_type(in_place, m_storage.storage.m_value)
4912  : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
4913 }
4914 
4915 template <typename T, typename E>
4916 template <typename Fn>
4918 auto RESULT_NS_IMPL::result<T, E>::flat_map_error(Fn&& fn)
4919  && -> detail::invoke_result_t<Fn, E&&>
4920 {
4921  using result_type = detail::invoke_result_t<Fn, E&&>;
4922 
4923  static_assert(
4924  is_result<result_type>::value,
4925  "flat_map_error must return a result type or the program is ill-formed"
4926  );
4927 
4928  return has_value()
4929  ? result_type(in_place, static_cast<T&&>(m_storage.storage.m_value))
4930  : detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error));
4931 }
4932 
4933 //-----------------------------------------------------------------------------
4934 // Private Monadic Functions
4935 //-----------------------------------------------------------------------------
4936 
4937 template <typename T, typename E>
4938 template <typename Fn>
4939 inline RESULT_INLINE_VISIBILITY constexpr
4940 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type, Fn&& fn)
4941  const & -> result<void,E>
4942 {
4943  using result_type = result<void, E>;
4944 
4945  return has_value()
4946  ? (detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value), result_type{})
4947  : result_type(in_place_error, m_storage.storage.m_error);
4948 }
4949 
4950 template <typename T, typename E>
4951 template <typename Fn>
4952 inline RESULT_INLINE_VISIBILITY constexpr
4953 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type, Fn&& fn)
4954  const & -> result<detail::invoke_result_t<Fn,const T&>,E>
4955 {
4956  using invoke_result_type = detail::invoke_result_t<Fn,const T&>;
4957  using result_type = result<invoke_result_type, E>;
4958 
4959  return has_value()
4960  ? result_type(in_place, detail::invoke(
4961  detail::forward<Fn>(fn), m_storage.storage.m_value
4962  ))
4963  : result_type(in_place_error, m_storage.storage.m_error);
4964 }
4965 
4966 template <typename T, typename E>
4967 template <typename Fn>
4969 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type, Fn&& fn)
4970  && -> result<void,E>
4971 {
4972  using result_type = result<void, E>;
4973 
4974  return has_value()
4975  ? (detail::invoke(
4976  detail::forward<Fn>(fn), static_cast<T&&>(m_storage.storage.m_value)
4977  ), result_type{})
4978  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4979 }
4980 
4981 template <typename T, typename E>
4982 template <typename Fn>
4984 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type, Fn&& fn)
4985  && -> result<detail::invoke_result_t<Fn,T&&>,E>
4986 {
4987  using invoke_result_type = detail::invoke_result_t<Fn,T&&>;
4988  using result_type = result<invoke_result_type, E>;
4989 
4990  return has_value()
4991  ? result_type(in_place, detail::invoke(
4992  detail::forward<Fn>(fn), static_cast<T&&>(m_storage.storage.m_value)
4993  ))
4994  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
4995 }
4996 
4997 //=============================================================================
4998 // class : result<void,E>
4999 //=============================================================================
5000 
5001 //-----------------------------------------------------------------------------
5002 // Constructor / Assignment
5003 //-----------------------------------------------------------------------------
5004 
5005 template <typename E>
5006 inline RESULT_INLINE_VISIBILITY constexpr
5007 RESULT_NS_IMPL::result<void, E>::result()
5008  noexcept
5009  : m_storage(in_place)
5010 {
5011 
5012 }
5013 
5014 template <typename E>
5015 template <typename U, typename E2, typename>
5017 RESULT_NS_IMPL::result<void, E>::result(const result<U,E2>& other)
5018  noexcept(std::is_nothrow_constructible<E,const E2&>::value)
5019  : m_storage(detail::unit{})
5020 {
5021  m_storage.construct_error_from_result(
5022  static_cast<const result<U,E2>&>(other).m_storage
5023  );
5024 }
5025 
5026 template <typename E>
5027 template <typename U, typename E2, typename>
5029 RESULT_NS_IMPL::result<void, E>::result(result<U,E2>&& other)
5030  noexcept(std::is_nothrow_constructible<E,E2&&>::value)
5031  : m_storage(detail::unit{})
5032 {
5033  m_storage.construct_error_from_result(
5034  static_cast<result<U,E2>&&>(other).m_storage
5035  );
5036 }
5037 
5038 
5039 //-----------------------------------------------------------------------------
5040 
5041 template <typename E>
5042 inline RESULT_INLINE_VISIBILITY constexpr
5043 RESULT_NS_IMPL::result<void, E>::result(in_place_t)
5044  noexcept
5045  : m_storage(in_place)
5046 {
5047 
5048 }
5049 
5050 template <typename E>
5051 template <typename...Args, typename>
5052 inline RESULT_INLINE_VISIBILITY constexpr
5053 RESULT_NS_IMPL::result<void, E>::result(in_place_error_t, Args&&...args)
5054  noexcept(std::is_nothrow_constructible<E, Args...>::value)
5055  : m_storage(in_place_error, detail::forward<Args>(args)...)
5056 {
5057 
5058 }
5059 
5060 template <typename E>
5061 template <typename U, typename...Args, typename>
5062 inline RESULT_INLINE_VISIBILITY constexpr
5063 RESULT_NS_IMPL::result<void, E>::result(in_place_error_t,
5064  std::initializer_list<U> ilist,
5065  Args&&...args)
5067  : m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
5068 {
5069 
5070 }
5071 
5072 //-----------------------------------------------------------------------------
5073 
5074 template <typename E>
5075 template <typename E2, typename>
5076 inline RESULT_INLINE_VISIBILITY constexpr
5077 RESULT_NS_IMPL::result<void, E>::result(const failure<E2>& e)
5078  noexcept(std::is_nothrow_constructible<E,const E2&>::value)
5079  : m_storage(in_place_error, e.error())
5080 {
5081 
5082 }
5083 
5084 template <typename E>
5085 template <typename E2, typename>
5086 inline RESULT_INLINE_VISIBILITY constexpr
5087 RESULT_NS_IMPL::result<void, E>::result(failure<E2>&& e)
5088  noexcept(std::is_nothrow_constructible<E,E2&&>::value)
5089  : m_storage(in_place_error, static_cast<E2&&>(e.error()))
5090 {
5091 
5092 }
5093 
5094 //-----------------------------------------------------------------------------
5095 
5096 template <typename E>
5097 template <typename E2, typename>
5099 auto RESULT_NS_IMPL::result<void, E>::operator=(const result<void,E2>& other)
5100  noexcept(std::is_nothrow_assignable<E, const E2&>::value)
5101  -> result&
5102 {
5103  m_storage.assign_from_result(other.m_storage);
5104  return (*this);
5105 }
5106 
5107 template <typename E>
5108 template <typename E2, typename>
5110 auto RESULT_NS_IMPL::result<void, E>::operator=(result<void,E2>&& other)
5111  noexcept(std::is_nothrow_assignable<E, E2&&>::value)
5112  -> result&
5113 {
5114  m_storage.assign_from_result(static_cast<result<void,E2>&&>(other).m_storage);
5115  return (*this);
5116 }
5117 
5118 template <typename E>
5119 template <typename E2, typename>
5121 auto RESULT_NS_IMPL::result<void, E>::operator=(const failure<E2>& other)
5122  noexcept(std::is_nothrow_assignable<E, const E2&>::value)
5123  -> result&
5124 {
5125  m_storage.assign_error(other.error());
5126  return (*this);
5127 }
5128 
5129 template <typename E>
5130 template <typename E2, typename>
5132 auto RESULT_NS_IMPL::result<void, E>::operator=(failure<E2>&& other)
5133  noexcept(std::is_nothrow_assignable<E, E2&&>::value)
5134  -> result&
5135 {
5136  m_storage.assign_error(static_cast<E2&&>(other.error()));
5137  return (*this);
5138 }
5139 
5140 //-----------------------------------------------------------------------------
5141 // Observers
5142 //-----------------------------------------------------------------------------
5143 
5144 template <typename E>
5145 inline RESULT_INLINE_VISIBILITY constexpr
5146 RESULT_NS_IMPL::result<void, E>::operator bool()
5147  const noexcept
5148 {
5149  return has_value();
5150 }
5151 
5152 template <typename E>
5153 inline RESULT_INLINE_VISIBILITY constexpr
5154 auto RESULT_NS_IMPL::result<void, E>::has_value()
5155  const noexcept -> bool
5156 {
5157  return m_storage.storage.m_has_value;
5158 }
5159 
5160 template <typename E>
5161 inline RESULT_INLINE_VISIBILITY constexpr
5162 auto RESULT_NS_IMPL::result<void, E>::has_error()
5163  const noexcept -> bool
5164 {
5165  return !has_value();
5166 }
5167 
5168 //-----------------------------------------------------------------------------
5169 
5170 template <typename E>
5172 auto RESULT_NS_IMPL::result<void, E>::value()
5173  const & -> void
5174 {
5175  static_cast<void>(
5176  has_value() ||
5177  (detail::throw_bad_result_access(m_storage.storage.m_error), true)
5178  );
5179 }
5180 
5181 template <typename E>
5183 auto RESULT_NS_IMPL::result<void, E>::value()
5184  && -> void
5185 {
5186  static_cast<void>(
5187  has_value() ||
5188  (detail::throw_bad_result_access(static_cast<E&&>(m_storage.storage.m_error)), true)
5189  );
5190 }
5191 
5192 template <typename E>
5193 inline RESULT_INLINE_VISIBILITY constexpr
5194 auto RESULT_NS_IMPL::result<void, E>::error()
5195  const &
5196  noexcept(std::is_nothrow_constructible<E>::value &&
5198 {
5199  return has_value() ? E{} : m_storage.storage.m_error;
5200 }
5201 
5202 template <typename E>
5204 auto RESULT_NS_IMPL::result<void, E>::error()
5205  && noexcept(std::is_nothrow_constructible<E>::value &&
5207 {
5208  return has_value() ? E{} : static_cast<E&&>(m_storage.storage.m_error);
5209 }
5210 
5211 //-----------------------------------------------------------------------------
5212 
5213 template <typename E>
5214 template <typename String, typename>
5216 auto RESULT_NS_IMPL::result<void,E>::expect(String&& message)
5217  const & -> void
5218 {
5219  if (has_error()) {
5220  detail::throw_bad_result_access_message(
5221  detail::forward<String>(message),
5222  m_storage.storage.m_error
5223  );
5224  }
5225 }
5226 
5227 template <typename E>
5228 template <typename String, typename>
5230 auto RESULT_NS_IMPL::result<void,E>::expect(String&& message)
5231  && -> void
5232 {
5233  if (has_error()) {
5234  detail::throw_bad_result_access_message(
5235  detail::forward<String>(message),
5236  static_cast<E&&>(m_storage.storage.m_error)
5237  );
5238  }
5239 }
5240 
5241 //-----------------------------------------------------------------------------
5242 // Monadic Functionalities
5243 //-----------------------------------------------------------------------------
5244 
5245 template <typename E>
5246 template <typename U>
5247 inline RESULT_INLINE_VISIBILITY constexpr
5248 auto RESULT_NS_IMPL::result<void, E>::error_or(U&& default_error)
5249  const & -> error_type
5250 {
5251  return has_value()
5252  ? detail::forward<U>(default_error)
5253  : m_storage.storage.m_error;
5254 }
5255 
5256 template <typename E>
5257 template <typename U>
5259 auto RESULT_NS_IMPL::result<void, E>::error_or(U&& default_error)
5260  && -> error_type
5261 {
5262  return has_value()
5263  ? detail::forward<U>(default_error)
5264  : static_cast<E&&>(m_storage.storage.m_error);
5265 }
5266 
5267 template <typename E>
5268 template <typename U>
5269 inline RESULT_INLINE_VISIBILITY constexpr
5270 auto RESULT_NS_IMPL::result<void, E>::and_then(U&& value)
5271  const -> result<typename std::decay<U>::type,E>
5272 {
5273  return map([&value]{
5274  return detail::forward<U>(value);
5275  });
5276 }
5277 
5278 //-----------------------------------------------------------------------------
5279 
5280 template <typename E>
5281 template <typename Fn>
5282 inline RESULT_INLINE_VISIBILITY constexpr
5283 auto RESULT_NS_IMPL::result<void, E>::flat_map(Fn&& fn)
5284  const & -> detail::invoke_result_t<Fn>
5285 {
5286  using result_type = detail::invoke_result_t<Fn>;
5287 
5288  static_assert(
5289  is_result<result_type>::value,
5290  "flat_map must return a result type or the program is ill-formed"
5291  );
5292 
5293  return has_value()
5294  ? detail::invoke(detail::forward<Fn>(fn))
5295  : result_type(in_place_error, m_storage.storage.m_error);
5296 }
5297 
5298 template <typename E>
5299 template <typename Fn>
5301 auto RESULT_NS_IMPL::result<void, E>::flat_map(Fn&& fn)
5302  && -> detail::invoke_result_t<Fn>
5303 {
5304  using result_type = detail::invoke_result_t<Fn>;
5305 
5306  static_assert(
5307  is_result<result_type>::value,
5308  "flat_map must return a result type or the program is ill-formed"
5309  );
5310 
5311  return has_value()
5312  ? detail::invoke(detail::forward<Fn>(fn))
5313  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
5314 }
5315 
5316 template <typename E>
5317 template <typename Fn>
5318 inline RESULT_INLINE_VISIBILITY constexpr
5319 auto RESULT_NS_IMPL::result<void, E>::map(Fn&& fn)
5320  const & -> result<detail::invoke_result_t<Fn>,E>
5321 {
5322  using result_type = detail::invoke_result_t<Fn>;
5323 
5324  return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
5325 }
5326 
5327 template <typename E>
5328 template <typename Fn>
5330 auto RESULT_NS_IMPL::result<void, E>::map(Fn&& fn)
5331  && -> result<detail::invoke_result_t<Fn>,E>
5332 {
5333  using result_type = detail::invoke_result_t<Fn>;
5334 
5335  return static_cast<result<void,E>&&>(*this).map_impl(
5336  std::is_void<result_type>{},
5337  detail::forward<Fn>(fn)
5338  );
5339 }
5340 
5341 //-----------------------------------------------------------------------------
5342 
5343 template <typename E>
5344 template <typename Fn>
5345 inline RESULT_INLINE_VISIBILITY constexpr
5346 auto RESULT_NS_IMPL::result<void, E>::map_error(Fn&& fn)
5347  const & -> result<void, detail::invoke_result_t<Fn,const E&>>
5348 {
5349  using result_type = result<void, detail::invoke_result_t<Fn, const E&>>;
5350 
5351  return has_value()
5352  ? result_type{}
5353  : result_type(in_place_error, detail::invoke(
5354  detail::forward<Fn>(fn), m_storage.storage.m_error
5355  ));
5356 }
5357 
5358 template <typename E>
5359 template <typename Fn>
5361 auto RESULT_NS_IMPL::result<void, E>::map_error(Fn&& fn)
5362  && -> result<void, detail::invoke_result_t<Fn,E&&>>
5363 {
5364  using result_type = result<void, detail::invoke_result_t<Fn, E&&>>;
5365 
5366  return has_value()
5367  ? result_type{}
5368  : result_type(in_place_error,
5369  detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error)
5370  ));
5371 }
5372 
5373 template <typename E>
5374 template <typename Fn>
5375 inline RESULT_INLINE_VISIBILITY constexpr
5376 auto RESULT_NS_IMPL::result<void, E>::flat_map_error(Fn&& fn)
5377  const & -> detail::invoke_result_t<Fn,const E&>
5378 {
5379  using result_type = detail::invoke_result_t<Fn,const E&>;
5380 
5381  static_assert(
5382  is_result<result_type>::value,
5383  "flat_map_error must return a result type or the program is ill-formed"
5384  );
5385  static_assert(
5386  std::is_default_constructible<typename result_type::value_type>::value,
5387  "flat_map_error for result<void,E> requires the new T type to be default-"
5388  "constructible"
5389  );
5390 
5391  return has_value()
5392  ? result_type{}
5393  : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
5394 }
5395 
5396 template <typename E>
5397 template <typename Fn>
5399 auto RESULT_NS_IMPL::result<void, E>::flat_map_error(Fn&& fn)
5400  && -> detail::invoke_result_t<Fn,E&&>
5401 {
5402  using result_type = detail::invoke_result_t<Fn,E&&>;
5403 
5404  static_assert(
5405  is_result<result_type>::value,
5406  "flat_map_error must return a result type or the program is ill-formed"
5407  );
5408  static_assert(
5409  std::is_default_constructible<typename result_type::value_type>::value,
5410  "flat_map_error for result<void,E> requires the new T type to be default-"
5411  "constructible"
5412  );
5413 
5414  return has_value()
5415  ? result_type{}
5416  : detail::invoke(detail::forward<Fn>(fn), static_cast<E&&>(m_storage.storage.m_error));
5417 }
5418 
5419 //-----------------------------------------------------------------------------
5420 // Private Monadic Functions
5421 //-----------------------------------------------------------------------------
5422 
5423 template <typename E>
5424 template <typename Fn>
5425 inline RESULT_INLINE_VISIBILITY constexpr
5426 auto RESULT_NS_IMPL::result<void, E>::map_impl(std::true_type, Fn&& fn)
5427  const & -> result<void,E>
5428 {
5429  using result_type = result<void, E>;
5430 
5431  return has_value()
5432  ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
5433  : result_type(in_place_error, m_storage.storage.m_error);
5434 }
5435 
5436 template <typename E>
5437 template <typename Fn>
5438 inline RESULT_INLINE_VISIBILITY constexpr
5439 auto RESULT_NS_IMPL::result<void, E>::map_impl(std::false_type, Fn&& fn)
5440  const & -> result<detail::invoke_result_t<Fn>,E>
5441 {
5442  using invoke_result_type = detail::invoke_result_t<Fn>;
5443  using result_type = result<invoke_result_type, E>;
5444 
5445  return has_value()
5446  ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
5447  : result_type(in_place_error, m_storage.storage.m_error);
5448 }
5449 
5450 template <typename E>
5451 template <typename Fn>
5453 auto RESULT_NS_IMPL::result<void, E>::map_impl(std::true_type, Fn&& fn)
5454  && -> result<void,E>
5455 {
5456  using result_type = result<void, E>;
5457 
5458  return has_value()
5459  ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
5460  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
5461 }
5462 
5463 template <typename E>
5464 template <typename Fn>
5466 auto RESULT_NS_IMPL::result<void, E>::map_impl(std::false_type, Fn&& fn)
5467  && -> result<detail::invoke_result_t<Fn>,E>
5468 {
5469  using invoke_result_type = detail::invoke_result_t<Fn>;
5470  using result_type = result<invoke_result_type, E>;
5471 
5472  return has_value()
5473  ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
5474  : result_type(in_place_error, static_cast<E&&>(m_storage.storage.m_error));
5475 }
5476 
5477 //=============================================================================
5478 // non-member functions : class : result
5479 //=============================================================================
5480 
5481 //-----------------------------------------------------------------------------
5482 // Comparison
5483 //-----------------------------------------------------------------------------
5484 
5485 template <typename T1, typename E1, typename T2, typename E2>
5486 inline RESULT_INLINE_VISIBILITY constexpr
5487 auto RESULT_NS_IMPL::operator==(const result<T1,E1>& lhs,
5488  const result<T2,E2>& rhs)
5489  noexcept -> bool
5490 {
5491  return (lhs.has_value() == rhs.has_value())
5492  ? (
5493  lhs.has_value()
5494  ? *lhs == *rhs
5495  : detail::extract_error(lhs) == detail::extract_error(rhs)
5496  )
5497  : false;
5498 }
5499 
5500 template <typename T1, typename E1, typename T2, typename E2>
5501 inline RESULT_INLINE_VISIBILITY constexpr
5502 auto RESULT_NS_IMPL::operator!=(const result<T1,E1>& lhs,
5503  const result<T2,E2>& rhs)
5504  noexcept -> bool
5505 {
5506  return (lhs.has_value() == rhs.has_value())
5507  ? (
5508  lhs.has_value()
5509  ? *lhs != *rhs
5510  : detail::extract_error(lhs) != detail::extract_error(rhs)
5511  )
5512  : true;
5513 }
5514 
5515 template <typename T1, typename E1, typename T2, typename E2>
5516 inline RESULT_INLINE_VISIBILITY constexpr
5517 auto RESULT_NS_IMPL::operator>=(const result<T1,E1>& lhs,
5518  const result<T2,E2>& rhs)
5519  noexcept -> bool
5520 {
5521  return (lhs.has_value() == rhs.has_value())
5522  ? (
5523  lhs.has_value()
5524  ? *lhs >= *rhs
5525  : detail::extract_error(lhs) >= detail::extract_error(rhs)
5526  )
5527  : static_cast<int>(static_cast<bool>(lhs)) >= static_cast<int>(static_cast<bool>(rhs));
5528 }
5529 
5530 template <typename T1, typename E1, typename T2, typename E2>
5531 inline RESULT_INLINE_VISIBILITY constexpr
5532 auto RESULT_NS_IMPL::operator<=(const result<T1,E1>& lhs,
5533  const result<T2,E2>& rhs)
5534  noexcept -> bool
5535 {
5536  return (lhs.has_value() == rhs.has_value())
5537  ? (
5538  lhs.has_value()
5539  ? *lhs <= *rhs
5540  : detail::extract_error(lhs) <= detail::extract_error(rhs)
5541  )
5542  : static_cast<int>(static_cast<bool>(lhs)) <= static_cast<int>(static_cast<bool>(rhs));
5543 }
5544 
5545 template <typename T1, typename E1, typename T2, typename E2>
5546 inline RESULT_INLINE_VISIBILITY constexpr
5547 auto RESULT_NS_IMPL::operator>(const result<T1,E1>& lhs,
5548  const result<T2,E2>& rhs)
5549  noexcept -> bool
5550 {
5551  return (lhs.has_value() == rhs.has_value())
5552  ? (
5553  lhs.has_value()
5554  ? *lhs > *rhs
5555  : detail::extract_error(lhs) > detail::extract_error(rhs)
5556  )
5557  : static_cast<int>(static_cast<bool>(lhs)) > static_cast<int>(static_cast<bool>(rhs));
5558 }
5559 
5560 template <typename T1, typename E1, typename T2, typename E2>
5561 inline RESULT_INLINE_VISIBILITY constexpr
5562 auto RESULT_NS_IMPL::operator<(const result<T1,E1>& lhs,
5563  const result<T2,E2>& rhs)
5564  noexcept -> bool
5565 {
5566  return (lhs.has_value() == rhs.has_value())
5567  ? (
5568  lhs.has_value()
5569  ? *lhs < *rhs
5570  : detail::extract_error(lhs) < detail::extract_error(rhs)
5571  )
5572  : static_cast<int>(static_cast<bool>(lhs)) < static_cast<int>(static_cast<bool>(rhs));
5573 }
5574 
5575 
5576 //-----------------------------------------------------------------------------
5577 
5578 template <typename E1, typename E2>
5579 inline RESULT_INLINE_VISIBILITY constexpr
5580 auto RESULT_NS_IMPL::operator==(const result<void,E1>& lhs,
5581  const result<void,E2>& rhs)
5582  noexcept -> bool
5583 {
5584  return lhs.has_value() == rhs.has_value()
5585  ? (
5586  lhs.has_value()
5587  ? true
5588  : detail::extract_error(lhs) == detail::extract_error(rhs)
5589  )
5590  : false;
5591 }
5592 
5593 template <typename E1, typename E2>
5594 inline RESULT_INLINE_VISIBILITY constexpr
5595 auto RESULT_NS_IMPL::operator!=(const result<void,E1>& lhs,
5596  const result<void,E2>& rhs)
5597  noexcept -> bool
5598 {
5599  return lhs.has_value() == rhs.has_value()
5600  ? (
5601  lhs.has_value()
5602  ? false
5603  : detail::extract_error(lhs) != detail::extract_error(rhs)
5604  )
5605  : true;
5606 }
5607 
5608 template <typename E1, typename E2>
5609 inline RESULT_INLINE_VISIBILITY constexpr
5610 auto RESULT_NS_IMPL::operator>=(const result<void,E1>& lhs,
5611  const result<void,E2>& rhs)
5612  noexcept -> bool
5613 {
5614  return lhs.has_value() == rhs.has_value()
5615  ? (
5616  lhs.has_value()
5617  ? true
5618  : detail::extract_error(lhs) >= detail::extract_error(rhs)
5619  )
5620  : static_cast<int>(static_cast<bool>(lhs)) >= static_cast<int>(static_cast<bool>(rhs));
5621 }
5622 
5623 template <typename E1, typename E2>
5624 inline RESULT_INLINE_VISIBILITY constexpr
5625 auto RESULT_NS_IMPL::operator<=(const result<void,E1>& lhs,
5626  const result<void,E2>& rhs)
5627  noexcept -> bool
5628 {
5629  return lhs.has_value() == rhs.has_value()
5630  ? (
5631  lhs.has_value()
5632  ? true
5633  : detail::extract_error(lhs) <= detail::extract_error(rhs)
5634  )
5635  : static_cast<int>(static_cast<bool>(lhs)) <= static_cast<int>(static_cast<bool>(rhs));
5636 }
5637 
5638 template <typename E1, typename E2>
5639 inline RESULT_INLINE_VISIBILITY constexpr
5640 auto RESULT_NS_IMPL::operator>(const result<void,E1>& lhs,
5641  const result<void,E2>& rhs)
5642  noexcept -> bool
5643 {
5644  return lhs.has_value() == rhs.has_value()
5645  ? (
5646  lhs.has_value()
5647  ? false
5648  : detail::extract_error(lhs) > detail::extract_error(rhs)
5649  )
5650  : static_cast<int>(static_cast<bool>(lhs)) > static_cast<int>(static_cast<bool>(rhs));
5651 }
5652 
5653 template <typename E1, typename E2>
5654 inline RESULT_INLINE_VISIBILITY constexpr
5655 auto RESULT_NS_IMPL::operator<(const result<void,E1>& lhs,
5656  const result<void,E2>& rhs)
5657  noexcept -> bool
5658 {
5659  return lhs.has_value() == rhs.has_value()
5660  ? (
5661  lhs.has_value()
5662  ? false
5663  : detail::extract_error(lhs) < detail::extract_error(rhs)
5664  )
5665  : static_cast<int>(static_cast<bool>(lhs)) < static_cast<int>(static_cast<bool>(rhs));
5666 }
5667 
5668 
5669 //-----------------------------------------------------------------------------
5670 
5671 template <typename T, typename E, typename U, typename>
5672 inline RESULT_INLINE_VISIBILITY constexpr
5673 auto RESULT_NS_IMPL::operator==(const result<T,E>& exp, const U& value)
5674  noexcept -> bool
5675 {
5676  return (exp.has_value() && *exp == value);
5677 }
5678 
5679 template <typename T, typename U, typename E, typename>
5680 inline RESULT_INLINE_VISIBILITY constexpr
5681 auto RESULT_NS_IMPL::operator==(const T& value, const result<U,E>& exp)
5682  noexcept -> bool
5683 {
5684  return (exp.has_value() && *exp == value);
5685 }
5686 
5687 template <typename T, typename E, typename U, typename>
5688 inline RESULT_INLINE_VISIBILITY constexpr
5689 auto RESULT_NS_IMPL::operator!=(const result<T,E>& exp, const U& value)
5690  noexcept -> bool
5691 {
5692  return exp.has_value() ? *exp != value : true;
5693 }
5694 
5695 template <typename T, typename U, typename E, typename>
5696 inline RESULT_INLINE_VISIBILITY constexpr
5697 auto RESULT_NS_IMPL::operator!=(const T& value, const result<U,E>& exp)
5698  noexcept -> bool
5699 {
5700  return exp.has_value() ? value != *exp : true;
5701 }
5702 
5703 template <typename T, typename E, typename U, typename>
5704 inline RESULT_INLINE_VISIBILITY constexpr
5705 auto RESULT_NS_IMPL::operator<=(const result<T,E>& exp, const U& value)
5706  noexcept -> bool
5707 {
5708  return exp.has_value() ? *exp <= value : false;
5709 }
5710 
5711 template <typename T, typename U, typename E, typename>
5712 inline RESULT_INLINE_VISIBILITY constexpr
5713 auto RESULT_NS_IMPL::operator<=(const T& value, const result<U,E>& exp)
5714  noexcept -> bool
5715 {
5716  return exp.has_value() ? value <= *exp : true;
5717 }
5718 
5719 template <typename T, typename E, typename U, typename>
5720 inline RESULT_INLINE_VISIBILITY constexpr
5721 auto RESULT_NS_IMPL::operator>=(const result<T,E>& exp, const U& value)
5722  noexcept -> bool
5723 {
5724  return exp.has_value() ? *exp >= value : true;
5725 }
5726 
5727 template <typename T, typename U, typename E, typename>
5728 inline RESULT_INLINE_VISIBILITY constexpr
5729 auto RESULT_NS_IMPL::operator>=(const T& value, const result<U,E>& exp)
5730  noexcept -> bool
5731 {
5732  return exp.has_value() ? value >= *exp : false;
5733 }
5734 
5735 template <typename T, typename E, typename U, typename>
5736 inline RESULT_INLINE_VISIBILITY constexpr
5737 auto RESULT_NS_IMPL::operator<(const result<T,E>& exp, const U& value)
5738  noexcept -> bool
5739 {
5740  return exp.has_value() ? *exp < value : false;
5741 }
5742 
5743 template <typename T, typename U, typename E, typename>
5744 inline RESULT_INLINE_VISIBILITY constexpr
5745 auto RESULT_NS_IMPL::operator<(const T& value, const result<U,E>& exp)
5746  noexcept -> bool
5747 {
5748  return exp.has_value() ? value < *exp : true;
5749 }
5750 
5751 template <typename T, typename E, typename U, typename>
5752 inline RESULT_INLINE_VISIBILITY constexpr
5753 auto RESULT_NS_IMPL::operator>(const result<T,E>& exp, const U& value)
5754  noexcept -> bool
5755 {
5756  return exp.has_value() ? *exp > value : false;
5757 }
5758 
5759 template <typename T, typename U, typename E, typename>
5760 inline RESULT_INLINE_VISIBILITY constexpr
5761 auto RESULT_NS_IMPL::operator>(const T& value, const result<U,E>& exp)
5762  noexcept -> bool
5763 {
5764  return exp.has_value() ? value > *exp : true;
5765 }
5766 
5767 //-----------------------------------------------------------------------------
5768 
5769 template <typename T, typename E, typename U>
5770 inline RESULT_INLINE_VISIBILITY constexpr
5771 auto RESULT_NS_IMPL::operator==(const result<T,E>& exp, const failure<U>& error)
5772  noexcept -> bool
5773 {
5774  return exp.has_error() ? detail::extract_error(exp) == error.error() : false;
5775 }
5776 
5777 template <typename T, typename U, typename E>
5778 inline RESULT_INLINE_VISIBILITY constexpr
5779 auto RESULT_NS_IMPL::operator==(const failure<T>& error, const result<E,U>& exp)
5780  noexcept -> bool
5781 {
5782  return exp.has_error() ? error.error() == detail::extract_error(exp) : false;
5783 }
5784 
5785 template <typename T, typename E, typename U>
5786 inline RESULT_INLINE_VISIBILITY constexpr
5787 auto RESULT_NS_IMPL::operator!=(const result<T,E>& exp, const failure<U>& error)
5788  noexcept -> bool
5789 {
5790  return exp.has_error() ? detail::extract_error(exp) != error.error() : true;
5791 }
5792 
5793 template <typename T, typename U, typename E>
5794 inline RESULT_INLINE_VISIBILITY constexpr
5795 auto RESULT_NS_IMPL::operator!=(const failure<T>& error, const result<E,U>& exp)
5796  noexcept -> bool
5797 {
5798  return exp.has_error() ? error.error() != detail::extract_error(exp) : true;
5799 }
5800 
5801 template <typename T, typename E, typename U>
5802 inline RESULT_INLINE_VISIBILITY constexpr
5803 auto RESULT_NS_IMPL::operator<=(const result<T,E>& exp, const failure<U>& error)
5804  noexcept -> bool
5805 {
5806  return exp.has_error() ? detail::extract_error(exp) <= error.error() : true;
5807 }
5808 
5809 template <typename T, typename U, typename E>
5810 inline RESULT_INLINE_VISIBILITY constexpr
5811 auto RESULT_NS_IMPL::operator<=(const failure<T>& error, const result<E,U>& exp)
5812  noexcept -> bool
5813 {
5814  return exp.has_error() ? error.error() <= detail::extract_error(exp) : false;
5815 }
5816 
5817 template <typename T, typename E, typename U>
5818 inline RESULT_INLINE_VISIBILITY constexpr
5819 auto RESULT_NS_IMPL::operator>=(const result<T,E>& exp, const failure<U>& error)
5820  noexcept -> bool
5821 {
5822  return exp.has_error() ? detail::extract_error(exp) >= error.error() : false;
5823 }
5824 
5825 template <typename T, typename U, typename E>
5826 inline RESULT_INLINE_VISIBILITY constexpr
5827 auto RESULT_NS_IMPL::operator>=(const failure<T>& error, const result<E,U>& exp)
5828  noexcept -> bool
5829 {
5830  return exp.has_error() ? error.error() >= detail::extract_error(exp) : true;
5831 }
5832 
5833 template <typename T, typename E, typename U>
5834 inline RESULT_INLINE_VISIBILITY constexpr
5835 auto RESULT_NS_IMPL::operator<(const result<T,E>& exp, const failure<U>& error)
5836  noexcept -> bool
5837 {
5838  return exp.has_error() ? detail::extract_error(exp) < error.error() : true;
5839 }
5840 
5841 template <typename T, typename U, typename E>
5842 inline RESULT_INLINE_VISIBILITY constexpr
5843 auto RESULT_NS_IMPL::operator<(const failure<T>& error, const result<E,U>& exp)
5844  noexcept -> bool
5845 {
5846  return exp.has_error() ? error.error() < detail::extract_error(exp) : false;
5847 }
5848 
5849 template <typename T, typename E, typename U>
5850 inline RESULT_INLINE_VISIBILITY constexpr
5851 auto RESULT_NS_IMPL::operator>(const result<T,E>& exp, const failure<U>& error)
5852  noexcept -> bool
5853 {
5854  return exp.has_error() ? detail::extract_error(exp) > error.error() : false;
5855 }
5856 
5857 template <typename T, typename U, typename E>
5858 inline RESULT_INLINE_VISIBILITY constexpr
5859 auto RESULT_NS_IMPL::operator>(const failure<T>& error, const result<E,U>& exp)
5860  noexcept -> bool
5861 {
5862  return exp.has_error() ? error.error() > detail::extract_error(exp) : true;
5863 }
5864 
5865 //-----------------------------------------------------------------------------
5866 // Utilities
5867 //-----------------------------------------------------------------------------
5868 
5869 template <typename T, typename E>
5871 auto RESULT_NS_IMPL::swap(result<T,E>& lhs, result<T,E>& rhs)
5872 #if __cplusplus >= 201703L
5877 #else
5880 #endif
5881  -> void
5882 {
5883  using std::swap;
5884 
5885  if (lhs.has_value() == rhs.has_value()) {
5886  if (lhs.has_value()) {
5887  swap(*lhs, *rhs);
5888  } else {
5889  auto& lhs_error = detail::result_error_extractor::get(lhs);
5890  auto& rhs_error = detail::result_error_extractor::get(rhs);
5891 
5892  swap(lhs_error, rhs_error);
5893  }
5894  // If both `result`s contain values, do nothing
5895  } else {
5896  auto temp = static_cast<result<T,E>&&>(lhs);
5897  lhs = static_cast<result<T,E>&&>(rhs);
5898  rhs = static_cast<result<T,E>&&>(temp);
5899  }
5900 }
5901 
5902 template <typename E>
5904 auto RESULT_NS_IMPL::swap(result<void,E>& lhs, result<void,E>& rhs)
5905 #if __cplusplus >= 201703L
5906  noexcept(std::is_nothrow_move_constructible<result<void,E>>::value &&
5909 #else
5910  noexcept(std::is_nothrow_move_constructible<result<void,E>>::value &&
5912 #endif
5913  -> void
5914 {
5915  using std::swap;
5916 
5917  if (lhs.has_value() == rhs.has_value()) {
5918  if (lhs.has_error()) {
5919  auto& lhs_error = detail::result_error_extractor::get(lhs);
5920  auto& rhs_error = detail::result_error_extractor::get(rhs);
5921 
5922  swap(lhs_error, rhs_error);
5923  }
5924  // If both `result`s contain values, do nothing
5925  } else {
5926  auto temp = static_cast<result<void,E>&&>(lhs);
5927  lhs = static_cast<result<void,E>&&>(rhs);
5928  rhs = static_cast<result<void,E>&&>(temp);
5929  }
5930 }
5931 
5932 #if defined(__clang__)
5933 # pragma clang diagnostic pop
5934 #endif
5935 
5936 #undef RESULT_NAMESPACE_INTERNAL
5937 #undef RESULT_NS_IMPL
5938 #undef RESULT_CPP14_CONSTEXPR
5939 #undef RESULT_CPP17_INLINE
5940 #undef RESULT_INLINE_VISIBILITY
5941 #undef RESULT_NODISCARD
5942 #undef RESULT_WARN_UNUSED
5943 
5944 #endif /* RESULT_RESULT_HPP */
RESULT_CPP14_CONSTEXPR auto error() &noexcept -> typename std::add_lvalue_reference< E >::type
Gets the underlying error.
#define RESULT_NS_IMPL
Definition: result.hpp:93
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto operator->() noexcept -> typename std::remove_reference< T >::type *
Retrieves a pointer to the contained value.
constexpr failure(E2 &&error) noexcept(std::is_nothrow_constructible< E, E2 >::value)
Constructs a failure from the given error.
RESULT_WARN_UNUSED constexpr auto fail(Args &&...args) noexcept(std::is_nothrow_constructible< E, Args... >::value) -> failure< E >
Constructs a failure type from a series of arguments.
constexpr result(in_place_t) noexcept
Constructs a result object in a value state.
bad_result_access(E2 &&error)
Constructs this exception using the underlying error type for the error type.
failure(failure &&other)=default
Constructs this failure by moving the contents of an existing one.
constexpr result(result &&other)=default
Move constructs a result.
RESULT_WARN_UNUSED constexpr 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.
auto error() &&noexcept -> E &&
Gets the underlying 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. ...
constexpr result() noexcept(std::is_nothrow_constructible< U >::value)
Default-constructs a result with the underlying value type active.
RESULT_WARN_UNUSED constexpr 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.
constexpr result(in_place_error_t, Args &&... args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
Constructs a result object that contains an error.
#define RESULT_NODISCARD
Definition: result.hpp:85
RESULT_WARN_UNUSED constexpr auto map(Fn &&fn) const &-> result< detail::invoke_result_t< Fn >, E >
Invokes the function fn if (*this) contains no value.
RESULT_WARN_UNUSED constexpr auto has_value() const noexcept -> bool
Returns true if *this contains a value.
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.
constexpr result() noexcept
Constructs a result object in a value state.
constexpr result(const result &other)=default
Copy constructs this 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.
auto operator=(failure< E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 &&>::value) -> result &
Perfect-forwarded assignment.
constexpr result(const failure< E2 > &e) noexcept(std::is_nothrow_constructible< E, const E2 &>::value)
Constructs the underlying error of this result.
#define RESULT_CPP17_INLINE
Definition: result.hpp:59
constexpr result(const result &other)=default
Copy constructs this result.
#define RESULT_WARN_UNUSED
Definition: result.hpp:84
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.
constexpr result(in_place_t, Args &&... args) noexcept(std::is_nothrow_constructible< T, Args... >::value)
Constructs a result object that contains a value.
auto error() const &noexcept -> const E &
Gets the underlying error.
RESULT_WARN_UNUSED constexpr auto has_error() const noexcept -> bool
Returns true if *this contains an error.
auto operator=(U &&value) noexcept(std::is_nothrow_assignable< T, U >::value) -> result &
Perfect-forwarded assignment.
A structure for representing in-place construction of an error type.
Definition: result.hpp:294
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.
RESULT_WARN_UNUSED constexpr 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...
RESULT_WARN_UNUSED constexpr operator bool() const noexcept
Contextually convertible to true if *this does not contain an error.
RESULT_WARN_UNUSED constexpr auto error_or(U &&default_error) const &-> error_type
Returns the contained error if *this has an error, otherwise returns default_error.
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.
constexpr result(in_place_error_t, Args &&... args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
Constructs a result object that contains an 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.
RESULT_WARN_UNUSED constexpr auto flat_map(Fn &&fn) const &-> detail::invoke_result_t< Fn >
Invokes the function fn if (*this) contains no value.
result(result< U, E2 > &&other) noexcept(std::is_nothrow_constructible< E, E2 &&>::value)
Converting move constructor.
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.
auto operator=(result &&other) -> result &=default
Move assigns the result stored in other.
result(const result< U, E2 > &other) noexcept(std::is_nothrow_constructible< E, const E2 &>::value)
Converting copy constructor.
result(result< T2, E2 > &&other) noexcept(std::is_nothrow_constructible< T, T2 &&>::value &&std::is_nothrow_constructible< E, E2 &&>::value)
Converting move constructor.
constexpr result(failure< E2 > &&e) noexcept(std::is_nothrow_constructible< E, E2 &&>::value)
Constructs the underlying error of this result.
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. ...
auto operator=(const failure &other) -> failure &=default
Assigns the contents of other to this by copy-assignment.
bad_result_access(const char *what_arg, E2 &&error)
Constructs this exception using the underlying error type for the error and a message.
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.
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.
auto operator=(const result< void, E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 &>::value) -> result &
Copy-converts the state of other.
RESULT_CPP14_CONSTEXPR auto error() &&noexcept -> typename std::add_rvalue_reference< E >::type
Gets the underlying error.
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_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.
RESULT_CPP14_CONSTEXPR auto value() &&-> void
Throws an exception if (*this) is in an error state.
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.
auto operator=(failure &&other) -> failure &=default
Assigns the contents of other to this by move-assignment.
constexpr result(failure< E2 > &&e) noexcept(std::is_nothrow_constructible< E, E2 &&>::value)
Constructs the underlying error of this result.
auto operator=(const failure< E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 &>::value) -> result &
Perfect-forwarded assignment.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto operator*() &noexcept -> typename std::add_lvalue_reference< T >::type
Retrieves a reference to the contained value.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto value() &&-> typename std::add_rvalue_reference< T >::type
Returns a reference to the contained value.
A structure for representing in-place construction.
Definition: result.hpp:282
RESULT_CPP14_CONSTEXPR auto expect(String &&message) const &-> void
}
#define RESULT_NAMESPACE_INTERNAL
Definition: result.hpp:91
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.
auto operator=(const failure< E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 &>::value) -> result &
Perfect-forwarded assignment.
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.
auto error() &noexcept -> E &
Gets the underlying error.
#define RESULT_INLINE_VISIBILITY
Definition: result.hpp:69
constexpr failure(failure< E2 > &&other) noexcept(std::is_nothrow_constructible< E, E2 &&>::value)
Constructs this failure by move-converting other.
RESULT_CPP14_CONSTEXPR auto value() const &-> void
Throws an exception if (*this) is in an error state.
auto operator=(result &&other) -> result &=default
Move assigns the result stored in other.
auto operator=(const result &other) -> result &=default
Copy assigns the result stored in other.
RESULT_WARN_UNUSED constexpr 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.
RESULT_CPP14_CONSTEXPR auto expect(String &&message) &&-> void
}
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.
constexpr auto error() const &noexcept -> typename std::add_lvalue_reference< typename std::add_const< E >::type >::type
Gets the underlying error.
constexpr result(result &&other)=default
Move constructs a result.
auto error() const &&noexcept -> const E &&
Gets the underlying error.
auto swap(failure< E > &lhs, failure< E > &rhs) noexcept(std::is_nothrow_move_constructible< E >::value) -> void
Swaps the contents of two failure values.
auto operator=(result< void, E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 &&>::value) -> result &
Move-converts the state of other.
constexpr result(U &&value) noexcept(std::is_nothrow_constructible< T, U >::value)
Constructs a result object that contains a value.
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.
auto operator=(const result &other) -> result &=default
Copy assigns the result stored in other.
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.
RESULT_WARN_UNUSED constexpr 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. ...
RESULT_WARN_UNUSED constexpr auto fail(std::reference_wrapper< E > e) noexcept -> failure< E &>
Deduces a failure reference from a reverence_wrapper.
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.
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.
RESULT_WARN_UNUSED constexpr auto operator->() const noexcept -> typename std::remove_reference< typename std::add_const< T >::type >::type *
Retrieves a pointer to the contained value.
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.
constexpr auto error() const &&noexcept -> typename std::add_rvalue_reference< typename std::add_const< E >::type >::type
Gets the underlying error.
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.
failure()=default
Constructs a failure via default construction.
failure(const failure &other)=default
Constructs this failure by copying the contents of an existing one.
constexpr failure(const failure< E2 > &other) noexcept(std::is_nothrow_constructible< E, const E2 &>::value)
Constructs this failure by copy-converting other.
constexpr result(const failure< E2 > &e) noexcept(std::is_nothrow_constructible< E, const E2 &>::value)
Constructs the underlying error of this result.
#define RESULT_CPP14_CONSTEXPR
Definition: result.hpp:53
auto operator=(failure< E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 &&>::value) -> result &
Perfect-forwarded assignment.