Abseil Code Review · 53/79
absl::any 분석
· Hawk · 2분 읽기
#std::any의 polyfill
C++17 std::any와 동일 인터페이스. C++17 이상 빌드에서는 std::any의 별칭.
#include "absl/types/any.h"
absl::any a = 42;a = std::string("hello");a = std::vector<int>{1, 2, 3};
if (a.has_value()) { auto v = absl::any_cast<std::vector<int>>(a);}#variant와의 차이
| 측면 | absl::variant<Ts...> | absl::any |
|---|---|---|
| 가능한 타입 | 컴파일 타임에 닫힌 집합 | 임의 (open) |
| sizeof | max(sizeof Ts) | 보통 32바이트 (포인터 + 컨트롤) |
| 큰 객체 | inline | 힙 할당 (SBO 가능) |
| 접근 | holds_alternative / get | any_cast<T> |
| visit | absl::visit 지원 | 없음 — 타입을 알아야 cast |
| 컴파일 시 검증 | 모든 alternative 강제 처리 | 런타임 cast 실패 |
variant는 알려진 닫힌 집합에, any는 플러그인·생명주기 컨테이너 같이 무엇이 들어올지 모를 때 쓴다.
#사용 — any_cast
absl::any a = std::string("hello");
// 값 cast (복사)auto s = absl::any_cast<std::string>(a); // string 복사
// reference cast (소유권 없음)auto& r = absl::any_cast<std::string&>(a);
// pointer cast (실패하면 nullptr)if (auto* p = absl::any_cast<std::string>(&a)) { use(*p);}any_cast<T>(any&)는 잘못된 타입이면 bad_any_cast throw. 안전한 시도는 pointer 버전.
#사용 예 — 플러그인 메타데이터
class Plugin {public: virtual ~Plugin() = default; virtual void Run() = 0;
void SetUserData(absl::any data) { user_data_ = std::move(data); } template <typename T> T* GetUserData() { return absl::any_cast<T>(&user_data_); }
private: absl::any user_data_;};
// 호출자plugin.SetUserData(std::string("config"));if (auto* s = plugin.GetUserData<std::string>()) { LOG(INFO) << "config = " << *s;}플러그인이 들고 다닐 타입을 라이브러리가 모를 때 적합. 단, 잘못된 cast는 런타임 에만 발견되므로 강한 타입을 우선한다.
#비용
| 작업 | 비용 |
|---|---|
| 작은 객체(보통 16바이트 이하) | inline storage — 할당 없음 |
| 큰 객체 | 힙 할당(new) |
any_cast<T> | typeid 비교 (대부분 RTTI 활용) |
| 복사 | 내부 타입의 복사 비용 |
RTTI 비활성화 빌드(-fno-rtti)에서는 any 사용 불가. Google 코드는 RTTI를 거의 안 쓰는데, any 도입 시 이 점을 의식해야 한다.
#회피 패턴
// 회피 — variant로 충분한데 any 사용absl::any color; // ❌ 무엇이 들어가지?color = "red";
// Good — 닫힌 집합은 variantenum class Color { kRed, kGreen, kBlue };absl::variant<Color, std::string /*hex*/> color;// 회피 — any를 API 경계로 흘리기absl::any Compute(); // ❌ 반환 타입을 호출자가 추측?
// Good — 의도가 명확한 타입absl::StatusOr<Result> Compute();absl::variant<Success, RateLimited, Error> Compute();// 회피 — RTTI 없는 빌드에서 any// 컴파일은 되지만 typeid가 빈 정보 → cast 실패#작은 예시 — 이벤트 디스패처
class Dispatcher {public: using Handler = std::function<void(const absl::any&)>;
template <typename T> void Subscribe(std::function<void(const T&)> fn) { handlers_[std::type_index(typeid(T))] = [fn = std::move(fn)](const absl::any& a) { if (auto* p = absl::any_cast<T>(&a)) { fn(*p); } }; }
void Dispatch(const absl::any& event) { auto it = handlers_.find(std::type_index(event.type())); if (it != handlers_.end()) it->second(event); }
private: absl::flat_hash_map<std::type_index, Handler> handlers_;};타입별 핸들러를 등록하고 이벤트를 type-erased로 흘린다. variant로는 컴파일 타임에 모든 이벤트 타입을 라이브러리가 알아야 해서 부적합.
#정리
absl::any는 임의 타입을 담는 type-erased 컨테이너.variant(닫힌 집합)와 달리 open set. 비용으로 RTTI·힙 할당이 들어올 수 있음.any_cast<T*>(&a)로 안전 cast. throw 버전은 잘못된 타입에서bad_any_cast.- 플러그인 메타데이터, 이벤트 디스패처 같이 타입이 외부에서 결정되는 경우에만.
- 코드베이스가 RTTI off라면 사용 불가.
#다음 장 예고
Part 9-07: absl::compare — three-way comparison.
#관련 항목
Abseil Code Review · 54 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::span 분석
absl::Span — 연속 메모리의 non-owning view. std::span의 친척이자 더 일찍 도착한 polyfill.
· cpp
같은 시리즈에서 이어 읽기
absl::variant 분석
absl::variant — std::variant의 polyfill. 타입-안전 union과 visitor 패턴.
· cpp
같은 시리즈에서 이어 읽기
absl::optional vs std::optional
absl::optional — std::optional이 도착하기 전 시기의 polyfill. 지금은 std::optional의 alias로 동작.
· cpp
같은 시리즈에서 이어 읽기