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

View File

@@ -116,6 +116,7 @@ public:
return does_contain;
}
void clear()
{
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>
class hmap
{
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>
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>
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{};
@@ -555,6 +558,16 @@ public:
return does_contain;
}
bool erase(KeyT const& key)
{
bool ok = false;
for (auto& func : _eraseFunc) {
ok |= func(key, this);
}
return ok;
}
void clear()
{
for (auto& func : _clearFunc) {
@@ -574,6 +587,7 @@ public:
return N;
}
template <typename VT>
bool push(KeyT const& key, VT&& value)
{
@@ -632,7 +646,9 @@ public:
// NOTE: do not use here iterator since after insertion
// 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) {
_values<v_t>[obj][key] = v;
return hmap_error_e::ERROR_OK;
@@ -643,8 +659,8 @@ public:
// FTs - conversional functions:
// convert-from: std::function<hmap_expected_t<UT>(hmap_expected_t<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-from: std::function<hmap_expected_t<UT>(VT const&)> (from inner type to user)
// convert-to: std::function<hmap_expected_t<VT>(UT const&)> (from user type to inner)
//
template <typename VT, typename... FTs>
requires(sizeof...(FTs) > 1)
@@ -669,14 +685,14 @@ public:
_getter<u_t>[this].emplace(
kk,
[kk, from_cnv_func_arg =
std::forward<decltype(from_cnv_func)>(from_cnv_func)](const hmap* obj) mutable -> u_t {
[kk, from_cnv_func_arg = std::forward<decltype(from_cnv_func)>(from_cnv_func)](
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]);
});
_setter<u_t>[this].emplace(kk,
[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);
if (val) {
_values<v_t>[obj][kk] = val.value();
@@ -708,6 +724,9 @@ public:
return ok;
}
//
// overloaded method with trivial conversion functions constructed from
// element types of the input std::tuple
template <typename VT, typename... Ts>
requires(sizeof...(Ts) > 0)
auto push(KeyT const& key, VT&& value, std::tuple<Ts...>)
@@ -735,7 +754,7 @@ public:
}
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>;