|
H5CPP
v1.14.0
Modern C++ templates for HDF5 serial and parallel I/O
|
|
Context-sensitive C++ exception hierarchy — every HDF5 CAPI failure surfaces as a typed exception that names which operation failed on which object kind, so callers can catch at the narrowest useful level.
HDF5's CAPI signals failure by negative return codes and pushes a diagnostic onto an internal error stack. Useful information lives in the stack; useful control flow comes from the return code. h5cpp collapses both into one mechanism: every failed CAPI call throws a typed C++ exception derived from h5::error::any : std::runtime_error, named after the operation that failed on the object kind it failed on.
The handler at your call site catches what it cares about; the rest propagates.
A C++ application calling HDF5 wants to distinguish failures by what was being attempted, not by a global error code. h5cpp's hierarchy is shaped exactly so:
Every leaf is its own type. Every intermediate is the "any" parent that catches a whole category at once.
The hierarchy is a real C++ inheritance chain — catch resolution follows standard rules. Catch the narrowest type you actually need to distinguish; let the rest propagate.
| Situation | Catch type | Reason |
|---|---|---|
| "File may not exist yet" — create on first run | h5::error::io::file::open | Just file-open; let other failures propagate |
| "Attribute may not be present" — use default | h5::error::io::attribute::open | Most callers want this exact type when reading optional metadata |
| "Read into too-small buffer" / "incompatible on-disk type" | h5::error::io::dataset::read | Distinguish from open-time failures (file/dataset) |
| Streaming append failure mid-flush | h5::error::io::dataset::append | Different recovery than a one-shot write |
| "Either dataset or attribute" partial-state recovery | h5::error::io::dataset::any, h5::error::io::attribute::any | Catch the kind, sub-distinguish at debug time |
| Library-level "anything went wrong" | h5::error::any | Last-resort handler before letting it propagate to main |
| Need the original HDF5 diagnostic text | Any leaf, then call .what() | h5cpp puts the HDF5 stack trace + the wrapping H5CPP_CHECK_NZ location into the message |
You can't tell whether the file was missing, the dataset was the wrong type, or you ran out of memory. Catch by exception type, not by hand-coded error-code switching.
CHECK_* macrosEvery HDF5 CAPI call in h5cpp goes through a small family of macros that wrap the return code, inspect the HDF5 error stack, and throw the contextual type:
capture_hdf5_error_stack() reads HDF5's internal error stack (via H5Eget_current_stack / H5Ewalk2) and folds it into the exception's .what() string before letting the exception fly. So you get:
H5Acreate.hpp:97) where the call failed— all in a single .what() you can log.
If you drop down to raw HDF5 inside h5cpp-based code, use the same macros so failures land in the same typed hierarchy:
This integrates cleanly: the application catches h5::error::io::attribute::open without needing to know whether it came from h5cpp's h5::open or your custom H5Aopen_by_idx wrapper.
A small set of exceptions signal **"a partial-state operation was
successfully rolled back"**. These are NOT derived from std::runtime_error (so they don't get caught by catch(std::exception&) in non-h5cpp-aware code) — instead they're a separate h5::error::*rollback family:
These are raised by the few operations that perform multi-step modifications and can clean up after themselves on failure (file creation across a flush boundary, dataset append after a partial chunk flush, attribute create when followed by a write that fails). The callee guarantees that on-disk state is consistent with pre-call state when a rollback is thrown.
For details on which operations are rollback-safe, see Error Handling — full reference.
mute / unmuteBy default the HDF5 CAPI also prints the error stack to stderr on every failure (separately from the typed exception h5cpp throws). This is helpful during development, noisy in production, and catastrophic in tight loops where failure is information:
h5::mute and h5::unmute work as RAII guards (recommended) or as manual switches. They suppress the HDF5 native stack-trace printing, not h5cpp's typed exceptions — those still fly.
h5::error::io::file::* leaves are the throws table for every file oph5::error::io::dataset::* leavesh5::error::io::attribute::* leaves