|
H5CPP
v1.14.0
Modern C++ templates for HDF5 serial and parallel I/O
|
|
h5cpp accepts std::unique_ptr<T[]>, std::shared_ptr<T[]>, std::unique_ptr<T>, and std::shared_ptr<T> anywhere a raw T* is accepted today — and also supports a return-style read that allocates the smart pointer for you, sized to the dataset extent.
All four smart-pointer flavours are supported (unique_ptr<T[]>, shared_ptr<T[]>, unique_ptr<T>, shared_ptr<T>).
| File | What it teaches |
|---|---|
smart_ptr.cpp | Five round-trips covering every supported smart-pointer flavour, including the auto-allocating return-style read. |
Expected output:
h5::write / h5::read overloads for std::unique_ptr<T[]> and std::shared_ptr<T[]> call .get() internally and delegate to the existing raw-pointer paths. The smart pointer is just a typed wrapper around the same T* that those paths already accept.
The smart pointer carries no length, so the explicit h5::count{...} is mandatory. There is no shape deduction from the pointer alone — the caller must say what to move.
h5::read<std::unique_ptr<T[]>>(fd, path) constructs a freshly-allocated buffer sized to the dataset's HDF5 extent, then reads into it. Useful when you want a clean owning handle without pre-allocating.
Under the hood the dispatch in H5Dread.hpp line 638 calls impl::get<std::unique_ptr<T[]>>::ctor(count) (registered in H5Mmemory.hpp), which does new T[total] with the size derived from the dataset extent.
This path is read-only — h5::write cannot use it because the smart pointer carries no length on write. Always pair the auto-alloc read with a separate length variable if you need the size downstream:
std::unique_ptr<T> / std::shared_ptr<T> (no []) are treated as a 1-element dataset. The forwarding overload synthesises h5::count{1} automatically:
Useful for niche cases (heap-resident scalar protocol fields, weak-ref scratch variables). For most code use a stack scalar and the existing h5::write(fd, path, value) surface.
Smart pointers compose cleanly with H5CPP_REGISTER_STRUCT — the registration declares the HDF5 compound type for T, and the smart-pointer mapper carries T* through the same way it would for any other primitive.
On disk this lands as:
Section 6 of smart_ptr.cpp exercises both a pre-allocated read and the auto-allocating return-style read on a compound POD type.
What does not work: a compound struct whose field is a smart pointer.
unique_ptr / shared_ptr aren't standard-layout, they have non-trivial destructors, and HDF5's compound type model has no representation for pointer-typed fields. Smart pointers can hold a struct or an array of structs; they cannot live inside one.
std::shared_ptr<T[]> makes the most sense when the buffer outlives the immediate I/O scope — for example, a reader that hands the buffer to multiple consumers, or a producer ring-buffer where readers all hold a shared_ptr. The library treats shared_ptr and unique_ptr identically at the I/O boundary; ownership semantics are entirely the caller's concern.
| Layer | File | What it adds |
|---|---|---|
| Trait registrations | h5cpp/H5Mmemory.hpp | impl::rank, impl::decay, impl::get<>::ctor, impl::data, access_traits_t, storage_representation_impl for all four smart-pointer flavours. Included from h5cpp/core. |
| Forwarding write/read | h5cpp/H5Mmemory_io.hpp | Free-function overloads of h5::write / h5::read for each smart-pointer flavour. Pulled in from h5cpp/io so the raw-pointer paths they delegate to are already declared. |
Including <h5cpp/all> brings both in automatically.
| Limitation | Why |
|---|---|
h5::write always needs an explicit h5::count{...}. | The smart pointer doesn't store a length. There's nothing for the library to deduce. |
Auto-allocating read uses new T[n](). | Value-initialises every element to zero. If you want unintialised memory for speed, pre-allocate yourself and use the forwarding overload. |
std::unique_ptr<T> / shared_ptr<T> (single) maps to a 1-element dataset. | Not a scalar attribute — it's a (1,) 1-D dataset. Use h5cpp's scalar surface for true scalar attributes. |
No support for std::weak_ptr. | Read/write require live ownership; the weak handle would have to be locked first. |
| Target | Status |
|---|---|
examples-smart-ptr | ✔ ok — five round-trips, all four smart-pointer flavours pass. |
No external library dependencies.
h5cpp/H5Mmemory.hpp / H5Mmemory_io.hpp** — implementation.examples/raw_memory/** — the raw-pointer surface this builds on. Same h5::write / h5::read shape with T* instead of unique_ptr<T[]>.examples/container/** — the same I/O dispatch surface for STL containers (which carry their own size and don't need an explicit h5::count).smart_ptr.cpp — rendered with syntax highlighting