...
This commit is contained in:
@@ -3,11 +3,12 @@ project(snipplib VERSION 0.1.0 LANGUAGES CXX)
|
||||
|
||||
option(BUILD_EXAMPLES "Build examples" ON)
|
||||
|
||||
|
||||
set(LIB_HEADERS include/snipplib/concepts/snplib_concepts.h
|
||||
include/snipplib/utils/snplib_hash.h
|
||||
include/snipplib/utils/snplib_utils.h
|
||||
include/snipplib/hmap/snplib_hmap.h)
|
||||
set(LIB_HEADERS
|
||||
include/snipplib/concepts/snplib_concepts.h
|
||||
include/snipplib/utils/snplib_hash.h
|
||||
include/snipplib/utils/snplib_utils.h
|
||||
include/snipplib/containers/snplib_hmap.h
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} INTERFACE ${LIB_HEADERS})
|
||||
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_23)
|
||||
@@ -18,7 +19,6 @@ target_include_directories(
|
||||
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>"
|
||||
)
|
||||
|
||||
|
||||
set(EXAM_STRING str_exam)
|
||||
add_executable(${EXAM_STRING} examples/str_exam.cpp)
|
||||
target_link_libraries(${EXAM_STRING} ${PROJECT_NAME})
|
||||
105
include/snipplib/containers/snplib_hmap.h
Normal file
105
include/snipplib/containers/snplib_hmap.h
Normal 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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user