This commit is contained in:
2026-06-17 13:09:06 +03:00
parent 60a261f18c
commit 6cb54740b4
3 changed files with 112 additions and 74 deletions

View File

@@ -3,11 +3,12 @@ project(snipplib VERSION 0.1.0 LANGUAGES CXX)
option(BUILD_EXAMPLES "Build examples" ON) option(BUILD_EXAMPLES "Build examples" ON)
set(LIB_HEADERS
set(LIB_HEADERS include/snipplib/concepts/snplib_concepts.h include/snipplib/concepts/snplib_concepts.h
include/snipplib/utils/snplib_hash.h include/snipplib/utils/snplib_hash.h
include/snipplib/utils/snplib_utils.h include/snipplib/utils/snplib_utils.h
include/snipplib/hmap/snplib_hmap.h) include/snipplib/containers/snplib_hmap.h
)
add_library(${PROJECT_NAME} INTERFACE ${LIB_HEADERS}) add_library(${PROJECT_NAME} INTERFACE ${LIB_HEADERS})
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_23) target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_23)
@@ -18,7 +19,6 @@ target_include_directories(
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>" "$<INSTALL_INTERFACE:include/${PROJECT_NAME}>"
) )
set(EXAM_STRING str_exam) set(EXAM_STRING str_exam)
add_executable(${EXAM_STRING} examples/str_exam.cpp) add_executable(${EXAM_STRING} examples/str_exam.cpp)
target_link_libraries(${EXAM_STRING} ${PROJECT_NAME}) target_link_libraries(${EXAM_STRING} ${PROJECT_NAME})

View File

@@ -0,0 +1,105 @@
#pragma once
#include <expected>
#include <functional>
#include <unordered_map>
#include <vector>
#include "../concepts/snplib_concepts.h"
#include "../utils/snplib_hash.h"
namespace snplib
{
template <snplib_hashable_c KeyT>
class HeterogenMap
{
protected:
// actuall map key type
typedef std::pair<const HeterogenMap*, KeyT> key_t;
struct KeyHash {
static size_t operator()(key_t key)
{
size_t hash = 0;
snplib_hash_combine(hash, key.first, key.second);
return hash;
}
};
template <typename VT>
inline static std::unordered_map<key_t, VT, KeyHash> _umap{};
template <typename UT>
inline static std::unordered_map<key_t, std::function<UT()>, KeyHash> _getter{};
template <typename UT>
inline static std::unordered_map<key_t, std::function<void(UT const&)>, KeyHash> _setter{};
std::vector<std::function<void()>> _clearFunc{};
public:
enum Error { ERROR_OK, ERROR_NO_ELEM };
HeterogenMap() = default;
~HeterogenMap()
{
for (auto& func : _clearFunc) {
func();
}
}
template <typename VT>
size_t push(KeyT const& key, VT&& value)
{
auto kk = std::make_pair(this, key);
auto it = _umap<std::decay_t<VT>>.emplace(kk, std::forward<VT>(value));
if (it.second) {
_getter<std::decay_t<VT>>.emplace(kk, [it = it.first]() { return it->second; });
_clearFunc.emplace_back([it = it.first]() { _umap<std::decay_t<VT>>.erase(it); });
} // here the element already exists (just update its value)
return _clearFunc.size();
}
template <typename VT, typename... Ts>
size_t push(KeyT const& key, VT&& value, std::tuple<Ts...>)
{
auto kk = std::make_pair(this, key);
auto add_cnv_func = [kk]<size_t I>() {
using u_t = std::tuple_element_t<I, std::tuple<Ts...>>;
if constexpr (!std::same_as<VT, u_t>) {
// _umap<u_t>.emplace(kk, )
}
};
[kk]<size_t... Is>(std::index_sequence<Is...>) {}(std::make_index_sequence<sizeof...(Ts)>());
return push(key, std::forward<VT>(value));
}
template <typename VT, typename... CtorArgTs>
size_t emplace(KeyT const& key, CtorArgTs&&... args)
{
return push(key, VT(std::forward<CtorArgTs>(args)...));
}
template <typename VT>
std::expected<VT, Error> get(KeyT const& key) const
{
if (auto it = _umap<VT>.find(std::make_pair(this, key)); it != _umap<VT>.end()) {
return it->second;
}
return std::unexpected(Error::ERROR_NO_ELEM);
}
};
} // end of namespace snplib

View File

@@ -1,67 +0,0 @@
#pragma once
#include "../concepts/snplib_concepts.h"
#include "../utils/snplib_hash.h"
namespace snplib {
template<snplib_hashable_c KeyT>
class HeterogenMap {
protected:
// actuall map key type
typedef std::pair<const HeterogenMap*, KeyT> key_t;
struct KeyHash {
static size_t operator()(key_t key) {
size_t hash = 0;
snplib_hash_combine(hash, key.first, , key.second);
return hash;
}
}
template <typename VT>
inline static std::unordered_map<key_t, VT, KeyHash> _umap{};
std::vector<std::function<void()>> _clearFunc{};
public:
enum Error : {ERROR_OK, ERROR_NO_ELEM};
HeterogenMap() = default;
~HeterogenMap() {
for (auto &func: _clearFunc) {
func();
}
}
template<typename VT>
size_t push(KeyT const& key, VT&& value) {
auto it = _umap<std::decay_t<VT>>.emplace(std::make_pair(this, key), std::forward<VT>(value));
if (it.second){
_clearFunc.empace_back([it=it.first]() { _umap<std::decay_t<VT>>.erase(it); });
} // here the element already exists (just update its value)
return _clearFunc.size();
}
template<typename VT, typename ...CtorArgTs>
size_t emplace(KeyT const&, CtorArgTs&& ...args) {
return push(key, VT(std::forward<CtorArgTs>(args)...));
}
template<typename VT>
std::expected<VT, Error> get(KeyT const& key) const {
if (auto it = _umap<VT>.find(std::make_pair(this, key)); it != _umap<VT>.end()) {
return it->second;
}
return std::unexpected(Error::ERROR_NO_ELEM);
}
};
} // end of namespace snplib