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 <type_traits> // for declval, enable_if_t, false_type, is_co...
#include <cstddef> // for std::byte
#include <set> // for set
#include <typeinfo> // for type_info
#include <utility> // for move, swap, pair
#include <vector> // for vector
@ -33,6 +34,13 @@ namespace pybind11
namespace ngcore
{
template <typename T>
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 <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
{
// 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 <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 =====================================================
// this functions can be overloaded in Archive implementations for more efficiency
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 =================================================
@ -663,7 +722,7 @@ namespace ngcore
void SetParallel (bool _parallel) { parallel = _parallel; }
private:
template<typename T, typename Bases, typename CArgs>
template<typename T, typename Bases>
friend class RegisterClassForArchive;
#ifdef NETGEN_PYTHON

View File

@ -37,7 +37,7 @@ namespace ngcore {
template <typename T>
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(); }
typedef decltype( check<T>(sizeof(char)) ) type;
static constexpr type value = type();
@ -45,14 +45,11 @@ namespace ngcore {
#endif // NETGEN_PYTHON
template<typename T, typename Bases=std::tuple<>, typename CArgs=std::tuple<>>
template<typename T, typename Bases=std::tuple<>>
class RegisterClassForArchive
{
public:
std::function<CArgs(T&)> get_cargs;
RegisterClassForArchive(std::function<CArgs(T&)> _get_cargs =
[](T&) -> std::tuple<> { return std::tuple<>{}; }) :
get_cargs(_get_cargs)
RegisterClassForArchive()
{
static_assert(std::is_base_of<Bases, T>::value ||
detail::is_base_of_tuple<T, Bases>,
@ -60,7 +57,7 @@ namespace ngcore {
detail::ClassArchiveInfo info {};
info.creator = [](const std::type_info& ti, Archive& ar) -> void*
{
CArgs args;
detail::TCargs<T> args;
ar &args;
auto nT = detail::constructIfPossible<T>(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<T, Bases>::tryDowncast(ti, 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
info.anyToPyCaster = [](const std::any &a) {

View File

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