expected¶
类模板 std::expected
提供存储二个值之一的方式。 std::expected
的对象再任何给定时刻要么保有一个期待的T
类型值,要么保有一个不期待的 E
类型值。 std::expected
决不会无值。
1 定义¶
template< class T, class E >
class expected;
- T: 期待的值的类型。类型必须为(可有 cv 限定的) void 或符合可析构 (Destructible) 要求(尤其是不允许数组或引用类型)。
- E:不期待的值的类型。类型必须符合可析构 (Destructible) 要求,且必须对于 std::unexpected 为合法的模板形参(尤其是不允许数组、非对象类型及 cv 限定的类型)。
2 示例¶
#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 << "value: " << *num << '\n';
// If num did not have a value, dereferencing num
// would cause an undefined behavior, and
// num.value() would throw std::bad_expected_access.
// num.value_or(123) uses specified default value 123.
}
else if (num.error() == parse_error::invalid_input)
{
std::cout << "error: invalid input\n";
}
else if (num.error() == parse_error::overflow)
{
std::cout << "error: overflow\n";
}
else
{
std::cout << "unexpected!\n"; // or invoke std::unreachable();
}
};
for (auto src: { "42", "42abc", "meow", "inf" })
process(src);
}
str: "42", value: 42
str: "42abc", value: 42
str: "meow", error: invalid input
str: "inf", error: overflow