This commit is contained in:
2026-09-02 18:52:56 +03:00
parent d15928eb68
commit a49e7b5d5f
2 changed files with 98 additions and 65 deletions

View File

@@ -162,5 +162,66 @@ int main()
} }
} }
std::println("\n\n\n\n");
snplib::hmap<std::string> hm;
std::string k1{"k_int"}, k2{"k_str"}, k3("k_dbl");
int i1 = 10;
double f1 = 7.7;
std::string s1 = "test-str";
std::print("push element with key '{}' and value {}\t...", k1, i1);
ok = hm.push(k1, i1, std::tuple<long, double, float, long long>{});
if (!ok) {
std::println("cannot insert the value {}", i1);
} else {
std::println("OK");
}
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());
// }
});
if (!ok) {
std::println("cannot insert the value {}", s1);
} else {
std::println("OK");
}
std::print("push element with key '{}' and value {}\t...", k3, f1);
ok = hm.push(k3, f1, std::tuple<long, int, float, long long>{});
if (!ok) {
std::println("cannot insert the value {}", f1);
} else {
std::println("OK");
}
std::println("\n");
std::print("get '{}'-element as double: ", k1);
auto f2 = hm.get<double>(k1);
if (f2) {
std::println("{}", f2.value());
} else {
std::println("FAIL");
}
return 0; return 0;
} }

View File

@@ -454,64 +454,34 @@ protected:
inline static std::vector<std::function<bool(KeyT const&, const hmap*)>> _containsFunc{}; inline static std::vector<std::function<bool(KeyT const&, const hmap*)>> _containsFunc{};
// trivial conversional functors // trivial conversional functions
struct trivial_conv_from_t {
hmap const* obj;
KeyT const& key;
template <typename VT, typename UT>
hmap_expected_t<UT> operator()(hmap_expected_t<VT> const&)
{
auto v = obj->get<VT>(key);
if (v) {
return static_cast<UT>(v.value());
}
return hmap_error_e::ERROR_USER_CONV;
}
};
struct trivial_conv_to_t {
hmap const* obj;
KeyT const& key;
template <typename VT, typename UT>
hmap_expected_t<VT> operator()(hmap_expected_t<UT> const& uval)
{
if (uval) {
auto err = obj->set(key, uval.value());
if (err) {
return std::unexpected(err);
}
// return
}
return hmap_error_e::ERROR_USER_CONV;
}
};
template <typename VT, typename UT> template <typename VT, typename UT>
requires requires(VT v, UT u) { v = u; } requires requires(VT v, UT u) { v = u; }
inline static std::function<hmap_expected_t<UT>(hmap_expected_t<VT> const&)> trivial_conv_from = inline static std::function<hmap_expected_t<UT>(VT const&)> trivial_conv_from =
[](hmap_expected_t<VT> const& val) -> hmap_expected_t<UT> { [](VT const& val) -> hmap_expected_t<UT> {
if (val) { // inline static std::function<hmap_expected_t<UT>(hmap_expected_t<VT> const&)> trivial_conv_from =
return static_cast<UT>(val.value()); // [](hmap_expected_t<VT> const& val) -> hmap_expected_t<UT> {
} else { return static_cast<UT>(val);
return val.error(); // if (val) {
} // return static_cast<UT>(val.value());
// } else {
// return val.error();
// }
}; };
template <typename VT, typename UT> template <typename VT, typename UT>
requires requires(VT v, UT u) { u = v; } requires requires(VT v, UT u) { u = v; }
inline static std::function<hmap_expected_t<VT>(hmap_expected_t<UT> const&)> trivial_conv_to = inline static std::function<hmap_expected_t<VT>(UT const&)> trivial_conv_to =
[](hmap_expected_t<UT> const& uval) -> hmap_expected_t<VT> { [](UT const& uval) -> hmap_expected_t<VT> {
if (uval) { // inline static std::function<hmap_expected_t<VT>(hmap_expected_t<UT> const&)> trivial_conv_to =
return static_cast<VT>(uval.value()); // [](hmap_expected_t<UT> const& uval) -> hmap_expected_t<VT> {
} else { return static_cast<VT>(uval);
return uval.error(); // if (uval) {
} // return static_cast<VT>(uval.value());
// } else {
// return uval.error();
// }
}; };
public: public:
@@ -692,7 +662,7 @@ public:
} }
auto add_cnv_func = [this](KeyT const& kk, auto&& from_cnv_func, auto&& to_cnv_func) { auto add_cnv_func = [this](KeyT const& kk, auto&& from_cnv_func, auto&& to_cnv_func) {
using u_t = std::invoke_result_t<decltype(from_cnv_func), v_t>; using u_t = std::invoke_result_t<decltype(from_cnv_func), v_t>::value_type;
// user type must differ from inserted one // user type must differ from inserted one
static_assert(!std::same_as<v_t, u_t>, "INVALID CONVERSIONAL 'FROM-FUNCTION' SIGNATURE!"); static_assert(!std::same_as<v_t, u_t>, "INVALID CONVERSIONAL 'FROM-FUNCTION' SIGNATURE!");
@@ -704,16 +674,17 @@ public:
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, [kk, to_cnv_func_arg = std::forward<decltype(to_cnv_func)>(to_cnv_func)]( _setter<u_t>[this].emplace(kk,
const u_t& v, const hmap* obj) mutable { [kk, to_cnv_func_arg = std::forward<decltype(to_cnv_func)>(to_cnv_func)](
auto val = std::forward<decltype(to_cnv_func_arg)>(to_cnv_func_arg)(v); const u_t& v, const hmap* obj) mutable -> hmap::error_t {
if (val) { auto val = std::forward<decltype(to_cnv_func_arg)>(to_cnv_func_arg)(v);
_values<v_t>[obj][kk] = val; if (val) {
return hmap_error_e::ERROR_OK; _values<v_t>[obj][kk] = val.value();
} else { return hmap_error_e::ERROR_OK;
return val.error(); } else {
} return val.error();
}); }
});
_clearFunc.emplace_back([](hmap* obj) { _clearFunc.emplace_back([](hmap* obj) {
_getter<u_t>[obj].clear(); _getter<u_t>[obj].clear();
@@ -741,14 +712,15 @@ public:
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...>)
{ {
using v_t = std::decay_t<VT>;
using tp_t = std::tuple<Ts...>; using tp_t = std::tuple<Ts...>;
return [&key, val = std::forward<VT>(value), this]<size_t... Is>(std::index_sequence<Is...>) { return [&key, val = std::forward<VT>(value), this]<size_t... Is>(std::index_sequence<Is...>) mutable {
return std::apply([this](auto&&... args) { return push(std::forward<decltype(args)>(args)...); }, return std::apply([this](auto&&... args) { return push(std::forward<decltype(args)>(args)...); },
std::tuple_cat(std::forward_as_tuple(key, std::forward<VT>(val)), std::tuple_cat(std::forward_as_tuple(key, std::forward<VT>(val)),
std::tuple_cat(std::forward_as_tuple( std::tuple_cat(std::forward_as_tuple(
hmap::trivial_conv_from<VT, std::tuple_element_t<Is, tp_t>>, hmap::trivial_conv_from<v_t, std::tuple_element_t<Is, tp_t>>,
hmap::trivial_conv_to<VT, std::tuple_element_t<Is, tp_t>>)...))); hmap::trivial_conv_to<v_t, std::tuple_element_t<Is, tp_t>>)...)));
}(std::make_index_sequence<sizeof...(Ts)>{}); }(std::make_index_sequence<sizeof...(Ts)>{});
} }