archive for pointer to abstract base classes

This commit is contained in:
Christopher Lackner 2018-12-03 19:07:15 +01:00
parent 2ec3bb0df1
commit e845a203e9
5 changed files with 52 additions and 27 deletions

View File

@ -5,6 +5,17 @@ namespace ngcore
{
class Archive;
// create new pointer of type T if it is default constructible, else throw
template<typename T>
T* constructIfPossible_impl(...)
{ throw std::runtime_error(std::string(typeid(T).name()) + " is not default constructible!"); }
template<typename T, typename= typename std::enable_if<std::is_constructible<T>::value>::type>
T* constructIfPossible_impl(int) { return new T; }
template<typename T>
T* constructIfPossible() { return constructIfPossible_impl<T>(int{}); }
// Type trait to check if a class implements a 'void DoArchive(Archive&)' function
template<typename T>
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<T>::value)
{
p = new T;
nr2ptr.push_back(p);
(*this) & *p;
}
else
throw std::runtime_error("Class isn't registered properly");
p = constructIfPossible<T>();
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<T>::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<T, Bases...>::tryUpcast(ti, new T); };
{ return typeid(T) == ti ? constructIfPossible<T>()
: Caster<T, Bases...>::tryUpcast(ti, constructIfPossible<T>()); };
info.upcaster = [this](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Caster<T, Bases...>::tryUpcast(ti, (T*) p); };
info.downcaster = [this](const std::type_info& ti, void* p) -> void*

View File

@ -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

View File

@ -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; }

View File

@ -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);

View File

@ -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<SharedPtrHolder>::value, "");
SharedPtrHolder holder, holder2;
SharedPtrAndPtrHolder holder, holder2;
holder.names.push_back(make_shared<string>("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]);