working hmap class

This commit is contained in:
Timur A. Fatkhullin
2026-09-02 21:18:07 +03:00
parent a49e7b5d5f
commit d35d356784
2 changed files with 46 additions and 30 deletions

View File

@@ -182,23 +182,8 @@ int main()
std::print("push element with key '{}' and value {}\t...", k2, s1); std::print("push element with key '{}' and value {}\t...", k2, s1);
ok = hm.push( ok = hm.push(
k2, s1, k2, s1, [](auto const& v) -> hmap_expected_t<const char*> { return v.c_str(); },
[](auto const& v) -> decltype(hm)::hmap_expected_t<const char*> { [](auto const& v) -> hmap_expected_t<std::string> { return std::string(v); });
return v.c_str();
// if (v) {
// return v.c_str();
// } else {
// return std::unexpected(v.error());
// }
},
[](auto const& v) -> decltype(hm)::hmap_expected_t<std::string> {
return std::string(v.value());
// if (v) {
// return std::string(v.value());
// } else {
// return std::unexpected(v.error());
// }
});
if (!ok) { if (!ok) {
std::println("cannot insert the value {}", s1); std::println("cannot insert the value {}", s1);
} else { } else {
@@ -213,6 +198,8 @@ int main()
std::println("OK"); std::println("OK");
} }
std::println("in total {} elelents were pushed", hm.size());
std::println("\n"); std::println("\n");
std::print("get '{}'-element as double: ", k1); std::print("get '{}'-element as double: ", k1);
@@ -223,5 +210,15 @@ int main()
std::println("FAIL"); std::println("FAIL");
} }
std::println("\n");
std::print("get '{}'-element as const char*: ", k2);
auto sp2 = hm.get<const char*>(k2);
if (sp2) {
std::println("{}", sp2.value());
} else {
std::println("FAIL");
}
return 0; return 0;
} }

View File

@@ -116,6 +116,7 @@ public:
return does_contain; return does_contain;
} }
void clear() void clear()
{ {
for (auto& func : _clearFunc) { for (auto& func : _clearFunc) {
@@ -413,15 +414,17 @@ inline std::error_code make_error_code(hmap_error_e ec)
} }
typedef std::error_code hmap_error_t;
template <typename VT>
using hmap_expected_t = std::expected<VT, hmap_error_t>;
template <snplib_hashable_c KeyT> template <snplib_hashable_c KeyT>
class hmap class hmap
{ {
public: public:
typedef std::error_code error_t;
template <typename VT>
using hmap_expected_t = std::expected<VT, hmap::error_t>;
template <typename VT, typename UT> template <typename VT, typename UT>
using hmap_user_conv_from_t = std::function<hmap_expected_t<UT>(hmap_expected_t<VT> const&)>; using hmap_user_conv_from_t = std::function<hmap_expected_t<UT>(hmap_expected_t<VT> const&)>;
@@ -439,7 +442,7 @@ protected:
template <typename UT> template <typename UT>
inline static std::unordered_map<const hmap*, inline static std::unordered_map<const hmap*,
std::unordered_map<KeyT, std::function<hmap::error_t(UT const&, const hmap*)>>> std::unordered_map<KeyT, std::function<hmap_error_t(UT const&, const hmap*)>>>
_setter{}; _setter{};
@@ -555,6 +558,16 @@ public:
return does_contain; return does_contain;
} }
bool erase(KeyT const& key)
{
bool ok = false;
for (auto& func : _eraseFunc) {
ok |= func(key, this);
}
return ok;
}
void clear() void clear()
{ {
for (auto& func : _clearFunc) { for (auto& func : _clearFunc) {
@@ -574,6 +587,7 @@ public:
return N; return N;
} }
template <typename VT> template <typename VT>
bool push(KeyT const& key, VT&& value) bool push(KeyT const& key, VT&& value)
{ {
@@ -632,7 +646,9 @@ public:
// NOTE: do not use here iterator since after insertion // NOTE: do not use here iterator since after insertion
// an rehashing may occur and all iterators will be invalidated! // an rehashing may occur and all iterators will be invalidated!
_getter<v_t>[this].emplace(key, [key](const hmap* obj) { return _values<v_t>[obj][key]; }); _getter<v_t>[this].emplace(key,
[key](const hmap* obj) -> hmap_expected_t<v_t> { return _values<v_t>[obj][key]; });
_setter<v_t>[this].emplace(key, [key](const v_t& v, const hmap* obj) { _setter<v_t>[this].emplace(key, [key](const v_t& v, const hmap* obj) {
_values<v_t>[obj][key] = v; _values<v_t>[obj][key] = v;
return hmap_error_e::ERROR_OK; return hmap_error_e::ERROR_OK;
@@ -643,8 +659,8 @@ public:
// FTs - conversional functions: // FTs - conversional functions:
// convert-from: std::function<hmap_expected_t<UT>(hmap_expected_t<VT> const&)> (from inner type to user) // convert-from: std::function<hmap_expected_t<UT>(VT const&)> (from inner type to user)
// convert-to: std::function<hmap_expected_t<VT>(hmap_expected_t<UT> const&)> (from user type to inner) // convert-to: std::function<hmap_expected_t<VT>(UT const&)> (from user type to inner)
// //
template <typename VT, typename... FTs> template <typename VT, typename... FTs>
requires(sizeof...(FTs) > 1) requires(sizeof...(FTs) > 1)
@@ -669,14 +685,14 @@ public:
_getter<u_t>[this].emplace( _getter<u_t>[this].emplace(
kk, kk,
[kk, from_cnv_func_arg = [kk, from_cnv_func_arg = std::forward<decltype(from_cnv_func)>(from_cnv_func)](
std::forward<decltype(from_cnv_func)>(from_cnv_func)](const hmap* obj) mutable -> u_t { const hmap* obj) mutable -> hmap_expected_t<u_t> {
return std::forward<decltype(from_cnv_func_arg)>(from_cnv_func_arg)(_values<v_t>[obj][kk]); return std::forward<decltype(from_cnv_func_arg)>(from_cnv_func_arg)(_values<v_t>[obj][kk]);
}); });
_setter<u_t>[this].emplace(kk, _setter<u_t>[this].emplace(kk,
[kk, to_cnv_func_arg = std::forward<decltype(to_cnv_func)>(to_cnv_func)]( [kk, to_cnv_func_arg = std::forward<decltype(to_cnv_func)>(to_cnv_func)](
const u_t& v, const hmap* obj) mutable -> hmap::error_t { const u_t& v, const hmap* obj) mutable -> hmap_error_t {
auto val = std::forward<decltype(to_cnv_func_arg)>(to_cnv_func_arg)(v); auto val = std::forward<decltype(to_cnv_func_arg)>(to_cnv_func_arg)(v);
if (val) { if (val) {
_values<v_t>[obj][kk] = val.value(); _values<v_t>[obj][kk] = val.value();
@@ -708,6 +724,9 @@ public:
return ok; return ok;
} }
//
// overloaded method with trivial conversion functions constructed from
// element types of the input std::tuple
template <typename VT, typename... Ts> template <typename VT, typename... Ts>
requires(sizeof...(Ts) > 0) requires(sizeof...(Ts) > 0)
auto push(KeyT const& key, VT&& value, std::tuple<Ts...>) auto push(KeyT const& key, VT&& value, std::tuple<Ts...>)
@@ -735,7 +754,7 @@ public:
} }
template <typename UT> template <typename UT>
hmap::error_t set(KeyT const& key, UT&& value) hmap_error_t set(KeyT const& key, UT&& value)
{ {
using u_t = std::decay_t<UT>; using u_t = std::decay_t<UT>;