mirror of
https://github.com/USCiLab/cereal.git
synced 2025-07-20 07:22:00 +02:00
Mostly solution for 137
This is option 1 for #137 which I'm quite happy with. Works across compilation units and shared libs on linux, need to test on windows. As for #113, it doesn't seem to be an issue on linux so just remains to sort that out on windows.
This commit is contained in:
parent
3189f037b7
commit
93b5073c62
@ -460,12 +460,17 @@ namespace cereal
|
||||
@tparam T The type of the class being serialized
|
||||
@param version The version number associated with it */
|
||||
template <class T> inline
|
||||
void registerClassVersion( const std::uint32_t version )
|
||||
std::uint32_t registerClassVersion()
|
||||
{
|
||||
static const auto hash = std::type_index(typeid(T)).hash_code();
|
||||
const auto insertResult = itsVersionedTypes.insert( hash );
|
||||
const auto version =
|
||||
detail::StaticObject<detail::Versions>::getInstance().find( hash, detail::Version<T>::version );
|
||||
|
||||
if( insertResult.second ) // insertion took place, serialize the version number
|
||||
process( make_nvp<ArchiveType>("cereal_class_version", version) );
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
//! Member serialization
|
||||
@ -473,8 +478,7 @@ namespace cereal
|
||||
template <class T, PROCESS_IF(member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
access::member_serialize(*self, const_cast<T &>(t), detail::Version<T>::version);
|
||||
access::member_serialize(*self, const_cast<T &>(t), registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
@ -483,8 +487,7 @@ namespace cereal
|
||||
template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t), detail::Version<T>::version);
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t), registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
@ -493,8 +496,7 @@ namespace cereal
|
||||
template <class T, PROCESS_IF(member_versioned_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
access::member_save(*self, t, detail::Version<T>::version);
|
||||
access::member_save(*self, t, registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
@ -503,8 +505,7 @@ namespace cereal
|
||||
template <class T, PROCESS_IF(non_member_versioned_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
CEREAL_SAVE_FUNCTION_NAME(*self, t, detail::Version<T>::version);
|
||||
CEREAL_SAVE_FUNCTION_NAME(*self, t, registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
@ -513,8 +514,7 @@ namespace cereal
|
||||
template <class T, PROCESS_IF(member_versioned_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
self->process( access::member_save_minimal(*self, t, detail::Version<T>::version) );
|
||||
self->process( access::member_save_minimal(*self, t, registerClassVersion<T>()) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
@ -523,8 +523,7 @@ namespace cereal
|
||||
template <class T, PROCESS_IF(non_member_versioned_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
registerClassVersion<T>( detail::Version<T>::version );
|
||||
self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, detail::Version<T>::version) );
|
||||
self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, registerClassVersion<T>()) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
|
@ -322,12 +322,6 @@ namespace cereal
|
||||
namespace detail
|
||||
{
|
||||
// ######################################################################
|
||||
//! Holds all registered version information
|
||||
struct Versions
|
||||
{
|
||||
std::unordered_map<std::size_t, std::uint32_t> mapping;
|
||||
}; // struct Versions
|
||||
|
||||
//! Version information class
|
||||
/*! This is the base case for classes that have not been explicitly
|
||||
registered */
|
||||
@ -338,6 +332,18 @@ namespace cereal
|
||||
// always get a version number of 0
|
||||
};
|
||||
|
||||
//! Holds all registered version information
|
||||
struct Versions
|
||||
{
|
||||
std::unordered_map<std::size_t, std::uint32_t> mapping;
|
||||
|
||||
std::uint32_t find( std::size_t hash, std::uint32_t version )
|
||||
{
|
||||
const auto result = mapping.emplace( hash, version );
|
||||
return result.first->second;
|
||||
}
|
||||
}; // struct Versions
|
||||
|
||||
#ifdef CEREAL_FUTURE_EXPERIMENTAL
|
||||
// ######################################################################
|
||||
//! A class that can store any type
|
||||
|
@ -345,7 +345,7 @@ namespace cereal
|
||||
#else // NOT _MSC_VER
|
||||
//! Creates the appropriate bindings depending on whether the archive supports
|
||||
//! saving or loading
|
||||
static void instantiate();
|
||||
static void instantiate() CEREAL_USED;
|
||||
//! This typedef causes the compiler to instantiate this static function
|
||||
typedef instantiate_function<instantiate> unused;
|
||||
#endif // _MSC_VER
|
||||
@ -372,6 +372,7 @@ namespace cereal
|
||||
void bind(std::false_type) const
|
||||
{
|
||||
instantiate_polymorphic_binding((T*) 0, 0, adl_tag{});
|
||||
std::cerr << "here i am " << std::endl;
|
||||
}
|
||||
|
||||
//! Binding for abstract types
|
||||
|
@ -4,7 +4,6 @@
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
@ -15,7 +14,6 @@
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
@ -30,6 +28,24 @@
|
||||
#ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
#define CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
|
||||
//! Prevent link optimization from removing non-referenced static objects
|
||||
/*! Especially for polymorphic support, we create static objects which
|
||||
may not ever be explicitly referenced. Most linkers will detect this
|
||||
and remove the code causing various unpleasant runtime errors. These
|
||||
macros, adopted from Boost (see force_include.hpp) prevent this
|
||||
(C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
Use, modification and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt) */
|
||||
#ifdef _MSC_VER
|
||||
# define CEREAL_DLL_EXPORT __declspec(dllexport)
|
||||
# define CEREAL_USED
|
||||
#else // clang or gcc
|
||||
# define CEREAL_DLL_EXPORT
|
||||
//# define CEREAL_USED
|
||||
# define CEREAL_USED __attribute__ ((__used__))
|
||||
#endif
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace detail
|
||||
@ -38,7 +54,6 @@ namespace cereal
|
||||
/*! This class will create a single copy (singleton) of some
|
||||
type and ensures that merely referencing this type will
|
||||
cause it to be instantiated and initialized pre-execution.
|
||||
|
||||
For example, this is used heavily in the polymorphic pointer
|
||||
serialization mechanisms to bind various archive types with
|
||||
different polymorphic classes */
|
||||
@ -49,7 +64,7 @@ namespace cereal
|
||||
//! Forces instantiation at pre-execution time
|
||||
static void instantiate( T const & ) {}
|
||||
|
||||
static T & create()
|
||||
CEREAL_DLL_EXPORT static T & create()
|
||||
{
|
||||
static T t;
|
||||
instantiate(instance);
|
||||
@ -59,16 +74,16 @@ namespace cereal
|
||||
StaticObject( StaticObject const & /*other*/ ) {}
|
||||
|
||||
public:
|
||||
static T & getInstance()
|
||||
CEREAL_DLL_EXPORT static T & getInstance()
|
||||
{
|
||||
return create();
|
||||
}
|
||||
|
||||
private:
|
||||
static T & instance;
|
||||
CEREAL_DLL_EXPORT static T & instance;
|
||||
};
|
||||
|
||||
template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
|
||||
template <class T> CEREAL_DLL_EXPORT T & StaticObject<T>::instance = StaticObject<T>::create();
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
|
||||
|
@ -258,6 +258,8 @@ namespace cereal
|
||||
|
||||
auto & bindingMap = detail::StaticObject<detail::OutputBindingMap<Archive>>::getInstance().map;
|
||||
|
||||
std::cerr << "o " << bindingMap.size () << std::endl;
|
||||
|
||||
auto binding = bindingMap.find(std::type_index(ptrinfo));
|
||||
if(binding == bindingMap.end())
|
||||
throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(ptrinfo.name()) + ").\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user