- tmp/tmphmycijtw/{from.md → to.md} +118 -110
tmp/tmphmycijtw/{from.md → to.md}
RENAMED
|
@@ -1,17 +1,18 @@
|
|
| 1 |
## Expected objects <a id="expected">[[expected]]</a>
|
| 2 |
|
| 3 |
-
###
|
| 4 |
|
| 5 |
Subclause [[expected]] describes the class template `expected` that
|
| 6 |
represents expected objects. An `expected<T, E>` object holds an object
|
| 7 |
-
of type `T` or an object of type `
|
| 8 |
-
|
| 9 |
|
| 10 |
### Header `<expected>` synopsis <a id="expected.syn">[[expected.syn]]</a>
|
| 11 |
|
| 12 |
``` cpp
|
|
|
|
| 13 |
namespace std {
|
| 14 |
// [expected.unexpected], class template unexpected
|
| 15 |
template<class E> class unexpected;
|
| 16 |
|
| 17 |
// [expected.bad], class template bad_expected_access
|
|
@@ -25,14 +26,14 @@ namespace std {
|
|
| 25 |
explicit unexpect_t() = default;
|
| 26 |
};
|
| 27 |
inline constexpr unexpect_t unexpect{};
|
| 28 |
|
| 29 |
// [expected.expected], class template expected
|
| 30 |
-
template<class T, class E> class expected;
|
| 31 |
|
| 32 |
// [expected.void], partial specialization of expected for void types
|
| 33 |
-
template<class T, class E> requires is_void_v<T> class expected<T, E>;
|
| 34 |
}
|
| 35 |
```
|
| 36 |
|
| 37 |
### Class template `unexpected` <a id="expected.unexpected">[[expected.unexpected]]</a>
|
| 38 |
|
|
@@ -179,16 +180,16 @@ its result is convertible to `bool`.
|
|
| 179 |
``` cpp
|
| 180 |
namespace std {
|
| 181 |
template<class E>
|
| 182 |
class bad_expected_access : public bad_expected_access<void> {
|
| 183 |
public:
|
| 184 |
-
explicit bad_expected_access(E);
|
| 185 |
-
const char* what() const noexcept override;
|
| 186 |
-
E& error() & noexcept;
|
| 187 |
-
const E& error() const & noexcept;
|
| 188 |
-
E&& error() && noexcept;
|
| 189 |
-
const E&& error() const && noexcept;
|
| 190 |
|
| 191 |
private:
|
| 192 |
E unex; // exposition only
|
| 193 |
};
|
| 194 |
}
|
|
@@ -198,60 +199,62 @@ The class template `bad_expected_access` defines the type of objects
|
|
| 198 |
thrown as exceptions to report the situation where an attempt is made to
|
| 199 |
access the value of an `expected<T, E>` object for which `has_value()`
|
| 200 |
is `false`.
|
| 201 |
|
| 202 |
``` cpp
|
| 203 |
-
explicit bad_expected_access(E e);
|
| 204 |
```
|
| 205 |
|
| 206 |
*Effects:* Initializes *unex* with `std::move(e)`.
|
| 207 |
|
| 208 |
``` cpp
|
| 209 |
-
const E& error() const & noexcept;
|
| 210 |
-
E& error() & noexcept;
|
| 211 |
```
|
| 212 |
|
| 213 |
*Returns:* *unex*.
|
| 214 |
|
| 215 |
``` cpp
|
| 216 |
-
E&& error() && noexcept;
|
| 217 |
-
const E&& error() const && noexcept;
|
| 218 |
```
|
| 219 |
|
| 220 |
*Returns:* `std::move(`*`unex`*`)`.
|
| 221 |
|
| 222 |
``` cpp
|
| 223 |
-
const char* what() const noexcept override;
|
| 224 |
```
|
| 225 |
|
| 226 |
-
*Returns:* An implementation-defined NTBS
|
|
|
|
| 227 |
|
| 228 |
### Class template specialization `bad_expected_access<void>` <a id="expected.bad.void">[[expected.bad.void]]</a>
|
| 229 |
|
| 230 |
``` cpp
|
| 231 |
namespace std {
|
| 232 |
template<>
|
| 233 |
class bad_expected_access<void> : public exception {
|
| 234 |
protected:
|
| 235 |
-
bad_expected_access() noexcept;
|
| 236 |
-
bad_expected_access(const bad_expected_access&);
|
| 237 |
-
bad_expected_access(bad_expected_access&&);
|
| 238 |
-
bad_expected_access& operator=(const bad_expected_access&);
|
| 239 |
-
bad_expected_access& operator=(bad_expected_access&&);
|
| 240 |
-
~bad_expected_access();
|
| 241 |
|
| 242 |
public:
|
| 243 |
-
const char* what() const noexcept override;
|
| 244 |
};
|
| 245 |
}
|
| 246 |
```
|
| 247 |
|
| 248 |
``` cpp
|
| 249 |
-
const char* what() const noexcept override;
|
| 250 |
```
|
| 251 |
|
| 252 |
-
*Returns:* An implementation-defined NTBS
|
|
|
|
| 253 |
|
| 254 |
### Class template `expected` <a id="expected.expected">[[expected.expected]]</a>
|
| 255 |
|
| 256 |
#### General <a id="expected.object.general">[[expected.object.general]]</a>
|
| 257 |
|
|
@@ -274,11 +277,11 @@ namespace std {
|
|
| 274 |
template<class U, class G>
|
| 275 |
constexpr explicit(see below) expected(const expected<U, G>&);
|
| 276 |
template<class U, class G>
|
| 277 |
constexpr explicit(see below) expected(expected<U, G>&&);
|
| 278 |
|
| 279 |
-
template<class U = T>
|
| 280 |
constexpr explicit(see below) expected(U&& v);
|
| 281 |
|
| 282 |
template<class G>
|
| 283 |
constexpr explicit(see below) expected(const unexpected<G>&);
|
| 284 |
template<class G>
|
|
@@ -297,11 +300,11 @@ namespace std {
|
|
| 297 |
constexpr ~expected();
|
| 298 |
|
| 299 |
// [expected.object.assign], assignment
|
| 300 |
constexpr expected& operator=(const expected&);
|
| 301 |
constexpr expected& operator=(expected&&) noexcept(see below);
|
| 302 |
-
template<class U = T> constexpr expected& operator=(U&&);
|
| 303 |
template<class G>
|
| 304 |
constexpr expected& operator=(const unexpected<G>&);
|
| 305 |
template<class G>
|
| 306 |
constexpr expected& operator=(unexpected<G>&&);
|
| 307 |
|
|
@@ -321,20 +324,20 @@ namespace std {
|
|
| 321 |
constexpr T& operator*() & noexcept;
|
| 322 |
constexpr const T&& operator*() const && noexcept;
|
| 323 |
constexpr T&& operator*() && noexcept;
|
| 324 |
constexpr explicit operator bool() const noexcept;
|
| 325 |
constexpr bool has_value() const noexcept;
|
| 326 |
-
constexpr const T& value() const &;
|
| 327 |
-
constexpr T& value() &;
|
| 328 |
-
constexpr const T&& value() const &&;
|
| 329 |
-
constexpr T&& value() &&;
|
| 330 |
constexpr const E& error() const & noexcept;
|
| 331 |
constexpr E& error() & noexcept;
|
| 332 |
constexpr const E&& error() const && noexcept;
|
| 333 |
constexpr E&& error() && noexcept;
|
| 334 |
-
template<class U> constexpr T value_or(U&&) const &;
|
| 335 |
-
template<class U> constexpr T value_or(U&&) &&;
|
| 336 |
template<class G = E> constexpr E error_or(G&&) const &;
|
| 337 |
template<class G = E> constexpr E error_or(G&&) &&;
|
| 338 |
|
| 339 |
// [expected.object.monadic], monadic operations
|
| 340 |
template<class F> constexpr auto and_then(F&& f) &;
|
|
@@ -371,15 +374,13 @@ namespace std {
|
|
| 371 |
};
|
| 372 |
}
|
| 373 |
```
|
| 374 |
|
| 375 |
Any object of type `expected<T, E>` either contains a value of type `T`
|
| 376 |
-
or a value of type `E` within
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
indicates whether the `expected<T, E>` object contains an object of type
|
| 380 |
-
`T`.
|
| 381 |
|
| 382 |
A type `T` is a *valid value type for `expected`*, if `remove_cv_t<T>`
|
| 383 |
is `void` or a complete non-array object type that is not `in_place_t`,
|
| 384 |
`unexpect_t`, or a specialization of `unexpected`. A program which
|
| 385 |
instantiates class template `expected<T, E>` with an argument `T` that
|
|
@@ -495,18 +496,19 @@ with `std::forward<GF>(rhs.error())`.
|
|
| 495 |
|
| 496 |
*Remarks:* The expression inside `explicit` is equivalent to
|
| 497 |
`!is_convertible_v<UF, T> || !is_convertible_v<GF, E>`.
|
| 498 |
|
| 499 |
``` cpp
|
| 500 |
-
template<class U = T>
|
| 501 |
constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);
|
| 502 |
```
|
| 503 |
|
| 504 |
*Constraints:*
|
| 505 |
|
| 506 |
- `is_same_v<remove_cvref_t<U>, in_place_t>` is `false`; and
|
| 507 |
-
- `is_same_v<
|
|
|
|
| 508 |
- `remove_cvref_t<U>` is not a specialization of `unexpected`; and
|
| 509 |
- `is_constructible_v<T, U>` is `true`; and
|
| 510 |
- if `T` is cv `bool`, `remove_cvref_t<U>` is not a specialization of
|
| 511 |
`expected`.
|
| 512 |
|
|
@@ -606,11 +608,12 @@ destroys *unex*.
|
|
| 606 |
`is_trivially_destructible_v<E>` is `true`, then this destructor is a
|
| 607 |
trivial destructor.
|
| 608 |
|
| 609 |
#### Assignment <a id="expected.object.assign">[[expected.object.assign]]</a>
|
| 610 |
|
| 611 |
-
This subclause makes use of the following exposition-only function
|
|
|
|
| 612 |
|
| 613 |
``` cpp
|
| 614 |
template<class T, class U, class... Args>
|
| 615 |
constexpr void reinit-expected(T& newval, U& oldval, Args&&... args) { // exposition only
|
| 616 |
if constexpr (is_nothrow_constructible_v<T, Args...>) {
|
|
@@ -703,11 +706,11 @@ Then, if no exception was thrown, equivalent to:
|
|
| 703 |
is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T> &&
|
| 704 |
is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>
|
| 705 |
```
|
| 706 |
|
| 707 |
``` cpp
|
| 708 |
-
template<class U = T>
|
| 709 |
constexpr expected& operator=(U&& v);
|
| 710 |
```
|
| 711 |
|
| 712 |
*Constraints:*
|
| 713 |
|
|
@@ -819,12 +822,12 @@ constexpr void swap(expected& rhs) noexcept(see below);
|
|
| 819 |
|
| 820 |
| \topline | `this->has_value()` | `!this->has_value()` |
|
| 821 |
| -------- | ------------------- | -------------------- |
|
| 822 |
|
| 823 |
|
| 824 |
-
For the case where `rhs.
|
| 825 |
-
`true`, equivalent to:
|
| 826 |
|
| 827 |
``` cpp
|
| 828 |
if constexpr (is_nothrow_move_constructible_v<E>) {
|
| 829 |
E tmp(std::move(rhs.unex));
|
| 830 |
destroy_at(addressof(rhs.unex));
|
|
@@ -872,29 +875,29 @@ friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)
|
|
| 872 |
``` cpp
|
| 873 |
constexpr const T* operator->() const noexcept;
|
| 874 |
constexpr T* operator->() noexcept;
|
| 875 |
```
|
| 876 |
|
| 877 |
-
|
| 878 |
|
| 879 |
*Returns:* `addressof(`*`val`*`)`.
|
| 880 |
|
| 881 |
``` cpp
|
| 882 |
constexpr const T& operator*() const & noexcept;
|
| 883 |
constexpr T& operator*() & noexcept;
|
| 884 |
```
|
| 885 |
|
| 886 |
-
|
| 887 |
|
| 888 |
*Returns:* *val*.
|
| 889 |
|
| 890 |
``` cpp
|
| 891 |
constexpr T&& operator*() && noexcept;
|
| 892 |
constexpr const T&& operator*() const && noexcept;
|
| 893 |
```
|
| 894 |
|
| 895 |
-
|
| 896 |
|
| 897 |
*Returns:* `std::move(`*`val`*`)`.
|
| 898 |
|
| 899 |
``` cpp
|
| 900 |
constexpr explicit operator bool() const noexcept;
|
|
@@ -931,34 +934,34 @@ constexpr const T&& value() const &&;
|
|
| 931 |
``` cpp
|
| 932 |
constexpr const E& error() const & noexcept;
|
| 933 |
constexpr E& error() & noexcept;
|
| 934 |
```
|
| 935 |
|
| 936 |
-
|
| 937 |
|
| 938 |
*Returns:* *unex*.
|
| 939 |
|
| 940 |
``` cpp
|
| 941 |
constexpr E&& error() && noexcept;
|
| 942 |
constexpr const E&& error() const && noexcept;
|
| 943 |
```
|
| 944 |
|
| 945 |
-
|
| 946 |
|
| 947 |
*Returns:* `std::move(`*`unex`*`)`.
|
| 948 |
|
| 949 |
``` cpp
|
| 950 |
-
template<class U> constexpr T value_or(U&& v) const &;
|
| 951 |
```
|
| 952 |
|
| 953 |
*Mandates:* `is_copy_constructible_v<T>` is `true` and
|
| 954 |
`is_convertible_v<U, T>` is `true`.
|
| 955 |
|
| 956 |
*Returns:* `has_value() ? **this : static_cast<T>(std::forward<U>(v))`.
|
| 957 |
|
| 958 |
``` cpp
|
| 959 |
-
template<class U> constexpr T value_or(U&& v) &&;
|
| 960 |
```
|
| 961 |
|
| 962 |
*Mandates:* `is_move_constructible_v<T>` is `true` and
|
| 963 |
`is_convertible_v<U, T>` is `true`.
|
| 964 |
|
|
@@ -990,45 +993,45 @@ template<class G = E> constexpr E error_or(G&& e) &&;
|
|
| 990 |
``` cpp
|
| 991 |
template<class F> constexpr auto and_then(F&& f) &;
|
| 992 |
template<class F> constexpr auto and_then(F&& f) const &;
|
| 993 |
```
|
| 994 |
|
| 995 |
-
Let `U` be `remove_cvref_t<invoke_result_t<F, decltype(
|
| 996 |
|
| 997 |
*Constraints:* `is_constructible_v<E, decltype(error())>` is `true`.
|
| 998 |
|
| 999 |
*Mandates:* `U` is a specialization of `expected` and
|
| 1000 |
-
`is_same_v<U::error_type, E>` is `true`.
|
| 1001 |
|
| 1002 |
*Effects:* Equivalent to:
|
| 1003 |
|
| 1004 |
``` cpp
|
| 1005 |
if (has_value())
|
| 1006 |
-
return invoke(std::forward<F>(f),
|
| 1007 |
else
|
| 1008 |
return U(unexpect, error());
|
| 1009 |
```
|
| 1010 |
|
| 1011 |
``` cpp
|
| 1012 |
template<class F> constexpr auto and_then(F&& f) &&;
|
| 1013 |
template<class F> constexpr auto and_then(F&& f) const &&;
|
| 1014 |
```
|
| 1015 |
|
| 1016 |
Let `U` be
|
| 1017 |
-
`remove_cvref_t<invoke_result_t<F, decltype(std::move(
|
| 1018 |
|
| 1019 |
*Constraints:* `is_constructible_v<E, decltype(std::move(error()))>` is
|
| 1020 |
`true`.
|
| 1021 |
|
| 1022 |
*Mandates:* `U` is a specialization of `expected` and
|
| 1023 |
-
`is_same_v<U::error_type, E>` is `true`.
|
| 1024 |
|
| 1025 |
*Effects:* Equivalent to:
|
| 1026 |
|
| 1027 |
``` cpp
|
| 1028 |
if (has_value())
|
| 1029 |
-
return invoke(std::forward<F>(f), std::move(
|
| 1030 |
else
|
| 1031 |
return U(unexpect, std::move(error()));
|
| 1032 |
```
|
| 1033 |
|
| 1034 |
``` cpp
|
|
@@ -1036,20 +1039,20 @@ template<class F> constexpr auto or_else(F&& f) &;
|
|
| 1036 |
template<class F> constexpr auto or_else(F&& f) const &;
|
| 1037 |
```
|
| 1038 |
|
| 1039 |
Let `G` be `remove_cvref_t<invoke_result_t<F, decltype(error())>>`.
|
| 1040 |
|
| 1041 |
-
*Constraints:* `is_constructible_v<T, decltype(
|
| 1042 |
|
| 1043 |
*Mandates:* `G` is a specialization of `expected` and
|
| 1044 |
-
`is_same_v<G::value_type, T>` is `true`.
|
| 1045 |
|
| 1046 |
*Effects:* Equivalent to:
|
| 1047 |
|
| 1048 |
``` cpp
|
| 1049 |
if (has_value())
|
| 1050 |
-
return G(in_place,
|
| 1051 |
else
|
| 1052 |
return invoke(std::forward<F>(f), error());
|
| 1053 |
```
|
| 1054 |
|
| 1055 |
``` cpp
|
|
@@ -1058,39 +1061,39 @@ template<class F> constexpr auto or_else(F&& f) const &&;
|
|
| 1058 |
```
|
| 1059 |
|
| 1060 |
Let `G` be
|
| 1061 |
`remove_cvref_t<invoke_result_t<F, decltype(std::move(error()))>>`.
|
| 1062 |
|
| 1063 |
-
*Constraints:* `is_constructible_v<T, decltype(std::move(
|
| 1064 |
-
`true`.
|
| 1065 |
|
| 1066 |
*Mandates:* `G` is a specialization of `expected` and
|
| 1067 |
-
`is_same_v<G::value_type, T>` is `true`.
|
| 1068 |
|
| 1069 |
*Effects:* Equivalent to:
|
| 1070 |
|
| 1071 |
``` cpp
|
| 1072 |
if (has_value())
|
| 1073 |
-
return G(in_place, std::move(
|
| 1074 |
else
|
| 1075 |
return invoke(std::forward<F>(f), std::move(error()));
|
| 1076 |
```
|
| 1077 |
|
| 1078 |
``` cpp
|
| 1079 |
template<class F> constexpr auto transform(F&& f) &;
|
| 1080 |
template<class F> constexpr auto transform(F&& f) const &;
|
| 1081 |
```
|
| 1082 |
|
| 1083 |
-
Let `U` be `remove_cv_t<invoke_result_t<F, decltype(
|
| 1084 |
|
| 1085 |
*Constraints:* `is_constructible_v<E, decltype(error())>` is `true`.
|
| 1086 |
|
| 1087 |
*Mandates:* `U` is a valid value type for `expected`. If `is_void_v<U>`
|
| 1088 |
is `false`, the declaration
|
| 1089 |
|
| 1090 |
``` cpp
|
| 1091 |
-
U u(invoke(std::forward<F>(f),
|
| 1092 |
```
|
| 1093 |
|
| 1094 |
is well-formed.
|
| 1095 |
|
| 1096 |
*Effects:*
|
|
@@ -1098,53 +1101,54 @@ is well-formed.
|
|
| 1098 |
- If `has_value()` is `false`, returns
|
| 1099 |
`expected<U, E>(unexpect, error())`.
|
| 1100 |
- Otherwise, if `is_void_v<U>` is `false`, returns an `expected<U, E>`
|
| 1101 |
object whose *has_val* member is `true` and *val* member is
|
| 1102 |
direct-non-list-initialized with
|
| 1103 |
-
`invoke(std::forward<F>(f),
|
| 1104 |
-
- Otherwise, evaluates `invoke(std::forward<F>(f),
|
| 1105 |
returns `expected<U, E>()`.
|
| 1106 |
|
| 1107 |
``` cpp
|
| 1108 |
template<class F> constexpr auto transform(F&& f) &&;
|
| 1109 |
template<class F> constexpr auto transform(F&& f) const &&;
|
| 1110 |
```
|
| 1111 |
|
| 1112 |
Let `U` be
|
| 1113 |
-
`remove_cv_t<invoke_result_t<F, decltype(std::move(
|
| 1114 |
|
| 1115 |
*Constraints:* `is_constructible_v<E, decltype(std::move(error()))>` is
|
| 1116 |
`true`.
|
| 1117 |
|
| 1118 |
*Mandates:* `U` is a valid value type for `expected`. If `is_void_v<U>`
|
| 1119 |
is `false`, the declaration
|
| 1120 |
|
| 1121 |
``` cpp
|
| 1122 |
-
U u(invoke(std::forward<F>(f), std::move(
|
| 1123 |
```
|
| 1124 |
|
| 1125 |
-
is well-formed
|
| 1126 |
|
| 1127 |
*Effects:*
|
| 1128 |
|
| 1129 |
- If `has_value()` is `false`, returns
|
| 1130 |
`expected<U, E>(unexpect, std::move(error()))`.
|
| 1131 |
- Otherwise, if `is_void_v<U>` is `false`, returns an `expected<U, E>`
|
| 1132 |
object whose *has_val* member is `true` and *val* member is
|
| 1133 |
direct-non-list-initialized with
|
| 1134 |
-
`invoke(std::forward<F>(f), std::move(
|
| 1135 |
-
- Otherwise, evaluates
|
| 1136 |
-
|
|
|
|
| 1137 |
|
| 1138 |
``` cpp
|
| 1139 |
template<class F> constexpr auto transform_error(F&& f) &;
|
| 1140 |
template<class F> constexpr auto transform_error(F&& f) const &;
|
| 1141 |
```
|
| 1142 |
|
| 1143 |
Let `G` be `remove_cv_t<invoke_result_t<F, decltype(error())>>`.
|
| 1144 |
|
| 1145 |
-
*Constraints:* `is_constructible_v<T, decltype(
|
| 1146 |
|
| 1147 |
*Mandates:* `G` is a valid template argument for `unexpected`
|
| 1148 |
[[expected.un.general]] and the declaration
|
| 1149 |
|
| 1150 |
``` cpp
|
|
@@ -1152,11 +1156,11 @@ G g(invoke(std::forward<F>(f), error()));
|
|
| 1152 |
```
|
| 1153 |
|
| 1154 |
is well-formed.
|
| 1155 |
|
| 1156 |
*Returns:* If `has_value()` is `true`,
|
| 1157 |
-
`expected<T, G>(in_place,
|
| 1158 |
object whose *has_val* member is `false` and *unex* member is
|
| 1159 |
direct-non-list-initialized with `invoke(std::forward<F>(f), error())`.
|
| 1160 |
|
| 1161 |
``` cpp
|
| 1162 |
template<class F> constexpr auto transform_error(F&& f) &&;
|
|
@@ -1164,12 +1168,12 @@ template<class F> constexpr auto transform_error(F&& f) const &&;
|
|
| 1164 |
```
|
| 1165 |
|
| 1166 |
Let `G` be
|
| 1167 |
`remove_cv_t<invoke_result_t<F, decltype(std::move(error()))>>`.
|
| 1168 |
|
| 1169 |
-
*Constraints:* `is_constructible_v<T, decltype(std::move(
|
| 1170 |
-
`true`.
|
| 1171 |
|
| 1172 |
*Mandates:* `G` is a valid template argument for `unexpected`
|
| 1173 |
[[expected.un.general]] and the declaration
|
| 1174 |
|
| 1175 |
``` cpp
|
|
@@ -1177,11 +1181,11 @@ G g(invoke(std::forward<F>(f), std::move(error())));
|
|
| 1177 |
```
|
| 1178 |
|
| 1179 |
is well-formed.
|
| 1180 |
|
| 1181 |
*Returns:* If `has_value()` is `true`,
|
| 1182 |
-
`expected<T, G>(in_place, std::move(
|
| 1183 |
`expected<T, G>` object whose *has_val* member is `false` and *unex*
|
| 1184 |
member is direct-non-list-initialized with
|
| 1185 |
`invoke(std::forward<F>(f), std::move(error()))`.
|
| 1186 |
|
| 1187 |
#### Equality operators <a id="expected.object.eq">[[expected.object.eq]]</a>
|
|
@@ -1189,34 +1193,35 @@ member is direct-non-list-initialized with
|
|
| 1189 |
``` cpp
|
| 1190 |
template<class T2, class E2> requires (!is_void_v<T2>)
|
| 1191 |
friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
|
| 1192 |
```
|
| 1193 |
|
| 1194 |
-
*
|
| 1195 |
-
well-formed and their results are convertible to `bool`.
|
| 1196 |
|
| 1197 |
*Returns:* If `x.has_value()` does not equal `y.has_value()`, `false`;
|
| 1198 |
otherwise if `x.has_value()` is `true`, `*x == *y`; otherwise
|
| 1199 |
`x.error() == y.error()`.
|
| 1200 |
|
| 1201 |
``` cpp
|
| 1202 |
template<class T2> friend constexpr bool operator==(const expected& x, const T2& v);
|
| 1203 |
```
|
| 1204 |
|
| 1205 |
-
*
|
| 1206 |
-
|
|
|
|
| 1207 |
|
| 1208 |
[*Note 1*: `T` need not be *Cpp17EqualityComparable*. — *end note*]
|
| 1209 |
|
| 1210 |
*Returns:* `x.has_value() && static_cast<bool>(*x == v)`.
|
| 1211 |
|
| 1212 |
``` cpp
|
| 1213 |
template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
|
| 1214 |
```
|
| 1215 |
|
| 1216 |
-
*
|
| 1217 |
-
its result is convertible to `bool`.
|
| 1218 |
|
| 1219 |
*Returns:*
|
| 1220 |
`!x.has_value() && static_cast<bool>(x.error() == e.error())`.
|
| 1221 |
|
| 1222 |
### Partial specialization of `expected` for `void` types <a id="expected.void">[[expected.void]]</a>
|
|
@@ -1273,12 +1278,12 @@ public:
|
|
| 1273 |
|
| 1274 |
// [expected.void.obs], observers
|
| 1275 |
constexpr explicit operator bool() const noexcept;
|
| 1276 |
constexpr bool has_value() const noexcept;
|
| 1277 |
constexpr void operator*() const noexcept;
|
| 1278 |
-
constexpr void value() const &;
|
| 1279 |
-
constexpr void value() &&;
|
| 1280 |
constexpr const E& error() const & noexcept;
|
| 1281 |
constexpr E& error() & noexcept;
|
| 1282 |
constexpr const E&& error() const && noexcept;
|
| 1283 |
constexpr E&& error() && noexcept;
|
| 1284 |
template<class G = E> constexpr E error_or(G&&) const &;
|
|
@@ -1315,15 +1320,13 @@ private:
|
|
| 1315 |
};
|
| 1316 |
};
|
| 1317 |
```
|
| 1318 |
|
| 1319 |
Any object of type `expected<T, E>` either represents a value of type
|
| 1320 |
-
`T`, or contains a value of type `E` within
|
| 1321 |
-
|
| 1322 |
-
|
| 1323 |
-
indicates whether the `expected<T, E>` object represents a value of type
|
| 1324 |
-
`T`.
|
| 1325 |
|
| 1326 |
A program that instantiates the definition of the template
|
| 1327 |
`expected<T, E>` with a type for the `E` parameter that is not a valid
|
| 1328 |
template argument for `unexpected` is ill-formed.
|
| 1329 |
|
|
@@ -1488,10 +1491,13 @@ constexpr expected& operator=(const expected& rhs);
|
|
| 1488 |
|
| 1489 |
``` cpp
|
| 1490 |
constexpr expected& operator=(expected&& rhs) noexcept(see below);
|
| 1491 |
```
|
| 1492 |
|
|
|
|
|
|
|
|
|
|
| 1493 |
*Effects:*
|
| 1494 |
|
| 1495 |
- If `this->has_value() && rhs.has_value()` is `true`, no effects.
|
| 1496 |
- Otherwise, if `this->has_value()` is `true`, equivalent to:
|
| 1497 |
``` cpp
|
|
@@ -1505,13 +1511,10 @@ constexpr expected& operator=(expected&& rhs) noexcept(see below);
|
|
| 1505 |
*Returns:* `*this`.
|
| 1506 |
|
| 1507 |
*Remarks:* The exception specification is equivalent to
|
| 1508 |
`is_nothrow_move_constructible_v<E> && is_nothrow_move_assignable_v<E>`.
|
| 1509 |
|
| 1510 |
-
This operator is defined as deleted unless `is_move_constructible_v<E>`
|
| 1511 |
-
is `true` and `is_move_assignable_v<E>` is `true`.
|
| 1512 |
-
|
| 1513 |
``` cpp
|
| 1514 |
template<class G>
|
| 1515 |
constexpr expected& operator=(const unexpected<G>& e);
|
| 1516 |
template<class G>
|
| 1517 |
constexpr expected& operator=(unexpected<G>&& e);
|
|
@@ -1556,12 +1559,12 @@ constexpr void swap(expected& rhs) noexcept(see below);
|
|
| 1556 |
|
| 1557 |
| \topline | `this->has_value()` | `!this->has_value()` |
|
| 1558 |
| -------- | ------------------- | -------------------- |
|
| 1559 |
|
| 1560 |
|
| 1561 |
-
For the case where `rhs.
|
| 1562 |
-
`true`, equivalent to:
|
| 1563 |
|
| 1564 |
``` cpp
|
| 1565 |
construct_at(addressof(unex), std::move(rhs.unex));
|
| 1566 |
destroy_at(addressof(rhs.unex));
|
| 1567 |
has_val = false;
|
|
@@ -1590,40 +1593,45 @@ constexpr bool has_value() const noexcept;
|
|
| 1590 |
|
| 1591 |
``` cpp
|
| 1592 |
constexpr void operator*() const noexcept;
|
| 1593 |
```
|
| 1594 |
|
| 1595 |
-
|
| 1596 |
|
| 1597 |
``` cpp
|
| 1598 |
constexpr void value() const &;
|
| 1599 |
```
|
| 1600 |
|
|
|
|
|
|
|
| 1601 |
*Throws:* `bad_expected_access(error())` if `has_value()` is `false`.
|
| 1602 |
|
| 1603 |
``` cpp
|
| 1604 |
constexpr void value() &&;
|
| 1605 |
```
|
| 1606 |
|
|
|
|
|
|
|
|
|
|
| 1607 |
*Throws:* `bad_expected_access(std::move(error()))` if `has_value()` is
|
| 1608 |
`false`.
|
| 1609 |
|
| 1610 |
``` cpp
|
| 1611 |
constexpr const E& error() const & noexcept;
|
| 1612 |
constexpr E& error() & noexcept;
|
| 1613 |
```
|
| 1614 |
|
| 1615 |
-
|
| 1616 |
|
| 1617 |
*Returns:* *unex*.
|
| 1618 |
|
| 1619 |
``` cpp
|
| 1620 |
constexpr E&& error() && noexcept;
|
| 1621 |
constexpr const E&& error() const && noexcept;
|
| 1622 |
```
|
| 1623 |
|
| 1624 |
-
|
| 1625 |
|
| 1626 |
*Returns:* `std::move(`*`unex`*`)`.
|
| 1627 |
|
| 1628 |
``` cpp
|
| 1629 |
template<class G = E> constexpr E error_or(G&& e) const &;
|
|
@@ -1655,11 +1663,11 @@ template<class F> constexpr auto and_then(F&& f) const &;
|
|
| 1655 |
Let `U` be `remove_cvref_t<invoke_result_t<F>>`.
|
| 1656 |
|
| 1657 |
*Constraints:* `is_constructible_v<E, decltype(error())>>` is `true`.
|
| 1658 |
|
| 1659 |
*Mandates:* `U` is a specialization of `expected` and
|
| 1660 |
-
`is_same_v<U::error_type, E>` is `true`.
|
| 1661 |
|
| 1662 |
*Effects:* Equivalent to:
|
| 1663 |
|
| 1664 |
``` cpp
|
| 1665 |
if (has_value())
|
|
@@ -1677,11 +1685,11 @@ Let `U` be `remove_cvref_t<invoke_result_t<F>>`.
|
|
| 1677 |
|
| 1678 |
*Constraints:* `is_constructible_v<E, decltype(std::move(error()))>` is
|
| 1679 |
`true`.
|
| 1680 |
|
| 1681 |
*Mandates:* `U` is a specialization of `expected` and
|
| 1682 |
-
`is_same_v<U::error_type, E>` is `true`.
|
| 1683 |
|
| 1684 |
*Effects:* Equivalent to:
|
| 1685 |
|
| 1686 |
``` cpp
|
| 1687 |
if (has_value())
|
|
@@ -1696,11 +1704,11 @@ template<class F> constexpr auto or_else(F&& f) const &;
|
|
| 1696 |
```
|
| 1697 |
|
| 1698 |
Let `G` be `remove_cvref_t<invoke_result_t<F, decltype(error())>>`.
|
| 1699 |
|
| 1700 |
*Mandates:* `G` is a specialization of `expected` and
|
| 1701 |
-
`is_same_v<G::value_type, T>` is `true`.
|
| 1702 |
|
| 1703 |
*Effects:* Equivalent to:
|
| 1704 |
|
| 1705 |
``` cpp
|
| 1706 |
if (has_value())
|
|
@@ -1716,11 +1724,11 @@ template<class F> constexpr auto or_else(F&& f) const &&;
|
|
| 1716 |
|
| 1717 |
Let `G` be
|
| 1718 |
`remove_cvref_t<invoke_result_t<F, decltype(std::move(error()))>>`.
|
| 1719 |
|
| 1720 |
*Mandates:* `G` is a specialization of `expected` and
|
| 1721 |
-
`is_same_v<G::value_type, T>` is `true`.
|
| 1722 |
|
| 1723 |
*Effects:* Equivalent to:
|
| 1724 |
|
| 1725 |
``` cpp
|
| 1726 |
if (has_value())
|
|
@@ -1834,22 +1842,22 @@ member is direct-non-list-initialized with
|
|
| 1834 |
``` cpp
|
| 1835 |
template<class T2, class E2> requires is_void_v<T2>
|
| 1836 |
friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
|
| 1837 |
```
|
| 1838 |
|
| 1839 |
-
*
|
| 1840 |
-
its result is convertible to `bool`.
|
| 1841 |
|
| 1842 |
*Returns:* If `x.has_value()` does not equal `y.has_value()`, `false`;
|
| 1843 |
otherwise `x.has_value() || static_cast<bool>(x.error() == y.error())`.
|
| 1844 |
|
| 1845 |
``` cpp
|
| 1846 |
template<class E2>
|
| 1847 |
friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
|
| 1848 |
```
|
| 1849 |
|
| 1850 |
-
*
|
| 1851 |
-
its result is convertible to `bool`.
|
| 1852 |
|
| 1853 |
*Returns:*
|
| 1854 |
`!x.has_value() && static_cast<bool>(x.error() == e.error())`.
|
| 1855 |
|
|
|
|
| 1 |
## Expected objects <a id="expected">[[expected]]</a>
|
| 2 |
|
| 3 |
+
### General <a id="expected.general">[[expected.general]]</a>
|
| 4 |
|
| 5 |
Subclause [[expected]] describes the class template `expected` that
|
| 6 |
represents expected objects. An `expected<T, E>` object holds an object
|
| 7 |
+
of type `T` or an object of type `E` and manages the lifetime of the
|
| 8 |
+
contained objects.
|
| 9 |
|
| 10 |
### Header `<expected>` synopsis <a id="expected.syn">[[expected.syn]]</a>
|
| 11 |
|
| 12 |
``` cpp
|
| 13 |
+
// mostly freestanding
|
| 14 |
namespace std {
|
| 15 |
// [expected.unexpected], class template unexpected
|
| 16 |
template<class E> class unexpected;
|
| 17 |
|
| 18 |
// [expected.bad], class template bad_expected_access
|
|
|
|
| 26 |
explicit unexpect_t() = default;
|
| 27 |
};
|
| 28 |
inline constexpr unexpect_t unexpect{};
|
| 29 |
|
| 30 |
// [expected.expected], class template expected
|
| 31 |
+
template<class T, class E> class expected; // partially freestanding
|
| 32 |
|
| 33 |
// [expected.void], partial specialization of expected for void types
|
| 34 |
+
template<class T, class E> requires is_void_v<T> class expected<T, E>; // partially freestanding
|
| 35 |
}
|
| 36 |
```
|
| 37 |
|
| 38 |
### Class template `unexpected` <a id="expected.unexpected">[[expected.unexpected]]</a>
|
| 39 |
|
|
|
|
| 180 |
``` cpp
|
| 181 |
namespace std {
|
| 182 |
template<class E>
|
| 183 |
class bad_expected_access : public bad_expected_access<void> {
|
| 184 |
public:
|
| 185 |
+
constexpr explicit bad_expected_access(E);
|
| 186 |
+
constexpr const char* what() const noexcept override;
|
| 187 |
+
constexpr E& error() & noexcept;
|
| 188 |
+
constexpr const E& error() const & noexcept;
|
| 189 |
+
constexpr E&& error() && noexcept;
|
| 190 |
+
constexpr const E&& error() const && noexcept;
|
| 191 |
|
| 192 |
private:
|
| 193 |
E unex; // exposition only
|
| 194 |
};
|
| 195 |
}
|
|
|
|
| 199 |
thrown as exceptions to report the situation where an attempt is made to
|
| 200 |
access the value of an `expected<T, E>` object for which `has_value()`
|
| 201 |
is `false`.
|
| 202 |
|
| 203 |
``` cpp
|
| 204 |
+
constexpr explicit bad_expected_access(E e);
|
| 205 |
```
|
| 206 |
|
| 207 |
*Effects:* Initializes *unex* with `std::move(e)`.
|
| 208 |
|
| 209 |
``` cpp
|
| 210 |
+
constexpr const E& error() const & noexcept;
|
| 211 |
+
constexpr E& error() & noexcept;
|
| 212 |
```
|
| 213 |
|
| 214 |
*Returns:* *unex*.
|
| 215 |
|
| 216 |
``` cpp
|
| 217 |
+
constexpr E&& error() && noexcept;
|
| 218 |
+
constexpr const E&& error() const && noexcept;
|
| 219 |
```
|
| 220 |
|
| 221 |
*Returns:* `std::move(`*`unex`*`)`.
|
| 222 |
|
| 223 |
``` cpp
|
| 224 |
+
constexpr const char* what() const noexcept override;
|
| 225 |
```
|
| 226 |
|
| 227 |
+
*Returns:* An *implementation-defined* NTBS, which during constant
|
| 228 |
+
evaluation is encoded with the ordinary literal encoding [[lex.ccon]].
|
| 229 |
|
| 230 |
### Class template specialization `bad_expected_access<void>` <a id="expected.bad.void">[[expected.bad.void]]</a>
|
| 231 |
|
| 232 |
``` cpp
|
| 233 |
namespace std {
|
| 234 |
template<>
|
| 235 |
class bad_expected_access<void> : public exception {
|
| 236 |
protected:
|
| 237 |
+
constexpr bad_expected_access() noexcept;
|
| 238 |
+
constexpr bad_expected_access(const bad_expected_access&) noexcept;
|
| 239 |
+
constexpr bad_expected_access(bad_expected_access&&) noexcept;
|
| 240 |
+
constexpr bad_expected_access& operator=(const bad_expected_access&) noexcept;
|
| 241 |
+
constexpr bad_expected_access& operator=(bad_expected_access&&) noexcept;
|
| 242 |
+
constexpr ~bad_expected_access();
|
| 243 |
|
| 244 |
public:
|
| 245 |
+
constexpr const char* what() const noexcept override;
|
| 246 |
};
|
| 247 |
}
|
| 248 |
```
|
| 249 |
|
| 250 |
``` cpp
|
| 251 |
+
constexpr const char* what() const noexcept override;
|
| 252 |
```
|
| 253 |
|
| 254 |
+
*Returns:* An *implementation-defined* NTBS, which during constant
|
| 255 |
+
evaluation is encoded with the ordinary literal encoding [[lex.ccon]].
|
| 256 |
|
| 257 |
### Class template `expected` <a id="expected.expected">[[expected.expected]]</a>
|
| 258 |
|
| 259 |
#### General <a id="expected.object.general">[[expected.object.general]]</a>
|
| 260 |
|
|
|
|
| 277 |
template<class U, class G>
|
| 278 |
constexpr explicit(see below) expected(const expected<U, G>&);
|
| 279 |
template<class U, class G>
|
| 280 |
constexpr explicit(see below) expected(expected<U, G>&&);
|
| 281 |
|
| 282 |
+
template<class U = remove_cv_t<T>>
|
| 283 |
constexpr explicit(see below) expected(U&& v);
|
| 284 |
|
| 285 |
template<class G>
|
| 286 |
constexpr explicit(see below) expected(const unexpected<G>&);
|
| 287 |
template<class G>
|
|
|
|
| 300 |
constexpr ~expected();
|
| 301 |
|
| 302 |
// [expected.object.assign], assignment
|
| 303 |
constexpr expected& operator=(const expected&);
|
| 304 |
constexpr expected& operator=(expected&&) noexcept(see below);
|
| 305 |
+
template<class U = remove_cv_t<T>> constexpr expected& operator=(U&&);
|
| 306 |
template<class G>
|
| 307 |
constexpr expected& operator=(const unexpected<G>&);
|
| 308 |
template<class G>
|
| 309 |
constexpr expected& operator=(unexpected<G>&&);
|
| 310 |
|
|
|
|
| 324 |
constexpr T& operator*() & noexcept;
|
| 325 |
constexpr const T&& operator*() const && noexcept;
|
| 326 |
constexpr T&& operator*() && noexcept;
|
| 327 |
constexpr explicit operator bool() const noexcept;
|
| 328 |
constexpr bool has_value() const noexcept;
|
| 329 |
+
constexpr const T& value() const &; // freestanding-deleted
|
| 330 |
+
constexpr T& value() &; // freestanding-deleted
|
| 331 |
+
constexpr const T&& value() const &&; // freestanding-deleted
|
| 332 |
+
constexpr T&& value() &&; // freestanding-deleted
|
| 333 |
constexpr const E& error() const & noexcept;
|
| 334 |
constexpr E& error() & noexcept;
|
| 335 |
constexpr const E&& error() const && noexcept;
|
| 336 |
constexpr E&& error() && noexcept;
|
| 337 |
+
template<class U = remove_cv_t<T>> constexpr T value_or(U&&) const &;
|
| 338 |
+
template<class U = remove_cv_t<T>> constexpr T value_or(U&&) &&;
|
| 339 |
template<class G = E> constexpr E error_or(G&&) const &;
|
| 340 |
template<class G = E> constexpr E error_or(G&&) &&;
|
| 341 |
|
| 342 |
// [expected.object.monadic], monadic operations
|
| 343 |
template<class F> constexpr auto and_then(F&& f) &;
|
|
|
|
| 374 |
};
|
| 375 |
}
|
| 376 |
```
|
| 377 |
|
| 378 |
Any object of type `expected<T, E>` either contains a value of type `T`
|
| 379 |
+
or a value of type `E` nested within [[intro.object]] it. Member
|
| 380 |
+
*`has_val`* indicates whether the `expected<T, E>` object contains an
|
| 381 |
+
object of type `T`.
|
|
|
|
|
|
|
| 382 |
|
| 383 |
A type `T` is a *valid value type for `expected`*, if `remove_cv_t<T>`
|
| 384 |
is `void` or a complete non-array object type that is not `in_place_t`,
|
| 385 |
`unexpect_t`, or a specialization of `unexpected`. A program which
|
| 386 |
instantiates class template `expected<T, E>` with an argument `T` that
|
|
|
|
| 496 |
|
| 497 |
*Remarks:* The expression inside `explicit` is equivalent to
|
| 498 |
`!is_convertible_v<UF, T> || !is_convertible_v<GF, E>`.
|
| 499 |
|
| 500 |
``` cpp
|
| 501 |
+
template<class U = remove_cv_t<T>>
|
| 502 |
constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);
|
| 503 |
```
|
| 504 |
|
| 505 |
*Constraints:*
|
| 506 |
|
| 507 |
- `is_same_v<remove_cvref_t<U>, in_place_t>` is `false`; and
|
| 508 |
+
- `is_same_v<remove_cvref_t<U>, expected>` is `false`; and
|
| 509 |
+
- `is_same_v<remove_cvref_t<U>, unexpect_t>` is `false`; and
|
| 510 |
- `remove_cvref_t<U>` is not a specialization of `unexpected`; and
|
| 511 |
- `is_constructible_v<T, U>` is `true`; and
|
| 512 |
- if `T` is cv `bool`, `remove_cvref_t<U>` is not a specialization of
|
| 513 |
`expected`.
|
| 514 |
|
|
|
|
| 608 |
`is_trivially_destructible_v<E>` is `true`, then this destructor is a
|
| 609 |
trivial destructor.
|
| 610 |
|
| 611 |
#### Assignment <a id="expected.object.assign">[[expected.object.assign]]</a>
|
| 612 |
|
| 613 |
+
This subclause makes use of the following exposition-only function
|
| 614 |
+
template:
|
| 615 |
|
| 616 |
``` cpp
|
| 617 |
template<class T, class U, class... Args>
|
| 618 |
constexpr void reinit-expected(T& newval, U& oldval, Args&&... args) { // exposition only
|
| 619 |
if constexpr (is_nothrow_constructible_v<T, Args...>) {
|
|
|
|
| 706 |
is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T> &&
|
| 707 |
is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>
|
| 708 |
```
|
| 709 |
|
| 710 |
``` cpp
|
| 711 |
+
template<class U = remove_cv_t<T>>
|
| 712 |
constexpr expected& operator=(U&& v);
|
| 713 |
```
|
| 714 |
|
| 715 |
*Constraints:*
|
| 716 |
|
|
|
|
| 822 |
|
| 823 |
| \topline | `this->has_value()` | `!this->has_value()` |
|
| 824 |
| -------- | ------------------- | -------------------- |
|
| 825 |
|
| 826 |
|
| 827 |
+
For the case where `rhs.has_value()` is `false` and `this->has_value()`
|
| 828 |
+
is `true`, equivalent to:
|
| 829 |
|
| 830 |
``` cpp
|
| 831 |
if constexpr (is_nothrow_move_constructible_v<E>) {
|
| 832 |
E tmp(std::move(rhs.unex));
|
| 833 |
destroy_at(addressof(rhs.unex));
|
|
|
|
| 875 |
``` cpp
|
| 876 |
constexpr const T* operator->() const noexcept;
|
| 877 |
constexpr T* operator->() noexcept;
|
| 878 |
```
|
| 879 |
|
| 880 |
+
`has_value()` is `true`.
|
| 881 |
|
| 882 |
*Returns:* `addressof(`*`val`*`)`.
|
| 883 |
|
| 884 |
``` cpp
|
| 885 |
constexpr const T& operator*() const & noexcept;
|
| 886 |
constexpr T& operator*() & noexcept;
|
| 887 |
```
|
| 888 |
|
| 889 |
+
`has_value()` is `true`.
|
| 890 |
|
| 891 |
*Returns:* *val*.
|
| 892 |
|
| 893 |
``` cpp
|
| 894 |
constexpr T&& operator*() && noexcept;
|
| 895 |
constexpr const T&& operator*() const && noexcept;
|
| 896 |
```
|
| 897 |
|
| 898 |
+
`has_value()` is `true`.
|
| 899 |
|
| 900 |
*Returns:* `std::move(`*`val`*`)`.
|
| 901 |
|
| 902 |
``` cpp
|
| 903 |
constexpr explicit operator bool() const noexcept;
|
|
|
|
| 934 |
``` cpp
|
| 935 |
constexpr const E& error() const & noexcept;
|
| 936 |
constexpr E& error() & noexcept;
|
| 937 |
```
|
| 938 |
|
| 939 |
+
`has_value()` is `false`.
|
| 940 |
|
| 941 |
*Returns:* *unex*.
|
| 942 |
|
| 943 |
``` cpp
|
| 944 |
constexpr E&& error() && noexcept;
|
| 945 |
constexpr const E&& error() const && noexcept;
|
| 946 |
```
|
| 947 |
|
| 948 |
+
`has_value()` is `false`.
|
| 949 |
|
| 950 |
*Returns:* `std::move(`*`unex`*`)`.
|
| 951 |
|
| 952 |
``` cpp
|
| 953 |
+
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) const &;
|
| 954 |
```
|
| 955 |
|
| 956 |
*Mandates:* `is_copy_constructible_v<T>` is `true` and
|
| 957 |
`is_convertible_v<U, T>` is `true`.
|
| 958 |
|
| 959 |
*Returns:* `has_value() ? **this : static_cast<T>(std::forward<U>(v))`.
|
| 960 |
|
| 961 |
``` cpp
|
| 962 |
+
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) &&;
|
| 963 |
```
|
| 964 |
|
| 965 |
*Mandates:* `is_move_constructible_v<T>` is `true` and
|
| 966 |
`is_convertible_v<U, T>` is `true`.
|
| 967 |
|
|
|
|
| 993 |
``` cpp
|
| 994 |
template<class F> constexpr auto and_then(F&& f) &;
|
| 995 |
template<class F> constexpr auto and_then(F&& f) const &;
|
| 996 |
```
|
| 997 |
|
| 998 |
+
Let `U` be `remove_cvref_t<invoke_result_t<F, decltype((`*`val`*`))>>`.
|
| 999 |
|
| 1000 |
*Constraints:* `is_constructible_v<E, decltype(error())>` is `true`.
|
| 1001 |
|
| 1002 |
*Mandates:* `U` is a specialization of `expected` and
|
| 1003 |
+
`is_same_v<typename U::error_type, E>` is `true`.
|
| 1004 |
|
| 1005 |
*Effects:* Equivalent to:
|
| 1006 |
|
| 1007 |
``` cpp
|
| 1008 |
if (has_value())
|
| 1009 |
+
return invoke(std::forward<F>(f), val);
|
| 1010 |
else
|
| 1011 |
return U(unexpect, error());
|
| 1012 |
```
|
| 1013 |
|
| 1014 |
``` cpp
|
| 1015 |
template<class F> constexpr auto and_then(F&& f) &&;
|
| 1016 |
template<class F> constexpr auto and_then(F&& f) const &&;
|
| 1017 |
```
|
| 1018 |
|
| 1019 |
Let `U` be
|
| 1020 |
+
`remove_cvref_t<invoke_result_t<F, decltype(std::move(`*`val`*`))>>`.
|
| 1021 |
|
| 1022 |
*Constraints:* `is_constructible_v<E, decltype(std::move(error()))>` is
|
| 1023 |
`true`.
|
| 1024 |
|
| 1025 |
*Mandates:* `U` is a specialization of `expected` and
|
| 1026 |
+
`is_same_v<typename U::error_type, E>` is `true`.
|
| 1027 |
|
| 1028 |
*Effects:* Equivalent to:
|
| 1029 |
|
| 1030 |
``` cpp
|
| 1031 |
if (has_value())
|
| 1032 |
+
return invoke(std::forward<F>(f), std::move(val));
|
| 1033 |
else
|
| 1034 |
return U(unexpect, std::move(error()));
|
| 1035 |
```
|
| 1036 |
|
| 1037 |
``` cpp
|
|
|
|
| 1039 |
template<class F> constexpr auto or_else(F&& f) const &;
|
| 1040 |
```
|
| 1041 |
|
| 1042 |
Let `G` be `remove_cvref_t<invoke_result_t<F, decltype(error())>>`.
|
| 1043 |
|
| 1044 |
+
*Constraints:* `is_constructible_v<T, decltype((`*`val`*`))>` is `true`.
|
| 1045 |
|
| 1046 |
*Mandates:* `G` is a specialization of `expected` and
|
| 1047 |
+
`is_same_v<typename G::value_type, T>` is `true`.
|
| 1048 |
|
| 1049 |
*Effects:* Equivalent to:
|
| 1050 |
|
| 1051 |
``` cpp
|
| 1052 |
if (has_value())
|
| 1053 |
+
return G(in_place, val);
|
| 1054 |
else
|
| 1055 |
return invoke(std::forward<F>(f), error());
|
| 1056 |
```
|
| 1057 |
|
| 1058 |
``` cpp
|
|
|
|
| 1061 |
```
|
| 1062 |
|
| 1063 |
Let `G` be
|
| 1064 |
`remove_cvref_t<invoke_result_t<F, decltype(std::move(error()))>>`.
|
| 1065 |
|
| 1066 |
+
*Constraints:* `is_constructible_v<T, decltype(std::move(`*`val`*`))>`
|
| 1067 |
+
is `true`.
|
| 1068 |
|
| 1069 |
*Mandates:* `G` is a specialization of `expected` and
|
| 1070 |
+
`is_same_v<typename G::value_type, T>` is `true`.
|
| 1071 |
|
| 1072 |
*Effects:* Equivalent to:
|
| 1073 |
|
| 1074 |
``` cpp
|
| 1075 |
if (has_value())
|
| 1076 |
+
return G(in_place, std::move(val));
|
| 1077 |
else
|
| 1078 |
return invoke(std::forward<F>(f), std::move(error()));
|
| 1079 |
```
|
| 1080 |
|
| 1081 |
``` cpp
|
| 1082 |
template<class F> constexpr auto transform(F&& f) &;
|
| 1083 |
template<class F> constexpr auto transform(F&& f) const &;
|
| 1084 |
```
|
| 1085 |
|
| 1086 |
+
Let `U` be `remove_cv_t<invoke_result_t<F, decltype((`*`val`*`))>>`.
|
| 1087 |
|
| 1088 |
*Constraints:* `is_constructible_v<E, decltype(error())>` is `true`.
|
| 1089 |
|
| 1090 |
*Mandates:* `U` is a valid value type for `expected`. If `is_void_v<U>`
|
| 1091 |
is `false`, the declaration
|
| 1092 |
|
| 1093 |
``` cpp
|
| 1094 |
+
U u(invoke(std::forward<F>(f), val));
|
| 1095 |
```
|
| 1096 |
|
| 1097 |
is well-formed.
|
| 1098 |
|
| 1099 |
*Effects:*
|
|
|
|
| 1101 |
- If `has_value()` is `false`, returns
|
| 1102 |
`expected<U, E>(unexpect, error())`.
|
| 1103 |
- Otherwise, if `is_void_v<U>` is `false`, returns an `expected<U, E>`
|
| 1104 |
object whose *has_val* member is `true` and *val* member is
|
| 1105 |
direct-non-list-initialized with
|
| 1106 |
+
`invoke(std::forward<F>(f), `*`val`*`)`.
|
| 1107 |
+
- Otherwise, evaluates `invoke(std::forward<F>(f), `*`val`*`)` and then
|
| 1108 |
returns `expected<U, E>()`.
|
| 1109 |
|
| 1110 |
``` cpp
|
| 1111 |
template<class F> constexpr auto transform(F&& f) &&;
|
| 1112 |
template<class F> constexpr auto transform(F&& f) const &&;
|
| 1113 |
```
|
| 1114 |
|
| 1115 |
Let `U` be
|
| 1116 |
+
`remove_cv_t<invoke_result_t<F, decltype(std::move(`*`val`*`))>>`.
|
| 1117 |
|
| 1118 |
*Constraints:* `is_constructible_v<E, decltype(std::move(error()))>` is
|
| 1119 |
`true`.
|
| 1120 |
|
| 1121 |
*Mandates:* `U` is a valid value type for `expected`. If `is_void_v<U>`
|
| 1122 |
is `false`, the declaration
|
| 1123 |
|
| 1124 |
``` cpp
|
| 1125 |
+
U u(invoke(std::forward<F>(f), std::move(val)));
|
| 1126 |
```
|
| 1127 |
|
| 1128 |
+
is well-formed.
|
| 1129 |
|
| 1130 |
*Effects:*
|
| 1131 |
|
| 1132 |
- If `has_value()` is `false`, returns
|
| 1133 |
`expected<U, E>(unexpect, std::move(error()))`.
|
| 1134 |
- Otherwise, if `is_void_v<U>` is `false`, returns an `expected<U, E>`
|
| 1135 |
object whose *has_val* member is `true` and *val* member is
|
| 1136 |
direct-non-list-initialized with
|
| 1137 |
+
`invoke(std::forward<F>(f), std::move(`*`val`*`))`.
|
| 1138 |
+
- Otherwise, evaluates
|
| 1139 |
+
`invoke(std::forward<F>(f), std::move(`*`val`*`))` and then returns
|
| 1140 |
+
`expected<U, E>()`.
|
| 1141 |
|
| 1142 |
``` cpp
|
| 1143 |
template<class F> constexpr auto transform_error(F&& f) &;
|
| 1144 |
template<class F> constexpr auto transform_error(F&& f) const &;
|
| 1145 |
```
|
| 1146 |
|
| 1147 |
Let `G` be `remove_cv_t<invoke_result_t<F, decltype(error())>>`.
|
| 1148 |
|
| 1149 |
+
*Constraints:* `is_constructible_v<T, decltype((`*`val`*`))>` is `true`.
|
| 1150 |
|
| 1151 |
*Mandates:* `G` is a valid template argument for `unexpected`
|
| 1152 |
[[expected.un.general]] and the declaration
|
| 1153 |
|
| 1154 |
``` cpp
|
|
|
|
| 1156 |
```
|
| 1157 |
|
| 1158 |
is well-formed.
|
| 1159 |
|
| 1160 |
*Returns:* If `has_value()` is `true`,
|
| 1161 |
+
`expected<T, G>(in_place, `*`val`*`)`; otherwise, an `expected<T, G>`
|
| 1162 |
object whose *has_val* member is `false` and *unex* member is
|
| 1163 |
direct-non-list-initialized with `invoke(std::forward<F>(f), error())`.
|
| 1164 |
|
| 1165 |
``` cpp
|
| 1166 |
template<class F> constexpr auto transform_error(F&& f) &&;
|
|
|
|
| 1168 |
```
|
| 1169 |
|
| 1170 |
Let `G` be
|
| 1171 |
`remove_cv_t<invoke_result_t<F, decltype(std::move(error()))>>`.
|
| 1172 |
|
| 1173 |
+
*Constraints:* `is_constructible_v<T, decltype(std::move(`*`val`*`))>`
|
| 1174 |
+
is `true`.
|
| 1175 |
|
| 1176 |
*Mandates:* `G` is a valid template argument for `unexpected`
|
| 1177 |
[[expected.un.general]] and the declaration
|
| 1178 |
|
| 1179 |
``` cpp
|
|
|
|
| 1181 |
```
|
| 1182 |
|
| 1183 |
is well-formed.
|
| 1184 |
|
| 1185 |
*Returns:* If `has_value()` is `true`,
|
| 1186 |
+
`expected<T, G>(in_place, std::move(`*`val`*`))`; otherwise, an
|
| 1187 |
`expected<T, G>` object whose *has_val* member is `false` and *unex*
|
| 1188 |
member is direct-non-list-initialized with
|
| 1189 |
`invoke(std::forward<F>(f), std::move(error()))`.
|
| 1190 |
|
| 1191 |
#### Equality operators <a id="expected.object.eq">[[expected.object.eq]]</a>
|
|
|
|
| 1193 |
``` cpp
|
| 1194 |
template<class T2, class E2> requires (!is_void_v<T2>)
|
| 1195 |
friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
|
| 1196 |
```
|
| 1197 |
|
| 1198 |
+
*Constraints:* The expressions `*x == *y` and `x.error() == y.error()`
|
| 1199 |
+
are well-formed and their results are convertible to `bool`.
|
| 1200 |
|
| 1201 |
*Returns:* If `x.has_value()` does not equal `y.has_value()`, `false`;
|
| 1202 |
otherwise if `x.has_value()` is `true`, `*x == *y`; otherwise
|
| 1203 |
`x.error() == y.error()`.
|
| 1204 |
|
| 1205 |
``` cpp
|
| 1206 |
template<class T2> friend constexpr bool operator==(const expected& x, const T2& v);
|
| 1207 |
```
|
| 1208 |
|
| 1209 |
+
*Constraints:* `T2` is not a specialization of `expected`. The
|
| 1210 |
+
expression `*x == v` is well-formed and its result is convertible to
|
| 1211 |
+
`bool`.
|
| 1212 |
|
| 1213 |
[*Note 1*: `T` need not be *Cpp17EqualityComparable*. — *end note*]
|
| 1214 |
|
| 1215 |
*Returns:* `x.has_value() && static_cast<bool>(*x == v)`.
|
| 1216 |
|
| 1217 |
``` cpp
|
| 1218 |
template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
|
| 1219 |
```
|
| 1220 |
|
| 1221 |
+
*Constraints:* The expression `x.error() == e.error()` is well-formed
|
| 1222 |
+
and its result is convertible to `bool`.
|
| 1223 |
|
| 1224 |
*Returns:*
|
| 1225 |
`!x.has_value() && static_cast<bool>(x.error() == e.error())`.
|
| 1226 |
|
| 1227 |
### Partial specialization of `expected` for `void` types <a id="expected.void">[[expected.void]]</a>
|
|
|
|
| 1278 |
|
| 1279 |
// [expected.void.obs], observers
|
| 1280 |
constexpr explicit operator bool() const noexcept;
|
| 1281 |
constexpr bool has_value() const noexcept;
|
| 1282 |
constexpr void operator*() const noexcept;
|
| 1283 |
+
constexpr void value() const &; // freestanding-deleted
|
| 1284 |
+
constexpr void value() &&; // freestanding-deleted
|
| 1285 |
constexpr const E& error() const & noexcept;
|
| 1286 |
constexpr E& error() & noexcept;
|
| 1287 |
constexpr const E&& error() const && noexcept;
|
| 1288 |
constexpr E&& error() && noexcept;
|
| 1289 |
template<class G = E> constexpr E error_or(G&&) const &;
|
|
|
|
| 1320 |
};
|
| 1321 |
};
|
| 1322 |
```
|
| 1323 |
|
| 1324 |
Any object of type `expected<T, E>` either represents a value of type
|
| 1325 |
+
`T`, or contains a value of type `E` nested within [[intro.object]] it.
|
| 1326 |
+
Member *`has_val`* indicates whether the `expected<T, E>` object
|
| 1327 |
+
represents a value of type `T`.
|
|
|
|
|
|
|
| 1328 |
|
| 1329 |
A program that instantiates the definition of the template
|
| 1330 |
`expected<T, E>` with a type for the `E` parameter that is not a valid
|
| 1331 |
template argument for `unexpected` is ill-formed.
|
| 1332 |
|
|
|
|
| 1491 |
|
| 1492 |
``` cpp
|
| 1493 |
constexpr expected& operator=(expected&& rhs) noexcept(see below);
|
| 1494 |
```
|
| 1495 |
|
| 1496 |
+
*Constraints:* `is_move_constructible_v<E>` is `true` and
|
| 1497 |
+
`is_move_assignable_v<E>` is `true`.
|
| 1498 |
+
|
| 1499 |
*Effects:*
|
| 1500 |
|
| 1501 |
- If `this->has_value() && rhs.has_value()` is `true`, no effects.
|
| 1502 |
- Otherwise, if `this->has_value()` is `true`, equivalent to:
|
| 1503 |
``` cpp
|
|
|
|
| 1511 |
*Returns:* `*this`.
|
| 1512 |
|
| 1513 |
*Remarks:* The exception specification is equivalent to
|
| 1514 |
`is_nothrow_move_constructible_v<E> && is_nothrow_move_assignable_v<E>`.
|
| 1515 |
|
|
|
|
|
|
|
|
|
|
| 1516 |
``` cpp
|
| 1517 |
template<class G>
|
| 1518 |
constexpr expected& operator=(const unexpected<G>& e);
|
| 1519 |
template<class G>
|
| 1520 |
constexpr expected& operator=(unexpected<G>&& e);
|
|
|
|
| 1559 |
|
| 1560 |
| \topline | `this->has_value()` | `!this->has_value()` |
|
| 1561 |
| -------- | ------------------- | -------------------- |
|
| 1562 |
|
| 1563 |
|
| 1564 |
+
For the case where `rhs.has_value()` is `false` and `this->has_value()`
|
| 1565 |
+
is `true`, equivalent to:
|
| 1566 |
|
| 1567 |
``` cpp
|
| 1568 |
construct_at(addressof(unex), std::move(rhs.unex));
|
| 1569 |
destroy_at(addressof(rhs.unex));
|
| 1570 |
has_val = false;
|
|
|
|
| 1593 |
|
| 1594 |
``` cpp
|
| 1595 |
constexpr void operator*() const noexcept;
|
| 1596 |
```
|
| 1597 |
|
| 1598 |
+
`has_value()` is `true`.
|
| 1599 |
|
| 1600 |
``` cpp
|
| 1601 |
constexpr void value() const &;
|
| 1602 |
```
|
| 1603 |
|
| 1604 |
+
*Mandates:* `is_copy_constructible_v<E>` is `true`.
|
| 1605 |
+
|
| 1606 |
*Throws:* `bad_expected_access(error())` if `has_value()` is `false`.
|
| 1607 |
|
| 1608 |
``` cpp
|
| 1609 |
constexpr void value() &&;
|
| 1610 |
```
|
| 1611 |
|
| 1612 |
+
*Mandates:* `is_copy_constructible_v<E>` is `true` and
|
| 1613 |
+
`is_move_constructible_v<E>` is `true`.
|
| 1614 |
+
|
| 1615 |
*Throws:* `bad_expected_access(std::move(error()))` if `has_value()` is
|
| 1616 |
`false`.
|
| 1617 |
|
| 1618 |
``` cpp
|
| 1619 |
constexpr const E& error() const & noexcept;
|
| 1620 |
constexpr E& error() & noexcept;
|
| 1621 |
```
|
| 1622 |
|
| 1623 |
+
`has_value()` is `false`.
|
| 1624 |
|
| 1625 |
*Returns:* *unex*.
|
| 1626 |
|
| 1627 |
``` cpp
|
| 1628 |
constexpr E&& error() && noexcept;
|
| 1629 |
constexpr const E&& error() const && noexcept;
|
| 1630 |
```
|
| 1631 |
|
| 1632 |
+
`has_value()` is `false`.
|
| 1633 |
|
| 1634 |
*Returns:* `std::move(`*`unex`*`)`.
|
| 1635 |
|
| 1636 |
``` cpp
|
| 1637 |
template<class G = E> constexpr E error_or(G&& e) const &;
|
|
|
|
| 1663 |
Let `U` be `remove_cvref_t<invoke_result_t<F>>`.
|
| 1664 |
|
| 1665 |
*Constraints:* `is_constructible_v<E, decltype(error())>>` is `true`.
|
| 1666 |
|
| 1667 |
*Mandates:* `U` is a specialization of `expected` and
|
| 1668 |
+
`is_same_v<typename U::error_type, E>` is `true`.
|
| 1669 |
|
| 1670 |
*Effects:* Equivalent to:
|
| 1671 |
|
| 1672 |
``` cpp
|
| 1673 |
if (has_value())
|
|
|
|
| 1685 |
|
| 1686 |
*Constraints:* `is_constructible_v<E, decltype(std::move(error()))>` is
|
| 1687 |
`true`.
|
| 1688 |
|
| 1689 |
*Mandates:* `U` is a specialization of `expected` and
|
| 1690 |
+
`is_same_v<typename U::error_type, E>` is `true`.
|
| 1691 |
|
| 1692 |
*Effects:* Equivalent to:
|
| 1693 |
|
| 1694 |
``` cpp
|
| 1695 |
if (has_value())
|
|
|
|
| 1704 |
```
|
| 1705 |
|
| 1706 |
Let `G` be `remove_cvref_t<invoke_result_t<F, decltype(error())>>`.
|
| 1707 |
|
| 1708 |
*Mandates:* `G` is a specialization of `expected` and
|
| 1709 |
+
`is_same_v<typename G::value_type, T>` is `true`.
|
| 1710 |
|
| 1711 |
*Effects:* Equivalent to:
|
| 1712 |
|
| 1713 |
``` cpp
|
| 1714 |
if (has_value())
|
|
|
|
| 1724 |
|
| 1725 |
Let `G` be
|
| 1726 |
`remove_cvref_t<invoke_result_t<F, decltype(std::move(error()))>>`.
|
| 1727 |
|
| 1728 |
*Mandates:* `G` is a specialization of `expected` and
|
| 1729 |
+
`is_same_v<typename G::value_type, T>` is `true`.
|
| 1730 |
|
| 1731 |
*Effects:* Equivalent to:
|
| 1732 |
|
| 1733 |
``` cpp
|
| 1734 |
if (has_value())
|
|
|
|
| 1842 |
``` cpp
|
| 1843 |
template<class T2, class E2> requires is_void_v<T2>
|
| 1844 |
friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
|
| 1845 |
```
|
| 1846 |
|
| 1847 |
+
*Constraints:* The expression `x.error() == y.error()` is well-formed
|
| 1848 |
+
and its result is convertible to `bool`.
|
| 1849 |
|
| 1850 |
*Returns:* If `x.has_value()` does not equal `y.has_value()`, `false`;
|
| 1851 |
otherwise `x.has_value() || static_cast<bool>(x.error() == y.error())`.
|
| 1852 |
|
| 1853 |
``` cpp
|
| 1854 |
template<class E2>
|
| 1855 |
friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
|
| 1856 |
```
|
| 1857 |
|
| 1858 |
+
*Constraints:* The expression `x.error() == e.error()` is well-formed
|
| 1859 |
+
and its result is convertible to `bool`.
|
| 1860 |
|
| 1861 |
*Returns:*
|
| 1862 |
`!x.has_value() && static_cast<bool>(x.error() == e.error())`.
|
| 1863 |
|