...
This commit is contained in:
@@ -32,6 +32,10 @@ if(BUILD_EXAMPLES)
|
||||
set(EXAM_HMAP hmap_example)
|
||||
add_executable(${EXAM_HMAP} examples/hmap_example.cpp)
|
||||
target_link_libraries(${EXAM_HMAP} ${PROJECT_NAME})
|
||||
|
||||
set(EXAM_HVEC hvec_example)
|
||||
add_executable(${EXAM_HVEC} examples/hvec_example.cpp)
|
||||
target_link_libraries(${EXAM_HVEC} ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
47
examples/hvec_example.cpp
Normal file
47
examples/hvec_example.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <print>
|
||||
#include <vector>
|
||||
|
||||
#include <snipplib/containers/snplib_hvec.h>
|
||||
|
||||
using namespace snplib;
|
||||
|
||||
struct visitor {
|
||||
using types = std::tuple<std::string, unsigned long>;
|
||||
|
||||
void operator()(auto& v)
|
||||
{
|
||||
using val_t = std::decay_t<decltype(v)>;
|
||||
|
||||
if constexpr (std::ranges::input_range<val_t>) {
|
||||
std::println("range val = {}", v);
|
||||
} else {
|
||||
std::println("val = {}", v);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
HeterogenVec vec;
|
||||
|
||||
vec.push(1.1);
|
||||
vec.push(std::string{"AAA"});
|
||||
vec.push(100UL);
|
||||
vec.push(200UL);
|
||||
vec.push(300UL);
|
||||
|
||||
std::vector<char> v{'q', 'w', 'e'};
|
||||
|
||||
vec.emplace<std::string>(std::from_range_t{}, v);
|
||||
|
||||
vec.visit(visitor{});
|
||||
vec.visitRange(visitor{});
|
||||
|
||||
vec.clear();
|
||||
|
||||
std::println("\n\tafter clear() ...");
|
||||
vec.visit(visitor{});
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -15,11 +15,20 @@ namespace details
|
||||
template <typename OT, typename TT, size_t... Is>
|
||||
concept snplib_all_func_oper_c = requires(OT obj) { (obj(std::declval<std::tuple_element_t<Is, TT>&>()), ...); };
|
||||
|
||||
template <typename OT, typename TT, size_t... Is>
|
||||
concept snplib_all_func_oper_range_c =
|
||||
requires(OT obj) { (obj(std::declval<std::vector<std::tuple_element_t<Is, TT>>&>()), ...); };
|
||||
|
||||
template <typename OT, typename TT>
|
||||
struct snplib_check_all_func_oper_t {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template <typename OT, typename TT>
|
||||
struct snplib_check_all_func_oper_range_t {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template <typename OT, typename TT>
|
||||
requires requires { typename std::tuple_size<TT>::type; }
|
||||
struct snplib_check_all_func_oper_t<OT, TT> {
|
||||
@@ -28,10 +37,21 @@ struct snplib_check_all_func_oper_t<OT, TT> {
|
||||
}(std::make_index_sequence<std::tuple_size<TT>::value>{});
|
||||
};
|
||||
|
||||
template <typename OT, typename TT>
|
||||
requires requires { typename std::tuple_size<TT>::type; }
|
||||
struct snplib_check_all_func_oper_range_t<OT, TT> {
|
||||
static constexpr bool value = []<std::size_t... Is>(std::index_sequence<Is...>) {
|
||||
return snplib_all_func_oper_range_c<OT, TT, Is...>;
|
||||
}(std::make_index_sequence<std::tuple_size<TT>::value>{});
|
||||
};
|
||||
|
||||
|
||||
template <typename OT, typename TT>
|
||||
static constexpr bool snplib_check_all_func_oper_v = snplib_check_all_func_oper_t<OT, TT>::value;
|
||||
|
||||
template <typename OT, typename TT>
|
||||
static constexpr bool snplib_check_all_func_oper_range_v = snplib_check_all_func_oper_range_t<OT, TT>::value;
|
||||
|
||||
} // namespace details
|
||||
|
||||
|
||||
@@ -42,6 +62,13 @@ concept snplib_hvec_visitor_c = requires {
|
||||
requires details::snplib_check_all_func_oper_v<T, typename T::types>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept snplib_hvec_range_visitor_c = requires {
|
||||
requires snplib_tuple_c<typename T::types>;
|
||||
|
||||
requires details::snplib_check_all_func_oper_range_v<T, typename T::types>;
|
||||
};
|
||||
|
||||
|
||||
class HeterogenVec
|
||||
{
|
||||
@@ -128,7 +155,7 @@ public:
|
||||
}
|
||||
});
|
||||
|
||||
_copyFunc.emplace_back([](HeterogenVec* from, HeterogenVec* to) {
|
||||
_copyFunc.emplace_back([](const HeterogenVec* from, HeterogenVec* to) {
|
||||
if (_values<v_t>.contains(from)) {
|
||||
_values<v_t>[to] = _values<v_t>[from];
|
||||
}
|
||||
@@ -139,16 +166,33 @@ public:
|
||||
_values<v_t>[this].push_back(std::forward<VT>(value));
|
||||
}
|
||||
|
||||
template <typename VT, typename... CtorArgTs>
|
||||
void emplace(CtorArgTs&&... args)
|
||||
{
|
||||
push(VT(std::forward<CtorArgTs>(args)...));
|
||||
}
|
||||
|
||||
// per element visiting
|
||||
template <snplib_hvec_visitor_c VT>
|
||||
void visit(VT&& visitor)
|
||||
{
|
||||
auto invoke_per_type = [&visitor, this]<typename T>() {
|
||||
auto invoke_per_elem = [&visitor, this]<typename T>() {
|
||||
for (auto& elem : _values<T>[this]) {
|
||||
visitor(elem);
|
||||
}
|
||||
};
|
||||
|
||||
[&invoke_per_elem]<size_t... Is>(std::index_sequence<Is...>) {
|
||||
(invoke_per_elem.template operator()<std::tuple_element_t<Is, typename VT::types>>(), ...);
|
||||
}(std::make_index_sequence<std::tuple_size_v<typename VT::types>>{});
|
||||
}
|
||||
|
||||
// per range of type visiting
|
||||
template <snplib_hvec_visitor_c VT>
|
||||
void visitRange(VT&& visitor)
|
||||
{
|
||||
auto invoke_per_type = [&visitor, this]<typename T>() { visitor(_values<T>[this]); };
|
||||
|
||||
[&invoke_per_type]<size_t... Is>(std::index_sequence<Is...>) {
|
||||
(invoke_per_type.template operator()<std::tuple_element_t<Is, typename VT::types>>(), ...);
|
||||
}(std::make_index_sequence<std::tuple_size_v<typename VT::types>>{});
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include "../concepts/snplib_concepts.h"
|
||||
#include "../containers/snplib_hvec.h"
|
||||
|
||||
namespace snplib
|
||||
{
|
||||
@@ -44,9 +46,9 @@ concept snplib_net_session_c = std::derived_from<T, std::enable_shared_from_this
|
||||
|
||||
snplib_net_connection_c<typename T::connection_t>;
|
||||
|
||||
{ t.start(std::declval<typename T::connection_t>()) } -> snplib_async_retval_c;
|
||||
{ t.startSession(std::declval<typename T::connection_t>()) } -> snplib_async_retval_c;
|
||||
|
||||
t.stop();
|
||||
t.stopSession();
|
||||
};
|
||||
|
||||
|
||||
@@ -84,7 +86,7 @@ protected:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept snplib_netserver_c = requires(T t) {
|
||||
concept snplib_netserver_c = std::derived_from<T, snplib_netserver_iface_t> && requires(T t) {
|
||||
// static constexpr member
|
||||
std::formattable<decltype(T::id), char>;
|
||||
[]() { [[maybe_unused]] static constexpr auto val = T::id; }();
|
||||
@@ -97,4 +99,50 @@ concept snplib_netserver_c = requires(T t) {
|
||||
|
||||
{ t.disconnectClients() } -> snplib_error_c;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* SINGLE-PROTO*/
|
||||
|
||||
template <snplib_net_listener_c ListenerT>
|
||||
class snplib_generic_netserver_t
|
||||
{
|
||||
public:
|
||||
typedef std::error_code error_t;
|
||||
|
||||
using session_t = typename ListenerT::session_t;
|
||||
|
||||
snplib_generic_netserver_t(std::unique_ptr<ListenerT> listener) : _listener(std::move(listener)) {}
|
||||
|
||||
error_t start()
|
||||
{
|
||||
auto err = _listener->start();
|
||||
if (err) {
|
||||
return snplib_deduced_error(err, std::make_error_code(std::errc::io_error));
|
||||
}
|
||||
|
||||
startListen();
|
||||
}
|
||||
|
||||
error_t stop()
|
||||
{
|
||||
_listener->stop();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<ListenerT> _listener{};
|
||||
std::set<std::weak_ptr<session_t>> _sessions{};
|
||||
|
||||
void startListen()
|
||||
{
|
||||
auto sess = co_await _listener->accept();
|
||||
if (sess) {
|
||||
_sessions.insert(sess);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace snplib
|
||||
Reference in New Issue
Block a user