Using absl::Status and absl::StatusOr for C++ Error Handling: A Complete Guide
Use absl::Status to signal success or failure with error codes, and absl::StatusOr<T> to return either a value or an error, enabling explicit error handling without exceptions.
The absl::Status and absl::StatusOr<T> utilities in the abseil/abseil-cpp repository provide a robust, exception-free mechanism for handling errors in modern C++. These types implement the "return-error-or-value" pattern popularized by Google's internal codebase, offering lightweight semantics that encourage explicit error checking while maintaining zero-overhead abstractions.
Understanding absl::Status
In absl/status/status.h, absl::Status is implemented as a lightweight object that carries an absl::StatusCode and an optional message string. It serves as the fundamental currency for signaling operation success or failure throughout Abseil-based codebases.
Core API and Success Semantics
Success is represented by absl::OkStatus(), which returns a status with code kOk. The class provides a mirror of absl::StatusCode semantics through key accessors:
ok()– Returnstrueif the status code iskOk.code()– Retrieves theabsl::StatusCodeenum value.message()– Returns the error message string (empty for OK statuses).
The type is cheap to copy and can be returned from any function that only needs to signal success or failure without transporting a value.
Source Location Tracking
Both Status and StatusOr expose AddSourceLocation() and WithSourceLocation() methods defined in absl/status/status.h. These allow callers to attach call-site information for richer diagnostics, particularly useful when propagating errors up the stack:
return absl::NotFoundError("file not found")
.WithSourceLocation(); // Attaches caller location automatically
Understanding absl::StatusOr
Defined in absl/status/statusor.h, absl::StatusOr<T> is a discriminated union that holds either a value of type T or a non-OK Status. This pattern eliminates the need for output parameters or exceptions when returning values that might fail to generate.
Value vs. Error Contract
The fundamental contract is presence of a value ↔ ok() == true. When the operation succeeds, the object stores the constructed T; otherwise, it stores a Status indicating the error. The internal implementation in absl/status/internal/statusor_internal.h manages this union efficiently, storing the Status inline to avoid heap allocation when holding a value.
Accessing Values and Handling Errors
StatusOr<T> provides multiple accessors for safe value extraction:
ok()– Tests whether the object contains a value.status()– Retrieves the storedStatus(useful for error propagation).value()– Returns the value or throwsabsl::BadStatusOrAccessif exceptions are enabled and the status is not OK.operator*/operator->– Provide convenient value access after anok()check.value_or(default)– Returns the contained value or a supplied default if the status is not OK.IgnoreError()– Silences "unused-status" warnings when the caller intentionally discards an error.
The type is marked with ABSL_MUST_USE_RESULT (expanding to [[nodiscard]] on supported compilers) in absl/base/attributes.h, preventing accidental discarding of error information.
Key Architectural Features
The implementation provides several guarantees critical for high-performance C++:
Zero-allocation on success – When StatusOr<T> holds a value, the internal error storage is kept in a small inline representation, avoiding heap allocation entirely.
Conversion flexibility – The class provides converting constructors and assignments for compatible types, as well as in-place construction via std::in_place.
Thread-safe copying – The type is copyable and movable as long as T satisfies the corresponding operations, with no internal synchronization required.
Practical Implementation Examples
The following patterns demonstrate idiomatic usage according to the abseil/abseil-cpp source:
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/log/log.h"
// Returns either an int or an error
absl::StatusOr<int> ParseInt(absl::string_view text) {
int value;
if (absl::SimpleAtoi(text, &value)) {
return value; // Implicit construction from T
}
return absl::InvalidArgumentError("not an integer");
}
// Consumer code with explicit checking
absl::StatusOr<int> result = ParseInt("42");
if (result.ok()) {
LOG(INFO) << "Parsed value: " << *result; // operator* after ok()
} else {
LOG(ERROR) << "Parse failed: " << result.status();
}
// Using value_or for safe defaults
int safe = ParseInt("abc").value_or(0);
// Error propagation with source location
absl::StatusOr<std::string> LoadFile(absl::string_view path) {
if (/* simulated IO error */ false) {
return absl::NotFoundError("file not found")
.WithSourceLocation();
}
return std::string("file contents");
}
// Chaining with early return
absl::StatusOr<std::string> content = LoadFile("data.txt");
if (!content.ok()) return content.status(); // Propagate error
Summary
absl::Status(inabsl/status/status.h) signals success/failure via error codes, withabsl::OkStatus()representing success.absl::StatusOr<T>(inabsl/status/statusor.h) transports either a value or an error status,强制执行 explicit checking through[[nodiscard]]semantics.- Access values using
ok()followed byoperator*oroperator->, or usevalue_or()for default fallbacks. - Zero-allocation guarantees and inline storage make
StatusOrsuitable for performance-critical paths. - Source location tracking via
WithSourceLocation()aids debugging without macro magic.
Frequently Asked Questions
What is the difference between absl::Status and absl::StatusOr?
absl::Status only indicates success or failure via error codes and messages, while absl::StatusOr<T> is a discriminated union that either contains a value of type T or a non-OK status. Use Status for void functions that might fail, and StatusOr when you need to return a computed value or an error.
How do I handle errors without exceptions using StatusOr?
Check ok() before accessing the value, or use value_or() to provide a default. For error propagation, call status() to extract the underlying Status and return it upstream. The ABSL_MUST_USE_RESULT attribute ensures the compiler warns you if you accidentally ignore a returned error.
Does absl::StatusOr allocate memory on the heap?
No. The implementation uses inline storage for the Status object when a value is present, resulting in zero heap allocation on the success path. This is managed internally through the variant storage logic in absl/status/internal/statusor_internal.h.
How do I attach source location information to errors?
Call WithSourceLocation() on any absl::Status or absl::StatusOr to automatically capture the current file and line number. This information is stored within the status object and can be logged or serialized for debugging distributed systems.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →