mirror of
https://github.com/RPCS3/cereal.git
synced 2024-11-23 19:29:45 +00:00
fixing up polymorph prototype
This commit is contained in:
parent
0414f5dcf6
commit
3efeab031d
4
Makefile
4
Makefile
@ -1,5 +1,5 @@
|
||||
CPPFLAGS=-std=c++11 -I./include -Wall -Werror
|
||||
CC=g++
|
||||
CC=clang++
|
||||
|
||||
all: unittests sandbox performance sandbox_rtti
|
||||
|
||||
@ -7,7 +7,7 @@ sandbox: sandbox.cpp
|
||||
${CC} sandbox.cpp -o sandbox ${CPPFLAGS}
|
||||
|
||||
sandbox_rtti: sandbox_rtti.cpp
|
||||
${CC} sandbox_rtti.cpp -o sandbox_rtti ${CPPFLAGS} -lpthread
|
||||
${CC} sandbox_rtti.cpp -o sandbox_rtti ${CPPFLAGS} -O3
|
||||
|
||||
unittests: unittests.cpp
|
||||
time ${CC} unittests.cpp -o unittests -lboost_unit_test_framework ${CPPFLAGS}
|
||||
|
@ -146,9 +146,15 @@ namespace cereal
|
||||
enum Flags { AllowEmptyClassElision = 1 };
|
||||
|
||||
// ######################################################################
|
||||
namespace detail
|
||||
{
|
||||
struct OutputArchiveBase {};
|
||||
struct InputArchiveBase {};
|
||||
}
|
||||
|
||||
//! The base output archive class
|
||||
template<class ArchiveType, uint32_t Flags = 0>
|
||||
class OutputArchive
|
||||
class OutputArchive : public detail::OutputArchiveBase
|
||||
{
|
||||
public:
|
||||
OutputArchive(ArchiveType * const self) : self(self), itsCurrentPointerId(1)
|
||||
@ -297,7 +303,7 @@ namespace cereal
|
||||
// ######################################################################
|
||||
//! The base input archive class
|
||||
template<class ArchiveType, uint32_t Flags = 0>
|
||||
class InputArchive
|
||||
class InputArchive : public detail::InputArchiveBase
|
||||
{
|
||||
public:
|
||||
InputArchive(ArchiveType * const self) : self(self) { }
|
||||
|
232
sandbox_rtti.cpp
232
sandbox_rtti.cpp
@ -26,174 +26,116 @@
|
||||
*/
|
||||
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
#include <cereal/details/static_object.hpp>
|
||||
|
||||
namespace boost { namespace archive { namespace detail {
|
||||
|
||||
// No instantiate_ptr_serialization overloads generated by
|
||||
// BOOST_SERIALIZATION_REGISTER_ARCHIVE that lexically follow the call
|
||||
// will be seen *unless* they are in an associated namespace of one of
|
||||
// the arguments, so we pass one of these along to make sure this
|
||||
// namespace is considered. See temp.dep.candidate (14.6.4.2) in the
|
||||
// standard.
|
||||
struct adl_tag {};
|
||||
|
||||
template <class Archive, class Serializable>
|
||||
struct ptr_serialization_support;
|
||||
|
||||
// We could've just used ptr_serialization_support, above, but using
|
||||
// it with only a forward declaration causes vc6/7 to complain about a
|
||||
// missing instantiate member, even if it has one. This is just a
|
||||
// friendly layer of indirection.
|
||||
template <class Archive, class Serializable>
|
||||
struct _ptr_serialization_support
|
||||
: ptr_serialization_support<Archive,Serializable>
|
||||
namespace cereal
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
namespace detail
|
||||
{
|
||||
struct InputArchiveBase;
|
||||
struct OutputArchiveBase;
|
||||
|
||||
// This function gets called, but its only purpose is to participate
|
||||
// in overload resolution with the functions declared by
|
||||
// BOOST_SERIALIZATION_REGISTER_ARCHIVE, below.
|
||||
template <class Serializable>
|
||||
void instantiate_ptr_serialization(Serializable*, int, adl_tag ) {}
|
||||
//TODO
|
||||
template <class Archive, class T> struct InputBinding {};
|
||||
template <class Archive, class T> struct OutputBinding {};
|
||||
|
||||
// The function declaration generated by this macro never actually
|
||||
// gets called, but its return type gets instantiated, and that's
|
||||
// enough to cause registration of serialization functions between
|
||||
// Archive and any exported Serializable type. See also:
|
||||
// boost/serialization/export.hpp
|
||||
# define BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive) \
|
||||
namespace boost { namespace archive { namespace detail { \
|
||||
\
|
||||
template <class Serializable> \
|
||||
typename _ptr_serialization_support<Archive, Serializable>::type \
|
||||
instantiate_ptr_serialization( Serializable*, Archive*, adl_tag ); \
|
||||
\
|
||||
}}}
|
||||
}}} // namespace boost::archive::detail
|
||||
struct adl_tag {};
|
||||
|
||||
namespace boost {
|
||||
namespace archive {
|
||||
namespace detail {
|
||||
//! Causes the static object bindings between an archive type and a serializable type T
|
||||
template <class Archive, class T>
|
||||
struct create_bindings
|
||||
{
|
||||
static const InputBinding<Archive, T> &
|
||||
load(std::true_type)
|
||||
{
|
||||
return cereal::detail::StaticObject<InputBinding<Archive, T>>::getInstance();
|
||||
}
|
||||
|
||||
struct basic_pointer_iserializer{};
|
||||
struct basic_pointer_oserializer{};
|
||||
static const OutputBinding<Archive, T> &
|
||||
save(std::true_type)
|
||||
{
|
||||
return cereal::detail::StaticObject<OutputBinding<Archive, T>>::getInstance();
|
||||
}
|
||||
|
||||
template <class A, class S>
|
||||
struct InputBinding{};
|
||||
template <class A, class S>
|
||||
struct OutputBinding{};
|
||||
inline static void load(std::false_type) {}
|
||||
inline static void save(std::false_type) {}
|
||||
};
|
||||
|
||||
template <class Archive, class Serializable>
|
||||
struct export_impl
|
||||
{
|
||||
static const InputBinding<Archive, Serializable> &
|
||||
enable_load(std::true_type){
|
||||
return cereal::detail::StaticObject<InputBinding<Archive, Serializable>>::getInstance();
|
||||
//! When specialized, causes the compiler to instantiate its parameter
|
||||
template <void(*)()>
|
||||
struct instantiate_function {};
|
||||
|
||||
template <class Archive, class T>
|
||||
struct polymorphic_serialization_support
|
||||
{
|
||||
static void instantiate();
|
||||
typedef instantiate_function<instantiate> unused;
|
||||
};
|
||||
|
||||
template <class Archive, class T>
|
||||
void polymorphic_serialization_support<Archive,T>::instantiate()
|
||||
{
|
||||
create_bindings<Archive,T>::save( std::is_base_of<detail::OutputArchiveBase, Archive>() );
|
||||
|
||||
create_bindings<Archive,T>::load( std::is_base_of<detail::InputArchiveBase, Archive>() );
|
||||
}
|
||||
|
||||
static const OutputBinding<Archive, Serializable> &
|
||||
enable_save(std::true_type){
|
||||
return cereal::detail::StaticObject<OutputBinding<Archive, Serializable>>::getInstance();
|
||||
}
|
||||
namespace detail2
|
||||
{
|
||||
template <class T>
|
||||
struct bind_to_archives
|
||||
{
|
||||
void bind(std::false_type) const
|
||||
{
|
||||
instantiate_polymorphic_binding( (T*)0, 0, adl_tag{} );
|
||||
}
|
||||
|
||||
inline static void enable_load(std::false_type) {}
|
||||
inline static void enable_save(std::false_type) {}
|
||||
};
|
||||
void bind(std::true_type) const
|
||||
{ }
|
||||
|
||||
// On many platforms, naming a specialization of this template is
|
||||
// enough to cause its argument to be instantiated.
|
||||
template <void(*)()>
|
||||
struct instantiate_function {};
|
||||
bind_to_archives const & bind() const
|
||||
{
|
||||
bind( std::is_abstract<T>() );
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Archive, class Serializable>
|
||||
struct ptr_serialization_support
|
||||
{
|
||||
static void instantiate() __attribute__((__used__));
|
||||
typedef instantiate_function<
|
||||
&ptr_serialization_support::instantiate
|
||||
> x;
|
||||
};
|
||||
template <class T>
|
||||
struct init_binding;
|
||||
} // end namespace
|
||||
|
||||
template <class Archive, class Serializable>
|
||||
void
|
||||
ptr_serialization_support<Archive,Serializable>::instantiate()
|
||||
{
|
||||
export_impl<Archive,Serializable>::enable_save(
|
||||
typename
|
||||
Archive::is_saving()
|
||||
);
|
||||
template <class T>
|
||||
void instantiate_polymorphic_binding( T*, int, adl_tag ) {};
|
||||
|
||||
export_impl<Archive,Serializable>::enable_load(
|
||||
typename
|
||||
Archive::is_loading()
|
||||
);
|
||||
}
|
||||
#define CEREAL_REGISTER_ARCHIVE(Archive) \
|
||||
namespace cereal { namespace detail { \
|
||||
template <class T> \
|
||||
typename polymorphic_serialization_support<Archive, T>::type \
|
||||
instantiate_polymorphic_binding( T*, Archive*, adl_tag ); \
|
||||
} } // end namespaces
|
||||
|
||||
// Note INTENTIONAL usage of anonymous namespace in header.
|
||||
// This was made this way so that export.hpp could be included
|
||||
// in other headers. This is still under study.
|
||||
|
||||
namespace extra_detail {
|
||||
|
||||
template<class T>
|
||||
struct guid_initializer
|
||||
{
|
||||
void export_guid(std::false_type) const {
|
||||
// generates the statically-initialized objects whose constructors
|
||||
// register the information allowing serialization of T objects
|
||||
// through pointers to their base classes.
|
||||
instantiate_ptr_serialization((T*)0, 0, adl_tag());
|
||||
}
|
||||
void export_guid(std::true_type) const {
|
||||
}
|
||||
guid_initializer const & export_guid() const {
|
||||
// note: exporting an abstract base class will have no effect
|
||||
// and cannot be used to instantitiate serialization code
|
||||
// (one might be using this in a DLL to instantiate code)
|
||||
//BOOST_STATIC_WARNING(! boost::serialization::is_abstract< T >::value);
|
||||
export_guid(std::is_abstract<T>());
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct init_guid;
|
||||
|
||||
} // anonymous
|
||||
} // namespace detail
|
||||
} // namespace archive
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#define BOOST_CLASS_EXPORT_IMPLEMENT(T) \
|
||||
namespace boost { \
|
||||
namespace archive { \
|
||||
#define CEREAL_BIND_TO_ARCHIVES(T) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
namespace extra_detail { \
|
||||
namespace detail2 { \
|
||||
template<> \
|
||||
struct init_guid< T > { \
|
||||
static guid_initializer< T > const & g; \
|
||||
struct init_binding<T> { \
|
||||
static bind_to_archives<T> const & b; \
|
||||
}; \
|
||||
guid_initializer< T > const & init_guid< T >::g = \
|
||||
::cereal::detail::StaticObject< \
|
||||
guid_initializer< T > \
|
||||
>::getInstance().export_guid(); \
|
||||
}}}}
|
||||
bind_to_archives<T> const & init_binding<T>::b = \
|
||||
::cereal::detail::StaticObject< \
|
||||
bind_to_archives<T > \
|
||||
>::getInstance().bind(); \
|
||||
}}} // end namespaces
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
|
||||
#include <cereal/archives/binary.hpp>
|
||||
|
||||
struct Archive
|
||||
{
|
||||
typedef std::true_type is_saving;
|
||||
typedef std::false_type is_loading;
|
||||
};
|
||||
struct MyType {};
|
||||
|
||||
struct MyType
|
||||
{};
|
||||
BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive);
|
||||
BOOST_CLASS_EXPORT_IMPLEMENT(MyType);
|
||||
CEREAL_REGISTER_ARCHIVE(BinaryInputArchive);
|
||||
CEREAL_BIND_TO_ARCHIVES(MyType);
|
||||
|
||||
template <class T>
|
||||
void nop(T&&t) {}
|
||||
|
Loading…
Reference in New Issue
Block a user