diff --git a/libsrc/core/basearchive.hpp b/libsrc/core/basearchive.hpp index cdd992fc..f16ef942 100644 --- a/libsrc/core/basearchive.hpp +++ b/libsrc/core/basearchive.hpp @@ -5,6 +5,17 @@ namespace ngcore { class Archive; + // create new pointer of type T if it is default constructible, else throw + template + T* constructIfPossible_impl(...) + { throw std::runtime_error(std::string(typeid(T).name()) + " is not default constructible!"); } + + template::value>::type> + T* constructIfPossible_impl(int) { return new T; } + + template + T* constructIfPossible() { return constructIfPossible_impl(int{}); } + // Type trait to check if a class implements a 'void DoArchive(Archive&)' function template struct has_DoArchive @@ -255,7 +266,7 @@ namespace ngcore + typeid(*p).name() + " not registered for archive"); else - reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), p); + reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), (void*) p); } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry @@ -300,29 +311,23 @@ namespace ngcore p = nullptr; else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) { - if (std::is_constructible::value) - { - p = new T; - nr2ptr.push_back(p); - (*this) & *p; - } - else - throw std::runtime_error("Class isn't registered properly"); - + p = constructIfPossible(); + nr2ptr.push_back(p); + (*this) & *p; } else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... { - // As stated above, we want this special behaviour only for our classes that implement DoArchive - std::string name; - (*this) & name; - auto info = GetArchiveRegister()[name]; - // the creator creates a new object of type name, and returns a void* pointing - // to T (which may have an offset) - p = (T*) info.creator(typeid(T)); - // we store the downcasted pointer (to be able to find it again from - // another class in a multiple inheritance tree) - nr2ptr.push_back(info.downcaster(typeid(T),p)); - (*this) & *p; + // As stated above, we want this special behaviour only for our classes that implement DoArchive + std::string name; + (*this) & name; + auto info = GetArchiveRegister()[name]; + // the creator creates a new object of type name, and returns a void* pointing + // to T (which may have an offset) + p = (T*) info.creator(typeid(T)); + // we store the downcasted pointer (to be able to find it again from + // another class in a multiple inheritance tree) + nr2ptr.push_back(info.downcaster(typeid(T),p)); + (*this) & *p; } else { @@ -360,10 +365,10 @@ namespace ngcore public: RegisterClassForArchive() { - static_assert(std::is_constructible::value, "Class registered for archive must be default constructible"); ClassArchiveInfo info; info.creator = [this,&info](const std::type_info& ti) -> void* - { return typeid(T) == ti ? new T : Caster::tryUpcast(ti, new T); }; + { return typeid(T) == ti ? constructIfPossible() + : Caster::tryUpcast(ti, constructIfPossible()); }; info.upcaster = [this](const std::type_info& ti, void* p) -> void* { return typeid(T) == ti ? p : Caster::tryUpcast(ti, (T*) p); }; info.downcaster = [this](const std::type_info& ti, void* p) -> void* diff --git a/libsrc/csg/csgeom.cpp b/libsrc/csg/csgeom.cpp index 3226e538..3662966d 100644 --- a/libsrc/csg/csgeom.cpp +++ b/libsrc/csg/csgeom.cpp @@ -326,9 +326,9 @@ namespace netgen void CSGeometry :: DoArchive(Archive& archive) { - archive & surfaces & surf2prim & solids & toplevelobjects & userpoints & userpoints_ref_factor + archive & surfaces & solids & toplevelobjects & userpoints & userpoints_ref_factor & identpoints & boundingbox & identicsurfaces & isidenticto & ideps - & filename & spline_surfaces; // TODO: & splinecurves2d & splinecurves3d + & filename & spline_surfaces; // TODO: & splinecurves2d & splinecurves3d & surf2prim } void CSGeometry :: SaveSurfaces (ostream & out) const diff --git a/libsrc/csg/csgeom.hpp b/libsrc/csg/csgeom.hpp index ee9e1260..ab91b08a 100644 --- a/libsrc/csg/csgeom.hpp +++ b/libsrc/csg/csgeom.hpp @@ -40,6 +40,11 @@ namespace netgen TopLevelObject (Solid * asolid, Surface * asurface = NULL); + void DoArchive(Archive& archive) + { + archive & solid & surface & red & blue & green & visible & transp & maxh + & material & layer & bc & bcname; + } const Solid * GetSolid() const { return solid; } Solid * GetSolid() { return solid; } diff --git a/libsrc/csg/solid.hpp b/libsrc/csg/solid.hpp index 724030bd..928f8985 100644 --- a/libsrc/csg/solid.hpp +++ b/libsrc/csg/solid.hpp @@ -57,6 +57,18 @@ namespace netgen Solid (optyp aop, Solid * as1, Solid * as2 = NULL); ~Solid (); + void DoArchive(Archive& archive) + { + archive & name & prim & s1 & s2 & visited & maxh & num_surfs; + if(archive.Output()) + archive << int(op); + else + { + int iop; + archive & iop; + op = optyp(iop); + } + } const char * Name () const { return name; } void SetName (const char * aname); diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index dc31be16..40ee202b 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -13,6 +13,7 @@ public: virtual void DoArchive(Archive& archive) { archive & a; } }; +// pure abstract base class class SharedPtrHolder : virtual public CommonBase { public: @@ -20,6 +21,7 @@ public: virtual ~SharedPtrHolder() { } + virtual void abstract() = 0; virtual void DoArchive(Archive& archive) { CommonBase::DoArchive(archive); @@ -49,6 +51,7 @@ public: SharedPtrHolder::DoArchive(archive); PtrHolder::DoArchive(archive); } + virtual void abstract() {} }; // Classes without virt. or multiple inheritance do not need to be registered @@ -91,12 +94,12 @@ void testSharedPointer(Archive& in, Archive& out) SECTION("Same shared ptr") { static_assert(has_DoArchive::value, ""); - SharedPtrHolder holder, holder2; + SharedPtrAndPtrHolder holder, holder2; holder.names.push_back(make_shared("name")); holder2.names = holder.names; // same shared ptr out & holder & holder2; out.FlushBuffer(); - SharedPtrHolder inholder, inholder2; + SharedPtrAndPtrHolder inholder, inholder2; in & inholder & inholder2; CHECK(inholder.names.size() == 1); CHECK(inholder.names[0] == inholder2.names[0]);