1197class ICEBERG_TEMPLATE_CLASS_EXPORT [[nodiscard]]
expected
1200 static_assert(expected_detail::is_value_type_valid_v<T>);
1201 static_assert(expected_detail::is_error_type_valid_v<E>);
1203 constexpr T* valptr()
noexcept {
return std::addressof(this->m_val); }
1204 constexpr const T* valptr()
const noexcept {
return std::addressof(this->m_val); }
1205 constexpr E* errptr()
noexcept {
return std::addressof(this->m_unexpect); }
1206 constexpr const E* errptr()
const noexcept {
return std::addressof(this->m_unexpect); }
1208 constexpr T& val()
noexcept {
return this->m_val; }
1209 constexpr E& err()
noexcept {
return this->m_unexpect; }
1211 constexpr const T& val()
const noexcept {
return this->m_val; }
1212 constexpr const E& err()
const noexcept {
return this->m_unexpect; }
1218 typedef T value_type;
1219 typedef E error_type;
1234 template <
class U,
class G,
1235 std::enable_if_t<!std::is_same_v<expected<U, G>,
expected>>* =
nullptr,
1236 std::enable_if_t<std::is_convertible_v<const U&, T> &&
1237 std::is_convertible_v<const G&, E>>* =
nullptr,
1238 expected_detail::enable_from_other_expected_t<T, E, U, G,
const U&,
1239 const G&>* =
nullptr>
1241 std::is_nothrow_constructible_v<T, const U&> &&
1242 std::is_nothrow_constructible_v<E, const G&>)
1243 :
impl_base(expected_detail::construct_from_expected, rhs),
1247 template <
class U,
class G,
1248 std::enable_if_t<!std::is_same_v<expected<U, G>,
expected>>* =
nullptr,
1249 std::enable_if_t<!(std::is_convertible_v<const U&, T> &&
1250 std::is_convertible_v<const G&, E>)>* =
nullptr,
1251 expected_detail::enable_from_other_expected_t<T, E, U, G,
const U&,
1252 const G&>* =
nullptr>
1254 std::is_nothrow_constructible_v<T, const U&> &&
1255 std::is_nothrow_constructible_v<E, const G&>)
1256 :
impl_base(expected_detail::construct_from_expected, rhs),
1260 template <
class U,
class G,
1261 std::enable_if_t<!std::is_same_v<expected<U, G>,
expected>>* =
nullptr,
1262 std::enable_if_t<std::is_convertible_v<U, T> &&
1263 std::is_convertible_v<G, E>>* =
nullptr,
1264 expected_detail::enable_from_other_expected_t<T, E, U, G, U, G>* =
nullptr>
1266 std::is_nothrow_constructible_v<T, U> && std::is_nothrow_constructible_v<E, G>)
1267 :
impl_base(expected_detail::construct_from_expected, std::move(rhs)),
1271 template <
class U,
class G,
1272 std::enable_if_t<!std::is_same_v<expected<U, G>,
expected>>* =
nullptr,
1273 std::enable_if_t<!(std::is_convertible_v<U, T> &&
1274 std::is_convertible_v<G, E>)>* =
nullptr,
1275 expected_detail::enable_from_other_expected_t<T, E, U, G, U, G>* =
nullptr>
1277 std::is_nothrow_constructible_v<T, U> && std::is_nothrow_constructible_v<E, G>)
1278 :
impl_base(expected_detail::construct_from_expected, std::move(rhs)),
1285 template <
class U = std::remove_cv_t<T>,
1286 std::enable_if_t<std::is_convertible_v<U, T>>* =
nullptr,
1287 expected_detail::enable_forward_t<T, E, U>* =
nullptr>
1288 constexpr expected(U&& v)
noexcept(std::is_nothrow_constructible_v<T, U>)
1289 :
expected(std::in_place, std::forward<U>(v)) {}
1292 template <
class U = std::remove_cv_t<T>,
1293 std::enable_if_t<!std::is_convertible_v<U, T>>* =
nullptr,
1294 expected_detail::enable_forward_t<T, E, U>* =
nullptr>
1295 constexpr explicit expected(U&& v)
noexcept(std::is_nothrow_constructible_v<T, U>)
1296 :
expected(std::in_place, std::forward<U>(v)) {}
1298#if !ICEBERG_CXX20_COMPAT && defined(__cpp_lib_expected) && __cpp_lib_expected >= 202202L
1300 template <
class G, std::enable_if_t<std::is_constructible_v<E, const G&>>* =
nullptr>
1301 constexpr explicit(!std::is_convertible_v<const G&, E>)
expected(
1302 const std::unexpected<G>& e)
noexcept(std::is_nothrow_constructible_v<E, const G&>)
1305 template <
class G, std::enable_if_t<std::is_constructible_v<E, G>>* =
nullptr>
1306 constexpr explicit(!std::is_convertible_v<G, E>)
1307 expected(std::unexpected<G>&& e)
noexcept(std::is_nothrow_constructible_v<E, G>)
1308 :
expected(unexpect, std::move(e.error())) {}
1314 template <
class G, std::enable_if_t<!std::is_convertible_v<const G&, E>>* =
nullptr,
1315 std::enable_if_t<std::is_constructible_v<E, const G&>>* =
nullptr>
1317 std::is_nothrow_constructible_v<E, const G&>)
1322 template <
class G, std::enable_if_t<std::is_convertible_v<const G&, E>>* =
nullptr,
1323 std::enable_if_t<std::is_constructible_v<E, const G&>>* =
nullptr>
1325 std::is_nothrow_constructible_v<E, const G&>)
1330 template <
class G, std::enable_if_t<!std::is_convertible_v<G, E>>* =
nullptr,
1331 std::enable_if_t<std::is_constructible_v<E, G>>* =
nullptr>
1333 std::is_nothrow_constructible_v<E, G>)
1334 :
impl_base(unexpect, std::move(e.error())),
1338 template <
class G, std::enable_if_t<std::is_convertible_v<G, E>>* =
nullptr,
1339 std::enable_if_t<std::is_constructible_v<E, G>>* =
nullptr>
1341 :
impl_base(unexpect, std::move(e.error())),
1347 template <
class... Args,
1348 std::enable_if_t<std::is_constructible_v<T, Args...>>* =
nullptr>
1349 constexpr explicit expected(std::in_place_t, Args&&... args)
noexcept(
1350 std::is_nothrow_constructible_v<T, Args...>)
1351 :
impl_base(std::in_place, std::forward<Args>(args)...),
1357 template <
class U,
class... Args,
1358 std::enable_if_t<std::is_constructible_v<T, std::initializer_list<U>&,
1359 Args...>>* =
nullptr>
1361 std::in_place_t, std::initializer_list<U> il,
1362 Args&&... args)
noexcept(std::is_nothrow_constructible_v<T,
1363 std::initializer_list<U>&,
1365 :
impl_base(std::in_place, il, std::forward<Args>(args)...),
1369 template <
class Fn,
class... Args>
1372 Args&&... args)
noexcept(
noexcept(
static_cast<T
>(std::invoke(std::forward<Fn>(func),
1375 :
impl_base(tag, std::forward<Fn>(func), std::forward<Args>(args)...),
1381 template <
class... Args,
1382 std::enable_if_t<std::is_constructible_v<E, Args...>>* =
nullptr>
1384 std::is_nothrow_constructible_v<E, Args...>)
1385 :
impl_base(unexpect, std::forward<Args>(args)...),
1391 template <
class U,
class... Args,
1392 std::enable_if_t<std::is_constructible_v<E, std::initializer_list<U>&,
1393 Args...>>* =
nullptr>
1396 Args&&... args)
noexcept(std::is_nothrow_constructible_v<E,
1397 std::initializer_list<U>&,
1399 :
impl_base(unexpect, il, std::forward<Args>(args)...),
1403 template <
class Fn,
class... Args>
1406 Args&&... args)
noexcept(
noexcept(
static_cast<E
>(std::invoke(std::forward<Fn>(func),
1409 :
impl_base(tag1, tag2, std::forward<Fn>(func), std::forward<Args>(args)...),
1420 class U = std::remove_cv_t<T>,
1421 std::enable_if_t<!std::is_same_v<expected, expected_detail::remove_cvref_t<U>> &&
1422 !expected_detail::is_specialization_v<
1423 expected_detail::remove_cvref_t<U>,
unexpected> &&
1424 std::is_constructible_v<T, U> && std::is_assignable_v<T&, U> &&
1425 (std::is_nothrow_constructible_v<T, U> ||
1426 std::is_nothrow_move_constructible_v<T> ||
1427 std::is_nothrow_move_constructible_v<E>)>* =
nullptr>
1428 constexpr expected&
operator=(U&& v)
noexcept(std::is_nothrow_constructible_v<T, U> &&
1429 std::is_nothrow_assignable_v<T&, U>) {
1431 val() = std::forward<U>(v);
1433 expected_detail::reinit_expected(val(), err(), std::forward<U>(v));
1434 this->m_has_val =
true;
1441 class G,
class GF =
const G&,
1442 std::enable_if_t<std::is_constructible_v<E, GF> && std::is_assignable_v<E&, GF> &&
1443 (std::is_nothrow_constructible_v<E, GF> ||
1444 std::is_nothrow_move_constructible_v<T> ||
1445 std::is_nothrow_move_constructible_v<E>)>* =
nullptr>
1447 std::is_nothrow_constructible_v<E, GF> && std::is_nothrow_assignable_v<E&, GF>) {
1449 err() = std::forward<GF>(rhs.error());
1451 expected_detail::reinit_expected(err(), val(), std::forward<GF>(rhs.error()));
1452 this->m_has_val =
false;
1459 class G,
class GF = G,
1460 std::enable_if_t<std::is_constructible_v<E, GF> && std::is_assignable_v<E&, GF> &&
1461 (std::is_nothrow_constructible_v<E, GF> ||
1462 std::is_nothrow_move_constructible_v<T> ||
1463 std::is_nothrow_move_constructible_v<E>)>* =
nullptr>
1465 std::is_nothrow_constructible_v<E, GF> && std::is_nothrow_assignable_v<E&, GF>) {
1467 err() = std::forward<GF>(rhs.error());
1469 expected_detail::reinit_expected(err(), val(), std::forward<GF>(rhs.error()));
1470 this->m_has_val =
false;
1476 template <
class... Args,
1477 typename std::enable_if_t<std::is_nothrow_constructible_v<T, Args&&...>,
1479 constexpr T& emplace(Args&&... args) {
1481 if constexpr (!std::is_trivially_destructible_v<T>) {
1485 if constexpr (!std::is_trivially_destructible_v<E>) {
1488 this->m_has_val =
true;
1491 return *expected_detail::construct_at(valptr(), std::forward<Args>(args)...);
1494 template <
class U,
class... Args,
1495 std::enable_if_t<std::is_nothrow_constructible_v<T, std::initializer_list<U>&,
1496 Args&&...>>* =
nullptr>
1497 constexpr T& emplace(std::initializer_list<U> il, Args&&... args) {
1499 if constexpr (!std::is_trivially_destructible_v<T>) {
1503 if constexpr (!std::is_trivially_destructible_v<E>) {
1506 this->m_has_val =
true;
1509 return *expected_detail::construct_at(valptr(), il, std::forward<Args>(args)...);
1512 template <
class OT = T,
class OE = E>
1513 constexpr std::enable_if_t<std::is_swappable_v<OT> && std::is_swappable_v<OE> &&
1514 std::is_move_constructible_v<OT> &&
1515 std::is_move_constructible_v<OE> &&
1516 (std::is_nothrow_move_constructible_v<OT> ||
1517 std::is_nothrow_move_constructible_v<OE>)>
1518 swap(
expected& rhs)
noexcept(std::is_nothrow_move_constructible_v<T> &&
1519 std::is_nothrow_swappable_v<T> &&
1520 std::is_nothrow_move_constructible_v<E> &&
1521 std::is_nothrow_swappable_v<E>) {
1523 if (this->m_has_val && rhs.m_has_val) {
1524 swap(this->m_val, rhs.m_val);
1525 }
else if (this->m_has_val) {
1526 if constexpr (std::is_nothrow_move_constructible_v<E>) {
1527 E tmp(std::move(rhs.error()));
1528 if constexpr (!std::is_trivially_destructible_v<E>) {
1532 if constexpr (std::is_nothrow_move_constructible_v<T>) {
1533 expected_detail::construct_at(std::addressof(rhs.m_val),
1534 std::move(this->m_val));
1537 std::addressof(tmp)};
1538 expected_detail::construct_at(std::addressof(rhs.m_val),
1539 std::move(this->m_val));
1540 guard._target =
nullptr;
1543 if constexpr (!std::is_trivially_destructible_v<T>) {
1546 expected_detail::construct_at(std::addressof(this->error()), std::move(tmp));
1548 T tmp(std::move(this->m_val));
1549 if constexpr (!std::is_trivially_destructible_v<T>) {
1554 std::addressof(tmp)};
1555 expected_detail::construct_at(std::addressof(this->error()),
1556 std::move(rhs.error()));
1557 guard._target =
nullptr;
1559 if constexpr (!std::is_trivially_destructible_v<E>) {
1562 expected_detail::construct_at(std::addressof(rhs.m_val), std::move(tmp));
1565 this->m_has_val =
false;
1566 rhs.m_has_val =
true;
1567 }
else if (rhs.m_has_val) {
1570 swap(this->error(), rhs.error());
1574 constexpr const T* operator->()
const noexcept {
return valptr(); }
1575 constexpr T* operator->()
noexcept {
return valptr(); }
1577 constexpr const T& operator*()
const&
noexcept {
return val(); }
1578 constexpr T& operator*() &
noexcept {
return val(); }
1579 constexpr const T&& operator*()
const&&
noexcept {
return std::move(val()); }
1580 constexpr T&& operator*() &&
noexcept {
return std::move(val()); }
1582 constexpr bool has_value()
const noexcept {
return this->m_has_val; }
1583 constexpr explicit operator bool()
const noexcept {
return this->m_has_val; }
1585 constexpr const T& value()
const& {
1586 static_assert(std::is_copy_constructible_v<E>,
1587 "E must be copy constructible, by LWG-3843");
1591 constexpr T& value() & {
1592 static_assert(std::is_copy_constructible_v<E>,
1593 "E must be copy constructible, by LWG-3843");
1597 constexpr const T&& value()
const&& {
1598 static_assert(std::is_copy_constructible_v<E>,
1599 "E must be copy constructible, by LWG-3843");
1600 static_assert(std::is_constructible_v<E,
decltype(std::move(error()))>,
1601 "E must be constructible from const E&&, by LWG-3843");
1603 return std::move(val());
1605 constexpr T&& value() && {
1606 static_assert(std::is_copy_constructible_v<E>,
1607 "E must be copy constructible, by LWG-3843");
1608 static_assert(std::is_constructible_v<E,
decltype(std::move(error()))>,
1609 "E must be constructible from E&&, by LWG-3843");
1611 return std::move(val());
1614 constexpr const E& error()
const&
noexcept {
return err(); }
1615 constexpr E& error() &
noexcept {
return err(); }
1616 constexpr const E&& error()
const&&
noexcept {
return std::move(err()); }
1617 constexpr E&& error() &&
noexcept {
return std::move(err()); }
1619 template <
class U = std::remove_cv_t<T>>
1620 constexpr T value_or(U&& v)
const&
noexcept(
1621 std::is_nothrow_copy_constructible_v<T> &&
1622 expected_detail::is_nothrow_convertible_v<U, T>) {
1623 static_assert(std::is_copy_constructible_v<T>,
"T must be copy-constructible");
1624 static_assert(std::is_convertible_v<U, T>,
"is_convertible_v<U, T> must be true");
1625 if (this->m_has_val) {
1628 return static_cast<T
>(std::forward<U>(v));
1631 template <
class U = std::remove_cv_t<T>>
1632 constexpr T value_or(U&& v) &&
noexcept(
1633 std::is_nothrow_move_constructible_v<T> &&
1634 expected_detail::is_nothrow_convertible_v<U, T>) {
1635 static_assert(std::is_move_constructible_v<T>,
"T must be move-constructible");
1636 static_assert(std::is_convertible_v<U, T>,
"is_convertible_v<U, T> must be true");
1637 if (this->m_has_val) {
1638 return std::move(this->m_val);
1640 return static_cast<T
>(std::forward<U>(v));
1644 template <
class G = E>
1645 constexpr E error_or(G&& v)
const&
noexcept(
1646 std::is_nothrow_copy_constructible_v<E> &&
1647 expected_detail::is_nothrow_convertible_v<G, E>) {
1648 static_assert(std::is_copy_constructible_v<E>,
"E must be copy-constructible");
1649 static_assert(std::is_convertible_v<G, E>,
"is_convertible_v<G, E> must be true");
1650 if (this->m_has_val) {
1651 return static_cast<E
>(std::forward<G>(v));
1653 return this->m_unexpect;
1656 template <
class G = E>
1657 constexpr E error_or(G&& v) &&
noexcept(
1658 std::is_nothrow_move_constructible_v<E> &&
1659 expected_detail::is_nothrow_convertible_v<G, E>) {
1660 static_assert(std::is_move_constructible_v<E>,
"E must be move-constructible");
1661 static_assert(std::is_convertible_v<G, E>,
"is_convertible_v<G, E> must be true");
1662 if (this->m_has_val) {
1663 return static_cast<E
>(std::forward<G>(v));
1665 return std::move(this->m_unexpect);
1669 template <
class F,
class GE = E,
1670 std::enable_if_t<std::is_constructible_v<GE, GE&>>* =
nullptr>
1671 constexpr auto and_then(F&& f) & {
1673 expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype((this->m_val))>>;
1674 static_assert(expected_detail::is_specialization_v<U, expected>,
1675 "U (return type of F) must be specialization of expected");
1676 static_assert(std::is_same_v<typename U::error_type, E>,
1677 "The error type must be the same after calling the F");
1680 return std::invoke(std::forward<F>(f), this->m_val);
1682 return U(unexpect, error());
1684 template <
class F,
class GE = E,
1685 std::enable_if_t<std::is_constructible_v<GE, const GE&>>* =
nullptr>
1686 constexpr auto and_then(F&& f)
const& {
1688 expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype((this->m_val))>>;
1689 static_assert(expected_detail::is_specialization_v<U, expected>,
1690 "U (return type of F) must be specialization of expected");
1691 static_assert(std::is_same_v<typename U::error_type, E>,
1692 "The error type must be the same after calling the F");
1695 return std::invoke(std::forward<F>(f), this->m_val);
1697 return U(unexpect, error());
1699 template <
class F,
class GE = E,
1700 std::enable_if_t<std::is_constructible_v<GE, GE&&>>* =
nullptr>
1701 constexpr auto and_then(F&& f) && {
1702 using U = expected_detail::remove_cvref_t<
1703 std::invoke_result_t<F,
decltype(std::move(this->m_val))>>;
1704 static_assert(expected_detail::is_specialization_v<U, expected>,
1705 "U (return type of F) must be specialization of expected");
1706 static_assert(std::is_same_v<typename U::error_type, E>,
1707 "The error type must be the same after calling the F");
1710 return std::invoke(std::forward<F>(f), std::move(this->m_val));
1712 return U(unexpect, std::move(error()));
1714 template <
class F,
class GE = E,
1715 std::enable_if_t<std::is_constructible_v<GE, const GE>>* =
nullptr>
1716 constexpr auto and_then(F&& f)
const&& {
1717 using U = expected_detail::remove_cvref_t<
1718 std::invoke_result_t<F,
decltype(std::move(this->m_val))>>;
1719 static_assert(expected_detail::is_specialization_v<U, expected>,
1720 "U (return type of F) must be specialization of expected");
1721 static_assert(std::is_same_v<typename U::error_type, E>,
1722 "The error type must be the same after calling the F");
1725 return std::invoke(std::forward<F>(f), std::move(this->m_val));
1727 return U(unexpect, std::move(error()));
1730 template <
class F,
class UT = T,
1731 std::enable_if_t<std::is_constructible_v<UT, UT&>>* =
nullptr>
1732 constexpr auto or_else(F&& f) & {
1733 using G = expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype(error())>>;
1734 static_assert(expected_detail::is_specialization_v<G, expected>,
1735 "G (return type of F) must be specialization of expected");
1736 static_assert(std::is_same_v<typename G::value_type, T>,
1737 "The value type must be the same after calling the F");
1740 return G(std::in_place, this->m_val);
1742 return std::invoke(std::forward<F>(f), error());
1744 template <
class F,
class UT = T,
1745 std::enable_if_t<std::is_constructible_v<UT, const UT&>>* =
nullptr>
1746 constexpr auto or_else(F&& f)
const& {
1747 using G = expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype(error())>>;
1748 static_assert(expected_detail::is_specialization_v<G, expected>,
1749 "G (return type of F) must be specialization of expected");
1750 static_assert(std::is_same_v<typename G::value_type, T>,
1751 "The value type must be the same after calling the F");
1754 return G(std::in_place, this->m_val);
1756 return std::invoke(std::forward<F>(f), error());
1758 template <
class F,
class UT = T,
1759 std::enable_if_t<std::is_constructible_v<UT, UT&&>>* =
nullptr>
1760 constexpr auto or_else(F&& f) && {
1761 using G = expected_detail::remove_cvref_t<
1762 std::invoke_result_t<F,
decltype(std::move(error()))>>;
1763 static_assert(expected_detail::is_specialization_v<G, expected>,
1764 "G (return type of F) must be specialization of expected");
1765 static_assert(std::is_same_v<typename G::value_type, T>,
1766 "The value type must be the same after calling the F");
1769 return G(std::in_place, std::move(this->m_val));
1771 return std::invoke(std::forward<F>(f), std::move(error()));
1773 template <
class F,
class UT = T,
1774 std::enable_if_t<std::is_constructible_v<UT, const UT>>* =
nullptr>
1775 constexpr auto or_else(F&& f)
const&& {
1776 using G = expected_detail::remove_cvref_t<
1777 std::invoke_result_t<F,
decltype(std::move(error()))>>;
1778 static_assert(expected_detail::is_specialization_v<G, expected>,
1779 "G (return type of F) must be specialization of expected");
1780 static_assert(std::is_same_v<typename G::value_type, T>,
1781 "The value type must be the same after calling the F");
1784 return G(std::in_place, std::move(this->m_val));
1786 return std::invoke(std::forward<F>(f), std::move(error()));
1789 template <
class F,
class GE = E,
1790 std::enable_if_t<std::is_constructible_v<GE, GE&>>* =
nullptr>
1791 constexpr auto transform(F&& f) & {
1793 expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype((this->m_val))>>;
1794 static_assert(expected_detail::is_value_type_valid_v<U>,
1795 "U must be a valid type for expected<U, E>");
1800 if constexpr (std::is_void_v<U>) {
1801 std::invoke(std::forward<F>(f), this->m_val);
1805 std::forward<F>(f), this->m_val);
1809 template <
class F,
class GE = E,
1810 std::enable_if_t<std::is_constructible_v<GE, const GE&>>* =
nullptr>
1811 constexpr auto transform(F&& f)
const& {
1813 expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype((this->m_val))>>;
1814 static_assert(expected_detail::is_value_type_valid_v<U>,
1815 "U must be a valid type for expected<U, E>");
1820 if constexpr (std::is_void_v<U>) {
1821 std::invoke(std::forward<F>(f), this->m_val);
1825 std::forward<F>(f), this->m_val);
1829 template <
class F,
class GE = E,
1830 std::enable_if_t<std::is_constructible_v<GE, GE&&>>* =
nullptr>
1831 constexpr auto transform(F&& f) && {
1832 using U = expected_detail::remove_cvref_t<
1833 std::invoke_result_t<F,
decltype(std::move(this->m_val))>>;
1834 static_assert(expected_detail::is_value_type_valid_v<U>,
1835 "U must be a valid type for expected<U, E>");
1840 if constexpr (std::is_void_v<U>) {
1841 std::invoke(std::forward<F>(f), std::move(this->m_val));
1845 std::forward<F>(f), std::move(this->m_val));
1849 template <
class F,
class GE = E,
1850 std::enable_if_t<std::is_constructible_v<GE, const GE>>* =
nullptr>
1851 constexpr auto transform(F&& f)
const&& {
1852 using U = expected_detail::remove_cvref_t<
1853 std::invoke_result_t<F,
decltype(std::move(this->m_val))>>;
1854 static_assert(expected_detail::is_value_type_valid_v<U>,
1855 "U must be a valid type for expected<U, E>");
1860 if constexpr (std::is_void_v<U>) {
1861 std::invoke(std::forward<F>(f), std::move(this->m_val));
1865 std::forward<F>(f), std::move(this->m_val));
1870 template <
class F,
class UT = T,
1871 std::enable_if_t<std::is_constructible_v<UT, UT&>>* =
nullptr>
1872 constexpr auto transform_error(F&& f) & {
1873 using G = expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype(error())>>;
1874 static_assert(expected_detail::is_error_type_valid_v<G>,
1875 "G must be a valid type for expected<T, G>");
1881 std::forward<F>(f), error());
1884 template <
class F,
class UT = T,
1885 std::enable_if_t<std::is_constructible_v<UT, const UT&>>* =
nullptr>
1886 constexpr auto transform_error(F&& f)
const& {
1887 using G = expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype(error())>>;
1888 static_assert(expected_detail::is_error_type_valid_v<G>,
1889 "G must be a valid type for expected<T, G>");
1895 std::forward<F>(f), error());
1898 template <
class F,
class UT = T,
1899 std::enable_if_t<std::is_constructible_v<UT, UT&&>>* =
nullptr>
1900 constexpr auto transform_error(F&& f) && {
1901 using G = expected_detail::remove_cvref_t<
1902 std::invoke_result_t<F,
decltype(std::move(error()))>>;
1903 static_assert(expected_detail::is_error_type_valid_v<G>,
1904 "G must be a valid type for expected<T, G>");
1910 std::forward<F>(f), std::move(error()));
1913 template <
class F,
class UT = T,
1914 std::enable_if_t<std::is_constructible_v<UT, const UT>>* =
nullptr>
1915 constexpr auto transform_error(F&& f)
const&& {
1916 using G = expected_detail::remove_cvref_t<
1917 std::invoke_result_t<F,
decltype(std::move(error()))>>;
1918 static_assert(expected_detail::is_error_type_valid_v<G>,
1919 "G must be a valid type for expected<T, G>");
1925 std::forward<F>(f), std::move(error()));
1929 template <
class T2,
class E2>
1930 [[nodiscard]]
friend constexpr std::enable_if_t<
1931 !std::is_void_v<T2> &&
1932 expected_detail::is_equality_result_convertible_to_bool_v<T, T2> &&
1933 expected_detail::is_equality_result_convertible_to_bool_v<E, E2>,
1936 expected_detail::is_nothrow_equality_result_convertible_to_bool_v<T, T2> &&
1937 expected_detail::is_nothrow_equality_result_convertible_to_bool_v<E, E2>) {
1938 if (x.has_value() != y.has_value()) {
1940 }
else if (x.has_value()) {
1943 return x.error() == y.error();
1946#if ICEBERG_EXPECTED_CPLUSPLUS < 202002L
1947 template <
class T2,
class E2>
1948 [[nodiscard]]
friend constexpr std::enable_if_t<
1949 !std::is_void_v<T2> &&
1950 expected_detail::is_equality_result_convertible_to_bool_v<T, T2> &&
1951 expected_detail::is_equality_result_convertible_to_bool_v<E, E2>,
1952 bool> operator!=(
const expected& x,
1959 [[nodiscard]]
friend constexpr std::enable_if_t<
1960 !expected_detail::is_specialization_v<T2, iceberg::expected> &&
1961 expected_detail::is_equality_result_convertible_to_bool_v<T, T2>,
1963 operator==(
const expected& x,
const T2& v)
noexcept(
1964 expected_detail::is_nothrow_equality_result_convertible_to_bool_v<T, T2>) {
1965 if (x.has_value()) {
1971#if ICEBERG_EXPECTED_CPLUSPLUS < 202002L
1973 [[nodiscard]]
friend constexpr std::enable_if_t<
1974 !expected_detail::is_specialization_v<T2, iceberg::expected> &&
1975 expected_detail::is_equality_result_convertible_to_bool_v<T, T2>,
1976 bool> operator!=(
const expected& x,
const T2& v)
noexcept(
noexcept(x == v)) {
1982 [[nodiscard]]
friend constexpr std::enable_if_t<
1983 expected_detail::is_equality_result_convertible_to_bool_v<E, E2>,
bool>
1985 expected_detail::is_nothrow_equality_result_convertible_to_bool_v<E, E2>) {
1986 if (x.has_value()) {
1989 return x.error() == e.error();
1992#if ICEBERG_EXPECTED_CPLUSPLUS < 202002L
1994 [[nodiscard]]
friend constexpr std::enable_if_t<
1995 expected_detail::is_equality_result_convertible_to_bool_v<E, E2>,
bool>
2015class ICEBERG_EXPORT [[nodiscard]]
2018 static_assert(expected_detail::is_error_type_valid_v<E>);
2022 constexpr E* errptr()
noexcept {
return std::addressof(this->m_unexpect); }
2023 constexpr const E* errptr()
const noexcept {
return std::addressof(this->m_unexpect); }
2025 constexpr void val()
noexcept {}
2027 constexpr E& err()
noexcept {
return this->m_unexpect; }
2029 constexpr void val()
const noexcept {}
2031 constexpr const E& err()
const noexcept {
return this->m_unexpect; }
2037 typedef T value_type;
2038 typedef E error_type;
2050 std::enable_if_t<!std::is_same_v<expected<U, G>,
expected>>* =
nullptr,
2051 std::enable_if_t<std::is_convertible_v<const G&, E>>* =
nullptr,
2052 expected_detail::enable_from_other_void_expected_t<E, U, G, const G&>* =
nullptr>
2054 std::is_nothrow_constructible_v<E, const G&>)
2055 :
impl_base(expected_detail::construct_from_expected, rhs),
2060 std::enable_if_t<!std::is_same_v<expected<U, G>,
expected>>* =
nullptr,
2061 std::enable_if_t<!std::is_convertible_v<const G&, E>>* =
nullptr,
2062 expected_detail::enable_from_other_void_expected_t<E, U, G, const G&>* =
nullptr>
2064 std::is_nothrow_constructible_v<E, const G&>)
2065 :
impl_base(expected_detail::construct_from_expected, rhs),
2068 template <
class U,
class G,
2069 std::enable_if_t<!std::is_same_v<expected<U, G>,
expected>>* =
nullptr,
2070 std::enable_if_t<std::is_convertible_v<G, E>>* =
nullptr,
2071 expected_detail::enable_from_other_void_expected_t<E, U, G, G>* =
nullptr>
2073 :
impl_base(expected_detail::construct_from_expected, std::move(rhs)),
2076 template <
class U,
class G,
2077 std::enable_if_t<!std::is_same_v<expected<U, G>,
expected>>* =
nullptr,
2078 std::enable_if_t<!std::is_convertible_v<G, E>>* =
nullptr,
2079 expected_detail::enable_from_other_void_expected_t<E, U, G, G>* =
nullptr>
2081 std::is_nothrow_constructible_v<E, G>)
2082 :
impl_base(expected_detail::construct_from_expected, std::move(rhs)),
2085#if !ICEBERG_CXX20_COMPAT && defined(__cpp_lib_expected) && __cpp_lib_expected >= 202202L
2087 template <
class G, std::enable_if_t<std::is_constructible_v<E, const G&>>* =
nullptr>
2088 constexpr explicit(!std::is_convertible_v<const G&, E>)
expected(
2089 const std::unexpected<G>& e)
noexcept(std::is_nothrow_constructible_v<E, const G&>)
2092 template <
class G, std::enable_if_t<std::is_constructible_v<E, G>>* =
nullptr>
2093 constexpr explicit(!std::is_convertible_v<G, E>)
2094 expected(std::unexpected<G>&& e)
noexcept(std::is_nothrow_constructible_v<E, G>)
2095 :
expected(unexpect, std::move(e.error())) {}
2101 template <
class G, std::enable_if_t<!std::is_convertible_v<const G&, E>>* =
nullptr,
2102 std::enable_if_t<std::is_constructible_v<E, const G&>>* =
nullptr>
2104 std::is_nothrow_constructible_v<E, const G&>)
2109 template <
class G, std::enable_if_t<std::is_convertible_v<const G&, E>>* =
nullptr,
2110 std::enable_if_t<std::is_constructible_v<E, const G&>>* =
nullptr>
2112 std::is_nothrow_constructible_v<E, const G&>)
2117 template <
class G, std::enable_if_t<!std::is_convertible_v<G, E>>* =
nullptr,
2118 std::enable_if_t<std::is_constructible_v<E, G>>* =
nullptr>
2120 std::is_nothrow_constructible_v<E, G>)
2121 :
impl_base(unexpect, std::move(e.error())),
2125 template <
class G, std::enable_if_t<std::is_convertible_v<G, E>>* =
nullptr,
2126 std::enable_if_t<std::is_constructible_v<E, G>>* =
nullptr>
2128 :
impl_base(unexpect, std::move(e.error())),
2132 constexpr explicit expected(std::in_place_t) noexcept
2137 template <
class... Args,
2138 std::enable_if_t<std::is_constructible_v<E, Args...>>* =
nullptr>
2140 std::is_nothrow_constructible_v<E, Args...>)
2141 :
impl_base(unexpect, std::forward<Args>(args)...),
2146 template <
class U,
class... Args,
2147 std::enable_if_t<std::is_constructible_v<E, std::initializer_list<U>&,
2148 Args...>>* =
nullptr>
2151 Args&&... args)
noexcept(std::is_nothrow_constructible_v<E,
2152 std::initializer_list<U>&,
2154 :
impl_base(unexpect, il, std::forward<Args>(args)...),
2158 template <
class Fn,
class... Args>
2161 Args&&... args)
noexcept(
noexcept(
static_cast<E
>(std::invoke(std::forward<Fn>(func),
2164 :
impl_base(tag1, tag2, std::forward<Fn>(func), std::forward<Args>(args)...),
2170 template <
class G,
class GF =
const G&,
2171 std::enable_if_t<std::is_constructible_v<E, GF> &&
2172 std::is_assignable_v<E&, GF>>* =
nullptr>
2174 std::is_nothrow_constructible_v<E, GF> && std::is_nothrow_assignable_v<E&, GF>) {
2176 expected_detail::construct_at(errptr(), std::forward<GF>(rhs.error()));
2177 this->m_has_val =
false;
2179 error() = std::forward<GF>(rhs.error());
2185 template <
class G,
class GF = G,
2186 std::enable_if_t<std::is_constructible_v<E, GF> &&
2187 std::is_assignable_v<E&, GF>>* =
nullptr>
2189 std::is_nothrow_constructible_v<E, GF> && std::is_nothrow_assignable_v<E&, GF>) {
2191 expected_detail::construct_at(errptr(), std::forward<GF>(rhs.error()));
2192 this->m_has_val =
false;
2194 error() = std::forward<GF>(rhs.error());
2200 constexpr void emplace() {
2202 if constexpr (!std::is_trivially_destructible_v<E>) {
2205 this->m_has_val =
true;
2209 template <
class OE = E>
2210 constexpr std::enable_if_t<std::is_swappable_v<OE> && std::is_move_constructible_v<OE>>
2211 swap(
expected& rhs)
noexcept(std::is_nothrow_move_constructible_v<E> &&
2212 std::is_nothrow_swappable_v<E>) {
2214 if (this->m_has_val && rhs.m_has_val) {
2216 }
else if (this->m_has_val) {
2217 expected_detail::construct_at(std::addressof(error()), std::move(rhs.error()));
2218 if constexpr (!std::is_trivially_destructible_v<E>) {
2221 this->m_has_val =
false;
2222 rhs.m_has_val =
true;
2223 }
else if (rhs.m_has_val) {
2224 expected_detail::construct_at(std::addressof(rhs.error()), std::move(error()));
2225 if constexpr (!std::is_trivially_destructible_v<E>) {
2228 this->m_has_val =
true;
2229 rhs.m_has_val =
false;
2231 swap(error(), rhs.error());
2235 constexpr void operator*()
const noexcept {
return val(); }
2237 constexpr bool has_value()
const noexcept {
return this->m_has_val; }
2238 constexpr explicit operator bool()
const noexcept {
return this->m_has_val; }
2240 constexpr void value()
const& {
2241 static_assert(std::is_copy_constructible_v<E>,
2242 "E must be copy constructible, by LWG-3940");
2246 constexpr void value() && {
2247 static_assert(std::is_copy_constructible_v<E>,
2248 "E must be copy constructible, by LWG-3940");
2249 static_assert(std::is_move_constructible_v<E>,
2250 "E must be move constructible, by LWG-3940");
2254 constexpr const E& error()
const&
noexcept {
return err(); }
2255 constexpr E& error() &
noexcept {
return err(); }
2256 constexpr const E&& error()
const&&
noexcept {
return std::move(err()); }
2257 constexpr E&& error() &&
noexcept {
return std::move(err()); }
2259 template <
class G = E>
2260 constexpr E error_or(G&& v)
const&
noexcept(
2261 std::is_nothrow_copy_constructible_v<E> &&
2262 expected_detail::is_nothrow_convertible_v<G, E>) {
2263 static_assert(std::is_copy_constructible_v<E>,
"E must be copy-constructible");
2264 static_assert(std::is_convertible_v<G, E>,
"is_convertible_v<G, E> must be true");
2265 if (this->m_has_val) {
2266 return static_cast<E
>(std::forward<G>(v));
2268 return this->m_unexpect;
2271 template <
class G = E>
2272 constexpr E error_or(G&& v) &&
noexcept(
2273 std::is_nothrow_move_constructible_v<E> &&
2274 expected_detail::is_nothrow_convertible_v<G, E>) {
2275 static_assert(std::is_move_constructible_v<E>,
"E must be move-constructible");
2276 static_assert(std::is_convertible_v<G, E>,
"is_convertible_v<G, E> must be true");
2277 if (this->m_has_val) {
2278 return static_cast<E
>(std::forward<G>(v));
2280 return std::move(this->m_unexpect);
2284 template <
class F,
class GE = E,
2285 std::enable_if_t<std::is_constructible_v<GE, GE&>>* =
nullptr>
2286 constexpr auto and_then(F&& f) & {
2287 using U = expected_detail::remove_cvref_t<std::invoke_result_t<F>>;
2288 static_assert(expected_detail::is_specialization_v<U, iceberg::expected>,
2289 "U (return type of F) must be specialization of expected");
2290 static_assert(std::is_same_v<typename U::error_type, E>,
2291 "The error type must be the same after calling the F");
2294 return std::invoke(std::forward<F>(f));
2296 return U(unexpect, error());
2298 template <
class F,
class GE = E,
2299 std::enable_if_t<std::is_constructible_v<GE, const GE&>>* =
nullptr>
2300 constexpr auto and_then(F&& f)
const& {
2301 using U = expected_detail::remove_cvref_t<std::invoke_result_t<F>>;
2302 static_assert(expected_detail::is_specialization_v<U, iceberg::expected>,
2303 "U (return type of F) must be specialization of expected");
2304 static_assert(std::is_same_v<typename U::error_type, E>,
2305 "The error type must be the same after calling the F");
2308 return std::invoke(std::forward<F>(f));
2310 return U(unexpect, error());
2312 template <
class F,
class GE = E,
2313 std::enable_if_t<std::is_constructible_v<GE, GE&&>>* =
nullptr>
2314 constexpr auto and_then(F&& f) && {
2315 using U = expected_detail::remove_cvref_t<std::invoke_result_t<F>>;
2316 static_assert(expected_detail::is_specialization_v<U, iceberg::expected>,
2317 "U (return type of F) must be specialization of expected");
2318 static_assert(std::is_same_v<typename U::error_type, E>,
2319 "The error type must be the same after calling the F");
2322 return std::invoke(std::forward<F>(f));
2324 return U(unexpect, std::move(error()));
2326 template <
class F,
class GE = E,
2327 std::enable_if_t<std::is_constructible_v<GE, const GE>>* =
nullptr>
2328 constexpr auto and_then(F&& f)
const&& {
2329 using U = expected_detail::remove_cvref_t<std::invoke_result_t<F>>;
2330 static_assert(expected_detail::is_specialization_v<U, iceberg::expected>,
2331 "U (return type of F) must be specialization of expected");
2332 static_assert(std::is_same_v<typename U::error_type, E>,
2333 "The error type must be the same after calling the F");
2336 return std::invoke(std::forward<F>(f));
2338 return U(unexpect, std::move(error()));
2342 constexpr auto or_else(F&& f) & {
2343 using G = expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype(error())>>;
2344 static_assert(expected_detail::is_specialization_v<G, iceberg::expected>,
2345 "G (return type of F) must be specialization of expected");
2346 static_assert(std::is_same_v<typename G::value_type, T>,
2347 "The value type must be the same after calling the F");
2352 return std::invoke(std::forward<F>(f), error());
2355 constexpr auto or_else(F&& f)
const& {
2356 using G = expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype(error())>>;
2357 static_assert(expected_detail::is_specialization_v<G, iceberg::expected>,
2358 "G (return type of F) must be specialization of expected");
2359 static_assert(std::is_same_v<typename G::value_type, T>,
2360 "The value type must be the same after calling the F");
2365 return std::invoke(std::forward<F>(f), error());
2368 constexpr auto or_else(F&& f) && {
2369 using G = expected_detail::remove_cvref_t<
2370 std::invoke_result_t<F,
decltype(std::move(error()))>>;
2371 static_assert(expected_detail::is_specialization_v<G, iceberg::expected>,
2372 "G (return type of F) must be specialization of expected");
2373 static_assert(std::is_same_v<typename G::value_type, T>,
2374 "The value type must be the same after calling the F");
2379 return std::invoke(std::forward<F>(f), std::move(error()));
2382 constexpr auto or_else(F&& f)
const&& {
2383 using G = expected_detail::remove_cvref_t<
2384 std::invoke_result_t<F,
decltype(std::move(error()))>>;
2385 static_assert(expected_detail::is_specialization_v<G, iceberg::expected>,
2386 "G (return type of F) must be specialization of expected");
2387 static_assert(std::is_same_v<typename G::value_type, T>,
2388 "The value type must be the same after calling the F");
2393 return std::invoke(std::forward<F>(f), std::move(error()));
2396 template <
class F,
class GE = E,
2397 std::enable_if_t<std::is_constructible_v<GE, GE&>>* =
nullptr>
2398 constexpr auto transform(F&& f) & {
2399 using U = expected_detail::remove_cvref_t<std::invoke_result_t<F>>;
2400 static_assert(expected_detail::is_value_type_valid_v<U>,
2401 "U must be a valid type for expected<U, E>");
2406 if constexpr (std::is_void_v<U>) {
2407 std::invoke(std::forward<F>(f));
2411 std::forward<F>(f));
2415 template <
class F,
class GE = E,
2416 std::enable_if_t<std::is_constructible_v<GE, const GE&>>* =
nullptr>
2417 constexpr auto transform(F&& f)
const& {
2418 using U = expected_detail::remove_cvref_t<std::invoke_result_t<F>>;
2419 static_assert(expected_detail::is_value_type_valid_v<U>,
2420 "U must be a valid type for expected<U, E>");
2425 if constexpr (std::is_void_v<U>) {
2426 std::invoke(std::forward<F>(f));
2430 std::forward<F>(f));
2434 template <
class F,
class GE = E,
2435 std::enable_if_t<std::is_constructible_v<GE, GE&&>>* =
nullptr>
2436 constexpr auto transform(F&& f) && {
2437 using U = expected_detail::remove_cvref_t<std::invoke_result_t<F>>;
2438 static_assert(expected_detail::is_value_type_valid_v<U>,
2439 "U must be a valid type for expected<U, E>");
2444 if constexpr (std::is_void_v<U>) {
2445 std::invoke(std::forward<F>(f));
2449 std::forward<F>(f));
2453 template <
class F,
class GE = E,
2454 std::enable_if_t<std::is_constructible_v<GE, const GE>>* =
nullptr>
2455 constexpr auto transform(F&& f)
const&& {
2456 using U = expected_detail::remove_cvref_t<std::invoke_result_t<F>>;
2457 static_assert(expected_detail::is_value_type_valid_v<U>,
2458 "U must be a valid type for expected<U, E>");
2463 if constexpr (std::is_void_v<U>) {
2464 std::invoke(std::forward<F>(f));
2468 std::forward<F>(f));
2474 constexpr auto transform_error(F&& f) & {
2475 using G = expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype(error())>>;
2476 static_assert(expected_detail::is_error_type_valid_v<G>,
2477 "G must be a valid type for expected<void, G>");
2483 std::forward<F>(f), error());
2487 constexpr auto transform_error(F&& f)
const& {
2488 using G = expected_detail::remove_cvref_t<std::invoke_result_t<F,
decltype(error())>>;
2489 static_assert(expected_detail::is_error_type_valid_v<G>,
2490 "G must be a valid type for expected<void, G>");
2496 std::forward<F>(f), error());
2500 constexpr auto transform_error(F&& f) && {
2501 using G = expected_detail::remove_cvref_t<
2502 std::invoke_result_t<F,
decltype(std::move(error()))>>;
2503 static_assert(expected_detail::is_error_type_valid_v<G>,
2504 "G must be a valid type for expected<void, G>");
2510 std::forward<F>(f), std::move(error()));
2514 constexpr auto transform_error(F&& f)
const&& {
2515 using G = expected_detail::remove_cvref_t<
2516 std::invoke_result_t<F,
decltype(std::move(error()))>>;
2517 static_assert(expected_detail::is_error_type_valid_v<G>,
2518 "G must be a valid type for expected<void, G>");
2524 std::forward<F>(f), std::move(error()));
2528 template <
class T2,
class E2>
2529 [[nodiscard]]
friend constexpr std::enable_if_t<
2530 std::is_void_v<T2> &&
2531 expected_detail::is_equality_result_convertible_to_bool_v<E, E2>,
2534 expected_detail::is_nothrow_equality_result_convertible_to_bool_v<E, E2>) {
2535 if (x.has_value() != y.has_value()) {
2537 }
else if (x.has_value()) {
2540 return x.error() == y.error();
2543#if ICEBERG_EXPECTED_CPLUSPLUS < 202002L
2544 template <
class T2,
class E2>
2545 [[nodiscard]]
friend constexpr std::enable_if_t<
2546 std::is_void_v<T2> &&
2547 expected_detail::is_equality_result_convertible_to_bool_v<E, E2>,
2548 bool> operator!=(
const expected& x,
2555 [[nodiscard]]
friend constexpr std::enable_if_t<
2556 expected_detail::is_equality_result_convertible_to_bool_v<E, E2>,
bool>
2558 expected_detail::is_nothrow_equality_result_convertible_to_bool_v<E, E2>) {
2559 if (x.has_value()) {
2562 return x.error() == e.error();
2565#if ICEBERG_EXPECTED_CPLUSPLUS < 202002L
2567 [[nodiscard]]
friend constexpr std::enable_if_t<
2568 expected_detail::is_equality_result_convertible_to_bool_v<E, E2>,
bool>