std::expected
Материал из cppreference.com
<tbody>
</tbody>
| Определено в заголовочном файле <expected>
|
||
template< class T, class E > class expected; |
(начиная с C++23) | |
Шаблон класса std::expected позволяет хранить одно из двух значений. Объект std::expected в любой момент времени содержит либо ожидаемое значение типа T, либо неожидаемое значение типа E. std::expected никогда не бывает без значения.
Сохранённое значение распределяется непосредственно в хранилище, занимаемом объектом expected. Динамического выделения памяти не происходит.
Программа некорректна, если она создаёт экземпляр expected со ссылочным типом, типом функции или специализацией std::unexpected. Кроме того, T не должно быть std::in_place_t или std::unexpect_t.
Параметры шаблона
| T | — | тип ожидаемого значения. Тип должен быть либо (возможно, cv-квалифицированный) void, либо соответствовать требованиям Destructible (в частности, массивы и ссылочные типы не допускаются).
|
| E | — | тип неожидаемого значения. Тип должен соответствовать требованиям Destructible и должен быть допустимым аргументом шаблона для std::unexpected (в частности, массивы, необъектные типы и типы с cv-квалификацией не допускаются). |
Типы элементы
| Тип элемента | Определение |
value_type
|
T
|
error_type
|
E
|
unexpected_type
|
std::unexpected<E>
|
rebind
|
template< class U > using rebind = expected<U, error_type>;
|
Функции-элементы
создаёт объект expected (public функция-элемент) | |
уничтожает объект expected вместе с содержащимся в нём значением (public функция-элемент) | |
| присваивает содержимое (public функция-элемент) | |
Наблюдение | |
| обращается к ожидаемому значению (public функция-элемент) | |
| проверяет, содержит ли объект ожидаемое значение (public функция-элемент) | |
| возвращает ожидаемое значение (public функция-элемент) | |
| возвращает неожидаемое значение (public функция-элемент) | |
| возвращает ожидаемое значение, если оно присутствует, иначе другое значение (public функция-элемент) | |
Монадические операции | |
возвращает результат данной функции по ожидаемому значению, если оно существует; в противном случае возвращает сам expected (public функция-элемент) | |
возвращает expected, содержащий преобразованное ожидаемое значение, если оно существует; в противном случае возвращает сам expected (public функция-элемент) | |
возвращает само expected, если оно содержит ожидаемое значение; в противном случае возвращает результат данной функции для неожидаемого значения (public функция-элемент) | |
возвращает само expected, если оно содержит ожидаемое значение; в противном случае возвращает expected, содержащее преобразованное неожидаемое значение (public функция-элемент) | |
Модификаторы | |
| создаёт ожидаемое значение на месте (public функция-элемент) | |
| обменивает содержимое (public функция-элемент) | |
Функции, не являющиеся элементами
(C++23) |
сравнивает объекты expected (шаблон функции) |
(C++23) |
специализация алгоритма std::swap (функция) |
Вспомогательные классы
(C++23) |
представлен как неожидаемое значение (шаблон класса) |
(C++23) |
исключение, указывающее проверенный доступ к expected, содержащему неожидаемое значение (шаблон класса) |
(C++23) |
тег создания на месте для неожидаемого значения в expected (класс) (константа) |
Примечание
Типы с такой же функциональностью называются Result в Rust и Either в Haskell.
| Макрос тест функциональности | Значение | Стандарт | Комментарий |
|---|---|---|---|
__cpp_lib_expected |
202202L |
(C++23) | шаблон класса std::expected и связанные с ним вспомогательные классы
|
202211L |
(C++23) | Монадические функции для std::expected
|
Пример
Запустить этот код
#include <cmath>
#include <expected>
#include <iomanip>
#include <iostream>
#include <string_view>
enum class parse_error
{
invalid_input,
overflow
};
auto parse_number(std::string_view& str) -> std::expected<double, parse_error>
{
const char* begin = str.data();
char* end;
double retval = std::strtod(begin, &end);
if (begin == end)
return std::unexpected(parse_error::invalid_input);
else if (std::isinf(retval))
return std::unexpected(parse_error::overflow);
str.remove_prefix(end - begin);
return retval;
}
int main()
{
auto process = [](std::string_view str)
{
std::cout << "str: " << std::quoted(str) << ", ";
if (const auto num = parse_number(str); num.has_value())
std::cout << "значение: " << *num << '\n';
// Если бы num не имел значения, разыменование num
// ривело бы к неопределённому поведению, а
// num.value() сгенерировала бы std::bad_expected_access.
// num.value_or(123) использует указанное значение по умолчанию 123.
else if (num.error() == parse_error::invalid_input)
std::cout << "ошибка: неверный ввод\n";
else if (num.error() == parse_error::overflow)
std::cout << "ошибка: переполнение\n";
else
std::cout << "непредвиденный случай!\n"; // или invoke std::unreachable();
};
for (auto src: { "42", "42abc", "meow", "inf" })
process(src);
}
Вывод:
str: "42", значение: 42
str: "42abc", значение: 42
str: "meow", ошибка: неверный ввод
str: "inf", ошибка: переполнение
Ссылки
- C++23 стандарт (ISO/IEC 14882:2023):
- 22.8 Объекты expected [expected]
Смотрите также
(C++17) |
типобезопасное размеченное объединение (шаблон класса) |
(C++17) |
обёртка, которая может содержать или не содержать объект (шаблон класса) |