@@ -752,31 +752,55 @@ constexpr void expected<T, E>::swap(expected& rhs) noexcept(std::is_nothrow_move
752752
753753template <class T , class E >
754754constexpr const T* expected<T, E>::operator ->() const noexcept {
755+ #if defined(BEMAN_EXPECTED_HARDENED)
756+ if (!has_val_)
757+ __builtin_trap ();
758+ #endif
755759 return std::addressof (val_);
756760}
757761
758762template <class T , class E >
759763constexpr T* expected<T, E>::operator ->() noexcept {
764+ #if defined(BEMAN_EXPECTED_HARDENED)
765+ if (!has_val_)
766+ __builtin_trap ();
767+ #endif
760768 return std::addressof (val_);
761769}
762770
763771template <class T , class E >
764772constexpr const T& expected<T, E>::operator *() const & noexcept {
773+ #if defined(BEMAN_EXPECTED_HARDENED)
774+ if (!has_val_)
775+ __builtin_trap ();
776+ #endif
765777 return val_;
766778}
767779
768780template <class T , class E >
769781constexpr T& expected<T, E>::operator *() & noexcept {
782+ #if defined(BEMAN_EXPECTED_HARDENED)
783+ if (!has_val_)
784+ __builtin_trap ();
785+ #endif
770786 return val_;
771787}
772788
773789template <class T , class E >
774790constexpr const T&& expected<T, E>::operator *() const && noexcept {
791+ #if defined(BEMAN_EXPECTED_HARDENED)
792+ if (!has_val_)
793+ __builtin_trap ();
794+ #endif
775795 return std::move (val_);
776796}
777797
778798template <class T , class E >
779799constexpr T&& expected<T, E>::operator *() && noexcept {
800+ #if defined(BEMAN_EXPECTED_HARDENED)
801+ if (!has_val_)
802+ __builtin_trap ();
803+ #endif
780804 return std::move (val_);
781805}
782806
@@ -826,21 +850,37 @@ constexpr T&& expected<T, E>::value() && {
826850
827851template <class T , class E >
828852constexpr const E& expected<T, E>::error() const & noexcept {
853+ #if defined(BEMAN_EXPECTED_HARDENED)
854+ if (has_val_)
855+ __builtin_trap ();
856+ #endif
829857 return unex_;
830858}
831859
832860template <class T , class E >
833861constexpr E& expected<T, E>::error() & noexcept {
862+ #if defined(BEMAN_EXPECTED_HARDENED)
863+ if (has_val_)
864+ __builtin_trap ();
865+ #endif
834866 return unex_;
835867}
836868
837869template <class T , class E >
838870constexpr const E&& expected<T, E>::error() const && noexcept {
871+ #if defined(BEMAN_EXPECTED_HARDENED)
872+ if (has_val_)
873+ __builtin_trap ();
874+ #endif
839875 return std::move (unex_);
840876}
841877
842878template <class T , class E >
843879constexpr E&& expected<T, E>::error() && noexcept {
880+ #if defined(BEMAN_EXPECTED_HARDENED)
881+ if (has_val_)
882+ __builtin_trap ();
883+ #endif
844884 return std::move (unex_);
845885}
846886
@@ -1304,15 +1344,44 @@ class expected<T, E> {
13041344 constexpr explicit operator bool () const noexcept { return has_val_; }
13051345 constexpr bool has_value () const noexcept { return has_val_; }
13061346
1307- constexpr void operator *() const noexcept {}
1347+ constexpr void operator *() const noexcept {
1348+ #if defined(BEMAN_EXPECTED_HARDENED)
1349+ if (!has_val_)
1350+ __builtin_trap ();
1351+ #endif
1352+ }
13081353
13091354 constexpr void value () const &;
13101355 constexpr void value () &&;
13111356
1312- constexpr const E& error () const & noexcept { return unex_; }
1313- constexpr E& error () & noexcept { return unex_; }
1314- constexpr const E&& error() const && noexcept { return std::move (unex_); }
1315- constexpr E&& error() && noexcept { return std::move (unex_); }
1357+ constexpr const E& error () const & noexcept {
1358+ #if defined(BEMAN_EXPECTED_HARDENED)
1359+ if (has_val_)
1360+ __builtin_trap ();
1361+ #endif
1362+ return unex_;
1363+ }
1364+ constexpr E& error () & noexcept {
1365+ #if defined(BEMAN_EXPECTED_HARDENED)
1366+ if (has_val_)
1367+ __builtin_trap ();
1368+ #endif
1369+ return unex_;
1370+ }
1371+ constexpr const E&& error() const && noexcept {
1372+ #if defined(BEMAN_EXPECTED_HARDENED)
1373+ if (has_val_)
1374+ __builtin_trap ();
1375+ #endif
1376+ return std::move (unex_);
1377+ }
1378+ constexpr E&& error() && noexcept {
1379+ #if defined(BEMAN_EXPECTED_HARDENED)
1380+ if (has_val_)
1381+ __builtin_trap ();
1382+ #endif
1383+ return std::move (unex_);
1384+ }
13161385
13171386 template <class G = E>
13181387 constexpr E error_or (G&& def) const &;
@@ -1715,7 +1784,8 @@ template <class F>
17151784constexpr auto expected<T, E>::or_else(F&& f) & {
17161785 using G = std::remove_cvref_t <std::invoke_result_t <F, E&>>;
17171786 static_assert (detail::is_expected_specialization<G>::value, " or_else: F must return a specialization of expected" );
1718- static_assert (std::is_void_v<typename G::value_type>, " or_else: F must return expected with void value_type" );
1787+ static_assert (std::is_same_v<typename G::value_type, T>,
1788+ " or_else: F must return expected with the same value_type" );
17191789 if (has_val_)
17201790 return G ();
17211791 return std::invoke (std::forward<F>(f), unex_);
@@ -1727,7 +1797,8 @@ template <class F>
17271797constexpr auto expected<T, E>::or_else(F&& f) && {
17281798 using G = std::remove_cvref_t <std::invoke_result_t <F, E&&>>;
17291799 static_assert (detail::is_expected_specialization<G>::value, " or_else: F must return a specialization of expected" );
1730- static_assert (std::is_void_v<typename G::value_type>, " or_else: F must return expected with void value_type" );
1800+ static_assert (std::is_same_v<typename G::value_type, T>,
1801+ " or_else: F must return expected with the same value_type" );
17311802 if (has_val_)
17321803 return G ();
17331804 return std::invoke (std::forward<F>(f), std::move (unex_));
@@ -1739,7 +1810,8 @@ template <class F>
17391810constexpr auto expected<T, E>::or_else(F&& f) const & {
17401811 using G = std::remove_cvref_t <std::invoke_result_t <F, const E&>>;
17411812 static_assert (detail::is_expected_specialization<G>::value, " or_else: F must return a specialization of expected" );
1742- static_assert (std::is_void_v<typename G::value_type>, " or_else: F must return expected with void value_type" );
1813+ static_assert (std::is_same_v<typename G::value_type, T>,
1814+ " or_else: F must return expected with the same value_type" );
17431815 if (has_val_)
17441816 return G ();
17451817 return std::invoke (std::forward<F>(f), unex_);
@@ -1751,7 +1823,8 @@ template <class F>
17511823constexpr auto expected<T, E>::or_else(F&& f) const && {
17521824 using G = std::remove_cvref_t <std::invoke_result_t <F, const E&&>>;
17531825 static_assert (detail::is_expected_specialization<G>::value, " or_else: F must return a specialization of expected" );
1754- static_assert (std::is_void_v<typename G::value_type>, " or_else: F must return expected with void value_type" );
1826+ static_assert (std::is_same_v<typename G::value_type, T>,
1827+ " or_else: F must return expected with the same value_type" );
17551828 if (has_val_)
17561829 return G ();
17571830 return std::invoke (std::forward<F>(f), std::move (unex_));
@@ -1872,8 +1945,8 @@ constexpr auto expected<T, E>::transform_error(F&& f) & {
18721945 static_assert (!detail::is_unexpected_specialization<G>::value,
18731946 " transform_error: G must not be a specialization of unexpected" );
18741947 if (has_val_)
1875- return expected<void , G>();
1876- return expected<void , G>(unexpect, std::invoke (std::forward<F>(f), unex_));
1948+ return expected<T , G>();
1949+ return expected<T , G>(unexpect, std::invoke (std::forward<F>(f), unex_));
18771950}
18781951
18791952template <class T , class E >
@@ -1887,8 +1960,8 @@ constexpr auto expected<T, E>::transform_error(F&& f) && {
18871960 static_assert (!detail::is_unexpected_specialization<G>::value,
18881961 " transform_error: G must not be a specialization of unexpected" );
18891962 if (has_val_)
1890- return expected<void , G>();
1891- return expected<void , G>(unexpect, std::invoke (std::forward<F>(f), std::move (unex_)));
1963+ return expected<T , G>();
1964+ return expected<T , G>(unexpect, std::invoke (std::forward<F>(f), std::move (unex_)));
18921965}
18931966
18941967template <class T , class E >
@@ -1902,8 +1975,8 @@ constexpr auto expected<T, E>::transform_error(F&& f) const& {
19021975 static_assert (!detail::is_unexpected_specialization<G>::value,
19031976 " transform_error: G must not be a specialization of unexpected" );
19041977 if (has_val_)
1905- return expected<void , G>();
1906- return expected<void , G>(unexpect, std::invoke (std::forward<F>(f), unex_));
1978+ return expected<T , G>();
1979+ return expected<T , G>(unexpect, std::invoke (std::forward<F>(f), unex_));
19071980}
19081981
19091982template <class T , class E >
@@ -1917,8 +1990,8 @@ constexpr auto expected<T, E>::transform_error(F&& f) const&& {
19171990 static_assert (!detail::is_unexpected_specialization<G>::value,
19181991 " transform_error: G must not be a specialization of unexpected" );
19191992 if (has_val_)
1920- return expected<void , G>();
1921- return expected<void , G>(unexpect, std::invoke (std::forward<F>(f), std::move (unex_)));
1993+ return expected<T , G>();
1994+ return expected<T , G>(unexpect, std::invoke (std::forward<F>(f), std::move (unex_)));
19221995}
19231996
19241997} // namespace expected
0 commit comments