diff --git a/include/snipplib/concepts/snplib_concepts.h b/include/snipplib/concepts/snplib_concepts.h index 85caeba..fde448d 100644 --- a/include/snipplib/concepts/snplib_concepts.h +++ b/include/snipplib/concepts/snplib_concepts.h @@ -4,7 +4,6 @@ #include #include #include -#include #include namespace snplib @@ -100,6 +99,12 @@ static constexpr bool snplib_check_indices_v = snplib_check_indices_t::value; template concept snplib_tuple_like_c = details::snplib_check_indices_v>; +// strictly std::tuple +template +concept snplib_tuple_c = requires { + [](std::type_identity>) {}(std::type_identity>{}); +}; + /* fixed-size and non-resizable ranges */ diff --git a/include/snipplib/containers/snplib_hvec.h b/include/snipplib/containers/snplib_hvec.h index b134c28..8211559 100644 --- a/include/snipplib/containers/snplib_hvec.h +++ b/include/snipplib/containers/snplib_hvec.h @@ -3,11 +3,46 @@ #include #include +#include "snipplib/concepts/snplib_concepts.h" namespace snplib { +namespace details +{ + +template +concept snplib_all_func_oper_c = requires(OT obj) { (obj(std::declval&>()), ...); }; + +template +struct snplib_check_all_func_oper_t { + static constexpr bool value = false; +}; + +template + requires requires { typename std::tuple_size::type; } +struct snplib_check_all_func_oper_t { + static constexpr bool value = [](std::index_sequence) { + return snplib_all_func_oper_c; + }(std::make_index_sequence::value>{}); +}; + + +template +static constexpr bool snplib_check_all_func_oper_v = snplib_check_all_func_oper_t::value; + +} // namespace details + + +template +concept snplib_hvec_visitor_c = requires { + requires snplib_tuple_c; + + requires details::snplib_check_all_func_oper_v; +}; + + class HeterogenVec { protected: @@ -16,7 +51,58 @@ protected: inline static std::vector> _clearFunc{}; + + // move: void(from_obj_ptr, to_obj_ptr) + inline static std::vector> _moveFunc{}; + // copy: void(const from_obj_ptr, to_obj_ptr) + inline static std::vector> _copyFunc{}; + + public: + HeterogenVec() = default; + + ~HeterogenVec() = default; + + HeterogenVec(const HeterogenVec& other) + { + if (&other != this) { + for (auto& func : _copyFunc) { + func(&other, this); + } + } + } + + HeterogenVec(HeterogenVec&& other) + { + if (&other != this) { + for (auto& func : _moveFunc) { + func(&other, this); + } + } + } + + HeterogenVec& operator=(const HeterogenVec& other) + { + if (&other != this) { + for (auto& func : _copyFunc) { + func(&other, this); + } + } + + return *this; + } + + HeterogenVec& operator=(HeterogenVec&& other) + { + if (&other != this) { + for (auto& func : _moveFunc) { + func(&other, this); + } + } + + return *this; + } + void clear() { for (auto& func : _clearFunc) { @@ -26,16 +112,47 @@ public: template - void insert(VT&& value) + void push(VT&& value) { using v_t = std::decay_t; if (_values.empty()) { - _clearFunc.emplace_back([](const HeterogenVec* obj) { _values[obj].clear(); }); + _clearFunc.emplace_back([](const HeterogenVec* obj) { + // _values[obj].clear(); + _values.erase(obj); + }); + + _moveFunc.emplace_back([](HeterogenVec* from, HeterogenVec* to) { + if (_values.contains(from)) { + _values[to] = std::move(_values[from]); + } + }); + + _copyFunc.emplace_back([](HeterogenVec* from, HeterogenVec* to) { + if (_values.contains(from)) { + _values[to] = _values[from]; + } + }); } + _values[this].push_back(std::forward(value)); } + + + template + void visit(VT&& visitor) + { + auto invoke_per_type = [&visitor, this]() { + for (auto& elem : _values[this]) { + visitor(elem); + } + }; + + [&invoke_per_type](std::index_sequence) { + (invoke_per_type.template operator()>(), ...); + }(std::make_index_sequence>{}); + } }; } // end of namespace snplib \ No newline at end of file