Archive classes with non default ctor

This commit is contained in:
Hochsteger, Matthias 2023-08-29 18:27:39 +02:00 committed by Lackner, Christopher
parent 3ff2e46ddd
commit 7fa30dbfac
3 changed files with 72 additions and 13 deletions

View File

@ -14,6 +14,7 @@
#include <string> // for string #include <string> // for string
#include <type_traits> // for declval, enable_if_t, false_type, is_co... #include <type_traits> // for declval, enable_if_t, false_type, is_co...
#include <cstddef> // for std::byte #include <cstddef> // for std::byte
#include <set> // for set
#include <typeinfo> // for type_info #include <typeinfo> // for type_info
#include <utility> // for move, swap, pair #include <utility> // for move, swap, pair
#include <vector> // for vector #include <vector> // for vector
@ -33,6 +34,13 @@ namespace pybind11
namespace ngcore namespace ngcore
{ {
template <typename T>
struct Shallow {
T val;
Shallow() = default;
Shallow(T aval) : val(aval) { ; }
operator T&() { return val; }
};
#ifdef NETGEN_PYTHON #ifdef NETGEN_PYTHON
pybind11::object CastAnyToPy(const std::any& a); pybind11::object CastAnyToPy(const std::any& a);
@ -101,6 +109,31 @@ namespace ngcore
NGCORE_API static constexpr bool value = type::value; NGCORE_API static constexpr bool value = type::value;
}; };
template <typename T>
struct has_GetCArgs
{
template <typename C> static std::true_type check( decltype( sizeof(&C::GetCArgs )) ) { return std::true_type(); }
template <typename> static std::false_type check(...) { return std::false_type(); }
typedef decltype( check<T>(sizeof(char)) ) type;
static constexpr type value = type();
};
template<typename T>
constexpr bool has_GetCArgs_v = has_GetCArgs<T>::value;
template<typename T,
typename std::enable_if<!has_GetCArgs_v<T>>::type* = nullptr>
std::tuple<> GetCArgs(T&val) { return {}; }
template<typename T,
typename std::enable_if<has_GetCArgs_v<T>>::type* = nullptr>
auto GetCArgs(T&val) {
return val.GetCArgs();
}
template<typename T>
using TCargs = decltype(GetCArgs<T>(*static_cast<T*>(nullptr)));
struct ClassArchiveInfo struct ClassArchiveInfo
{ {
// create new object of this type and return a void* pointer that is points to the location // 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); return (*this);
} }
template <typename T>
Archive& operator&(std::set<T> &s)
{
auto size = s.size();
(*this) & size;
if(Output())
for(const auto & val : s)
(*this) << val;
else
{
for(size_t i=0; i<size; i++)
{
T val;
(*this) & val;
s.insert(val);
}
}
return *this;
}
// Archive arrays ===================================================== // Archive arrays =====================================================
// this functions can be overloaded in Archive implementations for more efficiency // this functions can be overloaded in Archive implementations for more efficiency
template <typename T, typename = std::enable_if_t<is_archivable<T>>> template <typename T, typename = std::enable_if_t<is_archivable<T>>>
@ -420,6 +473,12 @@ namespace ngcore
template <typename T>
Archive& operator & (ngcore::Shallow<T>& shallow)
{
this->Shallow(shallow.val);
return *this;
}
// Archive shared_ptrs ================================================= // Archive shared_ptrs =================================================
@ -663,7 +722,7 @@ namespace ngcore
void SetParallel (bool _parallel) { parallel = _parallel; } void SetParallel (bool _parallel) { parallel = _parallel; }
private: private:
template<typename T, typename Bases, typename CArgs> template<typename T, typename Bases>
friend class RegisterClassForArchive; friend class RegisterClassForArchive;
#ifdef NETGEN_PYTHON #ifdef NETGEN_PYTHON

View File

@ -37,7 +37,7 @@ namespace ngcore {
template <typename T> template <typename T>
struct has_shared_from_this struct has_shared_from_this
{ {
template <typename C> static std::true_type check( decltype( sizeof(&C::shared_from_this() )) ) { return std::true_type(); } template <typename C> static std::true_type check( decltype( sizeof(&C::shared_from_this )) ) { return std::true_type(); }
template <typename> static std::false_type check(...) { return std::false_type(); } template <typename> static std::false_type check(...) { return std::false_type(); }
typedef decltype( check<T>(sizeof(char)) ) type; typedef decltype( check<T>(sizeof(char)) ) type;
static constexpr type value = type(); static constexpr type value = type();
@ -45,14 +45,11 @@ namespace ngcore {
#endif // NETGEN_PYTHON #endif // NETGEN_PYTHON
template<typename T, typename Bases=std::tuple<>, typename CArgs=std::tuple<>> template<typename T, typename Bases=std::tuple<>>
class RegisterClassForArchive class RegisterClassForArchive
{ {
public: public:
std::function<CArgs(T&)> get_cargs; RegisterClassForArchive()
RegisterClassForArchive(std::function<CArgs(T&)> _get_cargs =
[](T&) -> std::tuple<> { return std::tuple<>{}; }) :
get_cargs(_get_cargs)
{ {
static_assert(std::is_base_of<Bases, T>::value || static_assert(std::is_base_of<Bases, T>::value ||
detail::is_base_of_tuple<T, Bases>, detail::is_base_of_tuple<T, Bases>,
@ -60,7 +57,7 @@ namespace ngcore {
detail::ClassArchiveInfo info {}; detail::ClassArchiveInfo info {};
info.creator = [](const std::type_info& ti, Archive& ar) -> void* info.creator = [](const std::type_info& ti, Archive& ar) -> void*
{ {
CArgs args; detail::TCargs<T> args;
ar &args; ar &args;
auto nT = detail::constructIfPossible<T>(args); auto nT = detail::constructIfPossible<T>(args);
return typeid(T) == ti ? nT return typeid(T) == ti ? nT
@ -71,7 +68,8 @@ namespace ngcore {
info.downcaster = [/*this*/](const std::type_info& ti, void* p) -> void* info.downcaster = [/*this*/](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases>::tryDowncast(ti, p); }; { return typeid(T) == ti ? p : Archive::Caster<T, Bases>::tryDowncast(ti, p); };
info.cargs_archiver = [this](Archive &ar, void* p) { info.cargs_archiver = [this](Archive &ar, void* p) {
ar << get_cargs(*static_cast<T*>(p)); if constexpr(detail::has_GetCArgs_v<T>)
ar << static_cast<T*>(p)->GetCArgs();
}; };
#ifdef NETGEN_PYTHON #ifdef NETGEN_PYTHON
info.anyToPyCaster = [](const std::any &a) { info.anyToPyCaster = [](const std::any &a) {

View File

@ -98,12 +98,14 @@ public:
{ {
ar & b; ar & b;
} }
auto GetCArgs()
{
return make_tuple(a, c);
}
}; };
static RegisterClassForArchive<ClassWithoutDefaultConstructor, static RegisterClassForArchive<ClassWithoutDefaultConstructor> regwdc;
tuple<>, tuple<int, double>>
regwdc([](ClassWithoutDefaultConstructor& self)
{ return make_tuple(self.a, self.c); });
class OneMoreDerivedClass : public SharedPtrAndPtrHolder { class OneMoreDerivedClass : public SharedPtrAndPtrHolder {
}; };