utility_expected (std::expected - 예상 값 또는 예상치 못한 값 표현)
std::expected 클래스 템플릿은 두 값 중 하나를 나타내는 방법을 제공해요. T 타입의 예상 값(expected value) 또는 E 타입의 예상치 못한 값(unexpected value)을 저장할 수 있지요. expected 객체는 절대 값이 없는 상태가 아니며, 성공 또는 실패 결과를 명시적으로 다룰 때 유용해요.
이 페이지에서는 C++23부터 도입된 std::expected의 템플릿 매개변수, 중첩 타입, 멤버 함수, 비멤버 함수, 헬퍼 클래스 등을 자세히 설명할게요.
출처: cppreference
본문
<expected> 헤더에 정의되어 있어요.
| 정의 |
|
|
template < class T , class E > class expected ; |
(1) |
(since C++23) |
template < class T , class E > requires std :: is_void_v < T > class expected < T , E > ; |
(2) |
(since C++23) |
std::expected 클래스 템플릿은 두 값 중 하나를 나타내는 방법을 제공해요. T 타입의 예상 값 또는 E 타입의 예상치 못한 값이지요. expected는 절대 값이 없는 상태가 아니에요.
참조 타입, 함수 타입 또는 std::unexpected의 특수화로 expected를 인스턴스화하면 프로그램은 ill-formed예요. 또한 T는 std::in_place_t나 std::unexpect_t가 아니어야 해요.
템플릿 매개변수
| T |
- |
예상 값의 타입이에요. (cv-qualified) void이거나 Destructible 요구 사항을 충족해야 해요. 특히 배열과 참조 타입은 허용되지 않아요. |
| E |
- |
예상치 못한 값의 타입이에요. Destructible 요구 사항을 충족해야 하고, std::unexpected의 유효한 템플릿 인자여야 해요. 특히 배열, 비객체 타입, cv-qualified 타입은 허용되지 않아요. |
중첩 타입
| 타입 |
정의 |
value_type |
T |
error_type |
E |
unexpected_type |
std::unexpected<E> |
멤버 템플릿
| 템플릿 |
정의 |
rebind < U > |
std :: expected < U , error_type > |
데이터 멤버
| 멤버 |
설명 |
bool has_val |
expected 객체가 현재 예상 값을 나타내는지 여부 (설명 전용 멤버 객체*) |
T val (메인 템플릿만) |
예상 값 (설명 전용 variant 멤버 객체*) |
E unex |
예상치 못한 값 (설명 전용 variant 멤버 객체*) |
멤버 함수
| (constructor) |
expected 객체를 생성해요 (공용 멤버 함수) [edit] |
| (destructor) |
expected 객체와 포함된 값을 소멸해요 (공용 멤버 함수) [edit] |
operator= |
내용을 할당해요 (공용 멤버 함수) [edit] |
| Observers |
|
operator-> operator* |
예상 값에 접근해요 (공용 멤버 함수) [edit] |
operator bool has_value |
객체가 예상 값을 포함하는지 확인해요 (공용 멤버 함수) [edit] |
value |
예상 값을 반환해요 (공용 멤버 함수) [edit] |
error |
예상치 못한 값을 반환해요 (공용 멤버 함수) [edit] |
value_or |
예상 값이 있으면 그 값을, 없으면 다른 값을 반환해요 (공용 멤버 함수) [edit] |
error_or |
예상치 못한 값이 있으면 그 값을, 없으면 다른 값을 반환해요 (공용 멤버 함수) [edit] |
| Monadic operations |
|
and_then |
예상 값이 있으면 주어진 함수를 적용한 결과를 반환하고, 없으면 expected 자신을 반환해요 (공용 멤버 함수) [edit] |
transform |
예상 값이 있으면 변환된 예상 값을 담은 expected를 반환하고, 없으면 expected 자신을 반환해요 (공용 멤버 함수) [edit] |
or_else |
예상 값이 있으면 expected 자신을 반환하고, 없으면 예상치 못한 값에 주어진 함수를 적용한 결과를 반환해요 (공용 멤버 함수) [edit] |
transform_error |
예상 값이 있으면 expected 자신을 반환하고, 없으면 변환된 예상치 못한 값을 담은 expected를 반환해요 (공용 멤버 함수) [edit] |
| Modifiers |
|
emplace |
예상 값을 제자리에서 생성해요 (공용 멤버 함수) [edit] |
swap |
내용을 교환해요 (공용 멤버 함수) [edit] |
비멤버 함수
operator== (C++23) |
expected 객체를 비교해요 (함수 템플릿) [edit] |
swap (std::expected) (C++23) |
std::swap 알고리즘을 특수화해요 (함수) [edit] |
헬퍼 클래스
unexpected (C++23) |
예상치 못한 값으로 표현돼요 (클래스 템플릿) [edit] |
bad_expected_access (C++23) |
예상치 못한 값을 포함하는 expected에 대한 확인된 접근을 나타내는 예외예요 (클래스 템플릿) [edit] |
unexpect unexpect_t (C++23) |
expected의 예상치 못한 값에 대한 제자리 생성 태그예요 (태그) [edit] |
참고 사항
같은 기능을 가진 타입은 Rust에서는 Result, Haskell에서는 Either라고 불러요.
| Feature-test macro |
값 |
표준 |
기능 |
__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 << "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
결함 보고서
다음 동작 변경 결함 보고서는 이전에 발표된 C++ 표준에 소급 적용되었어요.
| DR |
적용 대상 |
발표된 동작 |
올바른 동작 |
| LWG 4141 |
C++23 |
저장 공간 할당 요구 사항이 혼란스러웠어요 |
포함된 객체는 expected 객체 안에 중첩되어야 해요 |
참고 문헌
- C++23 표준 (ISO/IEC 14882:2024):
- 22.8 Expected objects [expected]
같이 보기
variant (C++17) |
타입 안전한 구분 유니온 (클래스 템플릿) [edit] |
optional (C++17) |
객체를 보유할 수도 있고 보유하지 않을 수도 있는 래퍼 (클래스 템플릿) [edit] |
더 알아보기 (Learn more)
cppreference