From 117765ddd7595325f07a029eaffa65d7686d30fb Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 15 Jul 2026 18:33:42 +0300 Subject: [PATCH] add the pushWithCnv method to the HeterogenMap class --- examples/hmap_example.cpp | 26 ++++++++++ include/snipplib/containers/snplib_hmap.h | 58 +++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/examples/hmap_example.cpp b/examples/hmap_example.cpp index 397e11b..fd220b2 100644 --- a/examples/hmap_example.cpp +++ b/examples/hmap_example.cpp @@ -128,5 +128,31 @@ int main() std::println("hmap_move.size() = {}", hmap_move.size()); std::println("hmap_copy.size() = {}", hmap_copy.size()); + std::println("\n{:*^80}", " hmap with custom conv funcs "); + + hmap.pushWithCnv( + "str_cst", std::string{"ABC"}, [&s](std::string const& v) { return s.c_str(); }, + [&s](const char* p) { + s = p; + return s; + }); + + auto ptr = hmap.get("str_cst"); + if (ptr) { + std::println("ptr = {}", ptr.value()); + } else { + std::println("cannot get PTR"); + } + + // std::string pp = "EEEE"; + // auto err = hmap.set("str_cst", pp.c_str()); + const char* pp = "EEEE"; + auto err = hmap.set("str_cst", pp); + if (err) { + std::println("cannot set 'str_cst'"); + } else { + std::println("s = {}", s); + } + return 0; } \ No newline at end of file diff --git a/include/snipplib/containers/snplib_hmap.h b/include/snipplib/containers/snplib_hmap.h index 0f8cb71..fe54be8 100644 --- a/include/snipplib/containers/snplib_hmap.h +++ b/include/snipplib/containers/snplib_hmap.h @@ -247,6 +247,64 @@ public: return ok; } + // FTs - conversional functions: + // convert-from: std::function (from inner type to user) + // convert-to: std::function (from user type to inner) + // + template + requires(sizeof...(FTs) > 1) + auto pushWithCnv(KeyT const& key, VT&& value, FTs&&... cnv_funcs) + { + static_assert(sizeof...(FTs) % 2 == 0, + "IT MUST BE EVEN NUMBER OF THE INPUT CALLABLES!"); // must be even number ("convert-from" and + // "convert-to")! + + using v_t = std::decay_t; + + bool ok = push(key, std::forward(value)); + if (!ok) { // element with given 'key' is already in the map + return ok; + } + + auto add_cnv_func = [this](KeyT const& kk, auto&& from_cnv_func, auto&& to_cnv_func) { + using u_t = std::invoke_result_t; + + // user type must differ from inserted one + static_assert(!std::same_as, "INVALID CONVERSIONAL 'FROM-FUNCTION' SIGNATURE!"); + + _getter[this].emplace( + kk, + [kk, from_cnv_func_arg = + std::forward(from_cnv_func)](const HeterogenMap* obj) mutable -> u_t { + return std::forward(from_cnv_func_arg)(_values[obj][kk]); + }); + + _setter[this].emplace(kk, [kk, to_cnv_func_arg = std::forward(to_cnv_func)]( + const u_t& v, const HeterogenMap* obj) mutable { + _values[obj][kk] = std::forward(to_cnv_func_arg)(v); + }); + + _clearFunc.emplace_back([](HeterogenMap* obj) { + _getter[obj].clear(); + _setter[obj].clear(); + }); + + _eraseFunc.emplace_back([](KeyT const& k, const HeterogenMap* obj) { + _getter[obj].erase(k); + _setter[obj].erase(k); + + return true; + }); + }; + + [&add_cnv_func, key, + tp = std::forward_as_tuple(std::forward(cnv_funcs)...)](std::index_sequence) { + (add_cnv_func(key, std::get(tp), std::get(tp)), ...); + }(std::make_index_sequence()); + + return ok; + } + template bool emplace(KeyT const& key, CtorArgTs&&... args) {