...
This commit is contained in:
@@ -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})
|
||||||
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