C++ 14 for Archiver

This commit is contained in:
Matthias Hochsteger 2018-12-03 18:07:52 +01:00
parent b2a2c64845
commit 2ec3bb0df1
2 changed files with 45 additions and 71 deletions

View File

@ -205,7 +205,7 @@ macro(get_dll_from_lib dll_path lib_path)
get_filename_component(lib_name ${lib} name) get_filename_component(lib_name ${lib} name)
endmacro() endmacro()
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 14)
if(WIN32) if(WIN32)
get_WIN32_WINNT(ver) get_WIN32_WINNT(ver)
add_definitions(-D_WIN32_WINNT=${ver} -DWNT -DWNT_WINDOW -DNOMINMAX) add_definitions(-D_WIN32_WINNT=${ver} -DWNT -DWNT_WINDOW -DNOMINMAX)

View File

@ -153,17 +153,14 @@ namespace ngcore
// Downcasting is only possible for our registered classes // Downcasting is only possible for our registered classes
if(typeid(T) != typeid(*ptr)) if(typeid(T) != typeid(*ptr))
{ {
if constexpr(has_DoArchive<T>::value) if(GetArchiveRegister().count(std::string(typeid(*ptr).name())) == 0)
{ throw std::runtime_error(std::string("Archive error: Polymorphic type ")
if(GetArchiveRegister().count(std::string(typeid(*ptr).name())) == 0) + typeid(*ptr).name()
throw std::runtime_error(std::string("Archive error: Polymorphic type ") + " not registered for archive");
+ typeid(*ptr).name() reg_ptr = GetArchiveRegister()[typeid(*ptr).name()].downcaster(typeid(T), ptr.get());
+ " not registered for archive"); // if there was a true downcast we have to store more information
reg_ptr = GetArchiveRegister()[typeid(*ptr).name()].downcaster(typeid(T), ptr.get()); if(reg_ptr != (void*) ptr.get())
// if there was a true downcast we have to store more information neededDowncast = true;
if(reg_ptr != (void*) ptr.get())
neededDowncast = true;
}
} }
auto pos = shared_ptr2nr.find(reg_ptr); auto pos = shared_ptr2nr.find(reg_ptr);
// if not found store -1 and the pointer // if not found store -1 and the pointer
@ -225,19 +222,14 @@ namespace ngcore
{ {
// if there was a downcast we can expect the class to be registered (since archiving // if there was a downcast we can expect the class to be registered (since archiving
// wouldn't have worked else) // wouldn't have worked else)
if constexpr(has_DoArchive<T>::value) std::string name;
{ (*this) & name;
std::string name; auto info = GetArchiveRegister()[name];
(*this) & name; // same trick as above, create a shared ptr sharing lifetime with
auto info = GetArchiveRegister()[name]; // the shared_ptr<void> in the register, but pointing to our object
// same trick as above, create a shared ptr sharing lifetime with ptr = std::static_pointer_cast<T>(std::shared_ptr<void>(other,
// the shared_ptr<void> in the register, but pointing to our object info.upcaster(typeid(T),
ptr = std::static_pointer_cast<T>(std::shared_ptr<void>(other, other.get())));
info.upcaster(typeid(T),
other.get())));
}
else
throw std::runtime_error("Shouldn't get here...");
} }
else else
ptr = std::static_pointer_cast<T>(other); ptr = std::static_pointer_cast<T>(other);
@ -258,15 +250,12 @@ namespace ngcore
void* reg_ptr = (void*)p; void* reg_ptr = (void*)p;
if(typeid(T) != typeid(*p)) if(typeid(T) != typeid(*p))
{ {
if constexpr(has_DoArchive<T>::value) if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0)
{ throw std::runtime_error(std::string("Archive error: Polymorphic type ")
if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0) + typeid(*p).name()
throw std::runtime_error(std::string("Archive error: Polymorphic type ") + " not registered for archive");
+ typeid(*p).name() else
+ " not registered for archive"); reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), p);
else
reg_ptr = GetArchiveRegister()[typeid(*p).name()].downcaster(typeid(T), p);
}
} }
auto pos = ptr2nr.find(reg_ptr); auto pos = ptr2nr.find(reg_ptr);
// if the pointer is not found in the map create a new entry // if the pointer is not found in the map create a new entry
@ -274,7 +263,7 @@ namespace ngcore
{ {
ptr2nr[reg_ptr] = ptr_count++; ptr2nr[reg_ptr] = ptr_count++;
if(typeid(*p) == typeid(T)) if(typeid(*p) == typeid(T))
if constexpr (std::is_constructible<T>::value) if (std::is_constructible<T>::value)
{ {
return (*this) << -1 & (*p); return (*this) << -1 & (*p);
} }
@ -287,19 +276,12 @@ namespace ngcore
// to avoid compile time issues we allow this behaviour only for "our" classes that // to avoid compile time issues we allow this behaviour only for "our" classes that
// implement a void DoArchive(Archive&) member function // implement a void DoArchive(Archive&) member function
// To recreate the object we need to store the true type of it // To recreate the object we need to store the true type of it
if constexpr(has_DoArchive<T>::value) if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0)
{ throw std::runtime_error(std::string("Archive error: Polymorphic type ")
if(GetArchiveRegister().count(std::string(typeid(*p).name())) == 0)
throw std::runtime_error(std::string("Archive error: Polymorphic type ")
+ typeid(*p).name()
+ " not registered for archive");
else
return (*this) << -3 << std::string(typeid(*p).name()) & (*p);
}
else
throw std::runtime_error(std::string("Archive error: Class ")
+ typeid(*p).name() + typeid(*p).name()
+ " is polymorphic but not registered for archiving"); + " not registered for archive");
else
return (*this) << -3 << std::string(typeid(*p).name()) & (*p);
} }
} }
else else
@ -318,7 +300,7 @@ namespace ngcore
p = nullptr; p = nullptr;
else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...)
{ {
if constexpr (std::is_constructible<T>::value) if (std::is_constructible<T>::value)
{ {
p = new T; p = new T;
nr2ptr.push_back(p); nr2ptr.push_back(p);
@ -330,22 +312,17 @@ namespace ngcore
} }
else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... 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 // As stated above, we want this special behaviour only for our classes that implement DoArchive
if constexpr(has_DoArchive<T>::value) std::string name;
{ (*this) & name;
std::string name; auto info = GetArchiveRegister()[name];
(*this) & name; // the creator creates a new object of type name, and returns a void* pointing
auto info = GetArchiveRegister()[name]; // to T (which may have an offset)
// the creator creates a new object of type name, and returns a void* pointing p = (T*) info.creator(typeid(T));
// to T (which may have an offset) // we store the downcasted pointer (to be able to find it again from
p = (T*) info.creator(typeid(T)); // another class in a multiple inheritance tree)
// we store the downcasted pointer (to be able to find it again from nr2ptr.push_back(info.downcaster(typeid(T),p));
// another class in a multiple inheritance tree) (*this) & *p;
nr2ptr.push_back(info.downcaster(typeid(T),p));
(*this) & *p;
}
else
throw std::runtime_error("Class isn't registered properly");
} }
else else
{ {
@ -354,12 +331,9 @@ namespace ngcore
(*this) & downcasted & name; (*this) & downcasted & name;
if(downcasted) if(downcasted)
{ {
// if the class has been downcasted we can assume it is in the register // if the class has been downcasted we can assume it is in the register
if constexpr(has_DoArchive<T>::value) auto info = GetArchiveRegister()[name];
{ p = (T*) info.upcaster(typeid(T), nr2ptr[nr]);
auto info = GetArchiveRegister()[name];
p = (T*) info.upcaster(typeid(T), nr2ptr[nr]);
}
} }
else else
p = (T*) nr2ptr[nr]; p = (T*) nr2ptr[nr];
@ -386,7 +360,7 @@ namespace ngcore
public: public:
RegisterClassForArchive() RegisterClassForArchive()
{ {
static_assert(std::is_constructible_v<T>, "Class registered for archive must be default constructible"); static_assert(std::is_constructible<T>::value, "Class registered for archive must be default constructible");
ClassArchiveInfo info; ClassArchiveInfo info;
info.creator = [this,&info](const std::type_info& ti) -> void* 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 ? new T : Caster<T, Bases...>::tryUpcast(ti, new T); };