Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions c++/h5/stl/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,28 +39,29 @@ namespace h5 {
*/

/// Specialization of h5::hdf5_format_impl for std::map.
template <typename keyT, typename valueT>
struct hdf5_format_impl<std::map<keyT, valueT>> {
template <typename Key, typename T, typename Compare>
struct hdf5_format_impl<std::map<Key, T, Compare>> {
static std::string invoke() { return "Dict"; }
};

/**
* @brief Write a std::map to an HDF5 subgroup.
*
* @tparam keyT Key type of the std::map.
* @tparam valueT Value type of the std::map.
* @tparam Key Key type of the std::map.
* @tparam T Value type of the std::map.
* @tparam Compare Comparison type for the std::map.
* @param g h5::group in which the subgroup is created.
* @param name Name of the subgroup to which the std::map is written.
* @param m std::map to be written.
*/
template <typename keyT, typename valueT>
void h5_write(group g, std::string const &name, std::map<keyT, valueT> const &m) {
template <typename Key, typename T, typename Compare>
void h5_write(group g, std::string const &name, std::map<Key, T, Compare> const &m) {
// create the subgroup and write the hdf5_format tag
auto gr = g.create_group(name);
write_hdf5_format(gr, m);

// write element by element
if constexpr (std::is_same_v<keyT, std::string>) {
if constexpr (std::is_same_v<Key, std::string>) {
// if key is a string, use it for the dataset name
for (auto const &[key, val] : m) h5_write(gr, key, val);
} else {
Expand All @@ -78,29 +79,30 @@ namespace h5 {
/**
* @brief Read a std::map from an HDF5 subgroup.
*
* @tparam keyT Key type of the std::map.
* @tparam valueT Value type of the std::map.
* @tparam Key Key type of the std::map.
* @tparam T Value type of the std::map.
* @tparam Compare Comparison type for the std::map.
* @param g h5::group containing the subgroup.
* @param name Name of the subgroup from which the std::map is read.
* @param m std::map to read into.
*/
template <typename keyT, typename valueT>
void h5_read(group g, std::string const &name, std::map<keyT, valueT> &m) {
template <typename Key, typename T, typename Compare>
void h5_read(group g, std::string const &name, std::map<Key, T, Compare> &m) {
// open the subgroup and clear the map
auto gr = g.open_group(name);
m.clear();

// loop over all subgroups and datasets in the current group
for (auto const &x : gr.get_all_subgroup_dataset_names()) {
valueT val;
if constexpr (std::is_same_v<keyT, std::string>) {
T val;
if constexpr (std::is_same_v<Key, std::string>) {
// if key is a string, read from the dataset with the same name
h5_read(gr, x, val);
m.emplace(x, std::move(val));
} else {
// otherwise, read from the subgroup
auto element_gr = gr.open_group(x);
keyT key;
Key key;
h5_read(element_gr, "key", key);
h5_read(element_gr, "val", val);
m.emplace(std::move(key), std::move(val));
Expand Down
22 changes: 21 additions & 1 deletion test/c++/h5_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <h5/h5.hpp>

#include <complex>
#include <map>
#include <string>
#include <vector>
Expand Down Expand Up @@ -45,12 +46,31 @@ TEST(H5, MapWithStringKeyType) {
}
}

TEST(H5, MapWithGreaterComparison) {
// write/read a map with int keys and std::complex<double> values using std::greater as comparison
std::map<int, std::complex<double>, std::greater<int>> m_complex = {{1, {1.0, 2.0}}, {2, {3.0, 4.0}}};

{
h5::file file{"test_map_greater.h5", 'w'};
h5::write(file, "map_complex", m_complex);
}

{
h5::file file{"test_map_greater.h5", 'r'};

std::map<int, std::complex<double>, std::greater<int>> m_complex_in;
h5::read(file, "map_complex", m_complex_in);

EXPECT_EQ(m_complex, m_complex_in);
}
}

// Custom type to be used as a key in a map.
class custom_key_class {
int var;

public:
custom_key_class(int v = 0) : var(v){};
custom_key_class(int v = 0) : var(v) {};

static std::string hdf5_format() { return "TestkeyClass"; }

Expand Down