From 7fa30dbfac715d69bf9c318525b8e701a05ff89f Mon Sep 17 00:00:00 2001 From: "Hochsteger, Matthias" Date: Tue, 29 Aug 2023 18:27:39 +0200 Subject: [PATCH] Archive classes with non default ctor --- libsrc/core/archive.hpp | 61 +++++++++++++++++++++++++++++++- libsrc/core/register_archive.hpp | 14 ++++---- tests/catch/archive.cpp | 10 +++--- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 2aad63e8..604a3f26 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -14,6 +14,7 @@ #include // for string #include // for declval, enable_if_t, false_type, is_co... #include // for std::byte +#include // for set #include // for type_info #include // for move, swap, pair #include // for vector @@ -33,6 +34,13 @@ namespace pybind11 namespace ngcore { + template + struct Shallow { + T val; + Shallow() = default; + Shallow(T aval) : val(aval) { ; } + operator T&() { return val; } + }; #ifdef NETGEN_PYTHON pybind11::object CastAnyToPy(const std::any& a); @@ -101,6 +109,31 @@ namespace ngcore NGCORE_API static constexpr bool value = type::value; }; + template + struct has_GetCArgs + { + template static std::true_type check( decltype( sizeof(&C::GetCArgs )) ) { return std::true_type(); } + template static std::false_type check(...) { return std::false_type(); } + typedef decltype( check(sizeof(char)) ) type; + static constexpr type value = type(); + }; + template + constexpr bool has_GetCArgs_v = has_GetCArgs::value; + + template>::type* = nullptr> + std::tuple<> GetCArgs(T&val) { return {}; } + + template>::type* = nullptr> + auto GetCArgs(T&val) { + return val.GetCArgs(); + } + + template + using TCargs = decltype(GetCArgs(*static_cast(nullptr))); + + struct ClassArchiveInfo { // create new object of this type and return a void* pointer that is points to the location @@ -336,6 +369,26 @@ namespace ngcore } return (*this); } + template + Archive& operator&(std::set &s) + { + auto size = s.size(); + (*this) & size; + if(Output()) + for(const auto & val : s) + (*this) << val; + else + { + for(size_t i=0; i>> @@ -420,6 +473,12 @@ namespace ngcore + template + Archive& operator & (ngcore::Shallow& shallow) + { + this->Shallow(shallow.val); + return *this; + } // Archive shared_ptrs ================================================= @@ -663,7 +722,7 @@ namespace ngcore void SetParallel (bool _parallel) { parallel = _parallel; } private: - template + template friend class RegisterClassForArchive; #ifdef NETGEN_PYTHON diff --git a/libsrc/core/register_archive.hpp b/libsrc/core/register_archive.hpp index f5f673ed..80f46fc0 100644 --- a/libsrc/core/register_archive.hpp +++ b/libsrc/core/register_archive.hpp @@ -37,7 +37,7 @@ namespace ngcore { template struct has_shared_from_this { - template static std::true_type check( decltype( sizeof(&C::shared_from_this() )) ) { return std::true_type(); } + template static std::true_type check( decltype( sizeof(&C::shared_from_this )) ) { return std::true_type(); } template static std::false_type check(...) { return std::false_type(); } typedef decltype( check(sizeof(char)) ) type; static constexpr type value = type(); @@ -45,14 +45,11 @@ namespace ngcore { #endif // NETGEN_PYTHON - template, typename CArgs=std::tuple<>> + template> class RegisterClassForArchive { public: - std::function get_cargs; - RegisterClassForArchive(std::function _get_cargs = - [](T&) -> std::tuple<> { return std::tuple<>{}; }) : - get_cargs(_get_cargs) + RegisterClassForArchive() { static_assert(std::is_base_of::value || detail::is_base_of_tuple, @@ -60,7 +57,7 @@ namespace ngcore { detail::ClassArchiveInfo info {}; info.creator = [](const std::type_info& ti, Archive& ar) -> void* { - CArgs args; + detail::TCargs args; ar &args; auto nT = detail::constructIfPossible(args); return typeid(T) == ti ? nT @@ -71,7 +68,8 @@ namespace ngcore { info.downcaster = [/*this*/](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; info.cargs_archiver = [this](Archive &ar, void* p) { - ar << get_cargs(*static_cast(p)); + if constexpr(detail::has_GetCArgs_v) + ar << static_cast(p)->GetCArgs(); }; #ifdef NETGEN_PYTHON info.anyToPyCaster = [](const std::any &a) { diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index 26543695..62f6df46 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -98,12 +98,14 @@ public: { ar & b; } + + auto GetCArgs() + { + return make_tuple(a, c); + } }; -static RegisterClassForArchive, tuple> -regwdc([](ClassWithoutDefaultConstructor& self) - { return make_tuple(self.a, self.c); }); +static RegisterClassForArchive regwdc; class OneMoreDerivedClass : public SharedPtrAndPtrHolder { };