|
H5CPP
v1.14.0
Modern C++ templates for HDF5 serial and parallel I/O
|
|
This example proves a single property of h5cpp: you can include the same generated.h (the file that registers your POD structs as HDF5 compound types) in any number of translation units, and the linker will not complain.
That property is what makes h5cpp usable in real codebases. A single-TU example wouldn't show it — for that you need at least two .cpp files that both touch the type system, linked together into one executable.
The lesson is in the link step: tu-01.o and tu-02.o each carry their own copy of the register_struct<sn::example::record_t>() and register_struct<sn::typecheck::record_t>() definitions. The linker keeps one and discards the rest because the bodies are inline. Nothing else is required — no static, no anonymous namespace, no per-TU header guards.
Expected output:
Inspect the resulting multi-tu.h5:
You should see /linalg/armadillo (20×5 i64), /orm/chunked_2D (compound, chunked + gzipped), /orm/typecheck (unlimited 1-D), and /orm/partial/{one_shot,custom_dims} (compound vectors).
generated.hEarlier versions of this example shipped two separate generated headers (tu-01.h, tu-02.h), each with its own H5CPP_GUARD_* include guard. The intent was to show that a code generator could emit a header per TU. In practice that pattern is more confusing than the truth:
H5CPP_REGISTER_STRUCT(...) body is inline, so a single shared header is ODR-safe by construction.Modern h5cpp examples (compound/, csv/, stl/) all use one shared generated.h. This one now matches.
| TU | Includes | Why |
|---|---|---|
main.cpp | <h5cpp/all> | Only handles h5::fd_t; never names a compound type, so generated.h is dead weight here. |
tu-01.cpp | <armadillo>, <h5cpp/all>, "generated.h" | Mixes a linalg write with h5::create<record_t> calls in the same TU. |
tu-02.cpp | <h5cpp/all>, "generated.h" | Pure compound vector path — write, read, project a scalar field. |
generated.h itself pulls in <h5cpp/all> and "struct.h", so a TU that includes generated.h doesn't need to repeat them.
Pre-refactor each .cpp was structured like this:
The sandwich-between-core-and-io requirement is gone. The new shape is:
That same shape works whether you have one TU or twenty.
| Target | Status |
|---|---|
examples-multi-tu | ✔ ok — links two TUs sharing generated.h, runs clean |
Gated on ARMADILLO_FOUND in examples/CMakeLists.txt:377-388.
examples/compound/** — the single-TU version, same record_t types, same generated.h style. Start there if you're new to the compound path.examples/csv/** — another example that uses one shared generated.h (with a simpler struct).h5cpp/H5Tall.hpp** — H5CPP_REGISTER_STRUCT and register_struct<> live here; this is where the inline lives that makes the multi-TU story work.generated.h — rendered with syntax highlightingmain.cpp — rendered with syntax highlightingstruct.h — rendered with syntax highlightingtu-01.cpp — rendered with syntax highlightingtu-02.cpp — rendered with syntax highlighting