absl::optional vs std::optional
#짧은 역사
std::optional은 C++17에 들어왔다. Abseil은 C++11 이후 Google이 사용하던 absl::optional을 그대로 유지하되, C++17 이상 빌드에서는 std의 별칭이 된다.
// absl/types/optional.h 의 의사 코드namespace absl {#if defined(ABSL_USES_STD_OPTIONAL) using std::optional; using std::nullopt; using std::make_optional; using std::in_place;#else template <typename T> class optional { /* polyfill */ };#endif}C++17/20/23 어디서나 absl::optional<T>를 써도 안전하다. 코드를 옮길 때마다 #include만 정리하면 된다.
#사용 — 표준 인터페이스
std::optional과 동일하다.
#include "absl/types/optional.h"
absl::optional<int> FindUserAge(absl::string_view name);
auto age = FindUserAge("alice");if (age.has_value()) { LOG(INFO) << "age = " << *age;}
int safe = age.value_or(0);
absl::optional<std::string> empty;empty = "hello";empty.reset();has_value() / operator bool / operator* / value() / value_or 모두 그대로.
#함수 반환에서의 가치
null pointer 대신 값을 옵셔널로 감싸면 수명·소유권 의문이 사라진다.
// 회피 — null 가능 raw pointerconst User* FindUser(int id); // 누가 소유? null이면?
// Good — optional valueabsl::optional<User> FindUser(int id);또는 error vs 부재 구분이 필요하면 StatusOr를 쓴다(다음 비교).
| 시그니처 | 의미 |
|---|---|
optional<T> | 값이 없을 수 있음. 부재가 정상. |
StatusOr<T> | 값이 있거나 에러. 에러 이유 전달. |
unique_ptr<T> | 값이 있거나 nullptr. 소유권 이동 필요할 때. |
const T* | 값이 있거나 nullptr. borrow. |
#in-place 생성
복사·이동 없이 직접 생성.
absl::optional<std::vector<int>> v(absl::in_place, {1, 2, 3, 4});
// 또는 make_optionalauto v2 = absl::make_optional<std::vector<int>>(10, 0); // 10개 0emplace도 같은 효과.
absl::optional<std::string> s;s.emplace("hello", 3); // "hel"#비교와 정렬
optional끼리 비교 가능. nullopt는 최소값으로 취급.
absl::optional<int> a = 5;absl::optional<int> b = 10;absl::optional<int> n;
a < b; // truen < a; // true — nullopt is "smaller"std::set<absl::optional<T>>도 자연스럽게 정렬한다.
#monadic 연산 — std는 있지만 absl polyfill에는 없음
C++23에 optional::and_then, transform, or_else가 들어왔다. absl::optional이 std alias로 동작하는 환경에서는 함께 사용 가능하지만, polyfill 시기에는 없다.
// C++23absl::optional<int> result = FindUser(id) .transform([](User u) { return u.age; });
// C++17/Abseil polyfill — 수동absl::optional<int> result;if (auto u = FindUser(id); u.has_value()) { result = u->age;}absl::optional을 polyfill 모드 로 강제하는 코드를 짤 일은 거의 없으므로 신경 쓰지 않아도 된다.
#absl 만의 추가 헬퍼
absl::optional은 std 호환을 우선해 추가 헬퍼를 거의 두지 않는다. 유일한 예외는 polyfill 시기의 trivial copy/destroy 최적화 정도다. Production 코드는 std::optional과 동일하게 다룬다.
#회피 패턴
// 회피 — value() 무방비 호출absl::optional<int> x = MaybeParse(s);int v = x.value(); // ❌ 비어 있으면 bad_optional_access throw
// Goodif (!x) return absl::InvalidArgumentError("parse failed");int v = *x;// 회피 — *를 if 가드 없이return *FindUser(id); // ❌ 부재일 때 UB
// Goodauto u = FindUser(id);if (!u) return absl::NotFoundError("...");return *u;// 회피 — optional<bool>은 의도 모호absl::optional<bool> done; // ❌ 세 상태: true/false/nullopt
// Good — enum classenum class Done { kNo, kYes, kUnknown };#std::optional 마이그레이션
C++17 이상 빌드라면 absl::optional ↔ std::optional은 같은 타입(alias)이다. 따라서 한 곳에서 다른 곳으로 자유롭게 통과시킨다.
absl::optional<int> a = 5;std::optional<int> s = a; // OK — 같은 타입장기 마이그레이션은 점진적으로 std::optional로 통일하면 된다. 헤더만 바꾸면 끝.
#정리
absl::optional<T>는 C++17 이상에서std::optional<T>의 별칭.- C++14 polyfill 시기에는 자체 구현으로 동일 인터페이스 제공.
- null pointer 대신 값으로 부재 표현 — 수명·소유권 의문 제거.
StatusOr(에러),unique_ptr(소유),T*(borrow)와 의도를 구분.- monadic 연산(C++23)은 std와 동일 — polyfill 시기에는 수동 분기.
#다음 장 예고
Part 9-04: absl::variant — std::variant의 polyfill.
#관련 항목
Abseil Code Review · 51 of 79
- 1 Abseil Code Review — Google production-grade C++ 라이브러리 분석
- 2 Abseil 개요 — Google이 std를 보완한 이유
- 3 Abseil 설계 철학 — std 호환과 추가 기능의 균형
- 4 Abseil 빌드와 의존성 — Bazel vs CMake
- 5 Abseil LTS vs HEAD 릴리스 모델 분석
- 6 Abseil Versioning과 ABI 호환성 정책
- 7 Abseil 매크로 — ABSL_HAVE_*·ABSL_ATTRIBUTE_*
- 8 Abseil ABSL_PREDICT_TRUE/FALSE — branch hint
- 9 absl::LogSeverity — 로그 레벨 타입
- 10 Abseil type_traits — negation·conjunction·void_t
- 11 Abseil Conformance·Policy 분석
- 12 Abseil Memory utilities 분석
- 13 Abseil raw_logging — heap-free 로깅
- 14 Abseil thread_annotations — clang TSA 통합
- 15 absl::Status — exception-free error handling
- 16 absl::StatusOr<T> — 값 또는 에러
- 17 absl status_macros — ASSIGN_OR_RETURN·RETURN_IF_ERROR
- 18 absl::Status payload — 구조화된 에러 컨텍스트
- 19 absl::Status ↔ exception 변환 패턴
- 20 absl::string_view — non-owning 문자열 참조
- 21 absl::string_view 함정 — dangling·c_str·임시 객체
- 22 absl::StrCat — 가변 인자 문자열 연결과 AlphaNum
- 23 absl::StrSplit — Delimiter·Predicate·컨테이너 변환
- 24 absl::StrJoin — 컨테이너 결합과 Formatter
- 25 absl::StrFormat — type-safe printf·FormatSpec
- 26 Abseil ASCII 함수 — locale-free 분류·대소문자 변환
- 27 Abseil Escape — CEscape·HexEscape·Base64
- 28 absl::flat_hash_map — Swiss Table 기반 hash map
- 29 absl::flat_hash_set — set 버전 Swiss Table
- 30 absl::node_hash_map — stable pointer가 필요할 때
- 31 absl::btree_map — sorted·cache-friendly B-tree
- 32 absl::FixedArray — 런타임 크기 stack 배열
- 33 absl::InlinedVector — small buffer optimization
- 34 Abseil Swiss Table internals — control byte·SIMD probing
- 35 absl::Mutex — reader-writer·fairness·deadlock 검출
- 36 absl::Mutex Conditional Critical Section — Await로 cv 없애기
- 37 absl::Notification — once-only signal
- 38 absl::BlockingCounter·Barrier — 다중 thread 조율
- 39 absl::Mutex annotations — clang thread-safety로 race를 컴파일 타임에
- 40 absl::Time·Duration 분석 — 단단한 type
- 41 absl::Time Format·Parse
- 42 absl::CivilTime 분석
- 43 absl::time_zone 분석
- 44 absl::Time mocking — 테스트 친화 시간
- 45 absl::BitGen — 모던 난수 생성기
- 46 Abseil Random Distributions — Uniform·Exponential
- 47 Abseil Mocking Random — 테스트 결정성
- 48 Abseil Random Seeding·Entropy
- 49 absl::int128·uint128 분석
- 50 absl::bits — popcount·countl_zero
- 51 absl::optional vs std::optional
- 52 absl::variant 분석
- 53 absl::span 분석
- 54 absl::any 분석
- 55 absl::compare — three-way 비교
- 56 Abseil utility — apply·in_place
- 57 Abseil AbslHashValue 분석
- 58 Abseil HashState chaining
- 59 Abseil Custom hashable 구현
- 60 Abseil LOG·VLOG·CHECK 분석
- 61 Abseil LogSink 분석
- 62 Abseil LogEntry·structured logging
- 63 Abseil Stack trace·failure_signal_handler
- 64 ABSL_FLAG 정의 분석
- 65 Abseil ParseCommandLine 동작
- 66 Abseil Flag introspection·validation
- 67 Google 스타일의 Abseil 사용 패턴
- 68 Abseil 자주 보는 anti-pattern
- 69 std → absl 마이그레이션 전략
- 70 absl::Cleanup — 함수 종료 시 실행 보장
- 71 Abseil algorithm container 확장 — c_sort·c_find_if·c_count_if
- 72 absl::function_ref와 any_invocable — 함수 객체 전달의 두 축
- 73 absl::bind_front와 Overload — 함수 객체 보조 도구
- 74 absl::Cord — 분산 시스템용 대용량 문자열
- 75 absl::from_chars·SimpleAtoi — 빠른 숫자 변환
- 76 absl::Cord vs std::string — 선택 기준과 메모리 프로파일
- 77 absl::GetStackTrace와 Symbolize — crash 시 readable stack
- 78 absl::ComputeCrc32c — 하드웨어 가속 체크섬
- 79 absl::PeriodicSampler — 적응형 샘플링·jitter 회피
관련 글
absl::any 분석
absl::any — 임의 타입을 담는 type-erased 컨테이너. variant와 언제 어떻게 다른가.
같은 시리즈에서 이어 읽기
absl::span 분석
absl::Span — 연속 메모리의 non-owning view. std::span의 친척이자 더 일찍 도착한 polyfill.
같은 시리즈에서 이어 읽기
absl::variant 분석
absl::variant — std::variant의 polyfill. 타입-안전 union과 visitor 패턴.
같은 시리즈에서 이어 읽기
이 글을 참조하는 글 (6)
- Abseil utility — apply·in_place — Abseil Code Review
- absl::variant 분석 — Abseil Code Review
- absl::bits — popcount·countl_zero — Abseil Code Review
- absl::StatusOr<T> — 값 또는 에러 — Abseil Code Review
- Abseil Memory utilities 분석 — Abseil Code Review
- Abseil type_traits — negation·conjunction·void_t — Abseil Code Review