mirror of
https://github.com/USCiLab/cereal.git
synced 2025-10-18 01:45:52 +02:00
fixing up polymorph prototype
This commit is contained in:
4
Makefile
4
Makefile
@@ -1,5 +1,5 @@
|
|||||||
CPPFLAGS=-std=c++11 -I./include -Wall -Werror
|
CPPFLAGS=-std=c++11 -I./include -Wall -Werror
|
||||||
CC=g++
|
CC=clang++
|
||||||
|
|
||||||
all: unittests sandbox performance sandbox_rtti
|
all: unittests sandbox performance sandbox_rtti
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ sandbox: sandbox.cpp
|
|||||||
${CC} sandbox.cpp -o sandbox ${CPPFLAGS}
|
${CC} sandbox.cpp -o sandbox ${CPPFLAGS}
|
||||||
|
|
||||||
sandbox_rtti: sandbox_rtti.cpp
|
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
|
unittests: unittests.cpp
|
||||||
time ${CC} unittests.cpp -o unittests -lboost_unit_test_framework ${CPPFLAGS}
|
time ${CC} unittests.cpp -o unittests -lboost_unit_test_framework ${CPPFLAGS}
|
||||||
|
|||||||
@@ -146,9 +146,15 @@ namespace cereal
|
|||||||
enum Flags { AllowEmptyClassElision = 1 };
|
enum Flags { AllowEmptyClassElision = 1 };
|
||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct OutputArchiveBase {};
|
||||||
|
struct InputArchiveBase {};
|
||||||
|
}
|
||||||
|
|
||||||
//! The base output archive class
|
//! The base output archive class
|
||||||
template<class ArchiveType, uint32_t Flags = 0>
|
template<class ArchiveType, uint32_t Flags = 0>
|
||||||
class OutputArchive
|
class OutputArchive : public detail::OutputArchiveBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OutputArchive(ArchiveType * const self) : self(self), itsCurrentPointerId(1)
|
OutputArchive(ArchiveType * const self) : self(self), itsCurrentPointerId(1)
|
||||||
@@ -297,7 +303,7 @@ namespace cereal
|
|||||||
// ######################################################################
|
// ######################################################################
|
||||||
//! The base input archive class
|
//! The base input archive class
|
||||||
template<class ArchiveType, uint32_t Flags = 0>
|
template<class ArchiveType, uint32_t Flags = 0>
|
||||||
class InputArchive
|
class InputArchive : public detail::InputArchiveBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InputArchive(ArchiveType * const self) : self(self) { }
|
InputArchive(ArchiveType * const self) : self(self) { }
|
||||||
|
|||||||
232
sandbox_rtti.cpp
232
sandbox_rtti.cpp
@@ -26,174 +26,116 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <iostream>
|
|
||||||
#include <cereal/details/static_object.hpp>
|
#include <cereal/details/static_object.hpp>
|
||||||
|
|
||||||
namespace boost { namespace archive { namespace detail {
|
namespace cereal
|
||||||
|
|
||||||
// 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>
|
|
||||||
{
|
{
|
||||||
typedef int type;
|
namespace detail
|
||||||
};
|
{
|
||||||
|
struct InputArchiveBase;
|
||||||
|
struct OutputArchiveBase;
|
||||||
|
|
||||||
// This function gets called, but its only purpose is to participate
|
//TODO
|
||||||
// in overload resolution with the functions declared by
|
template <class Archive, class T> struct InputBinding {};
|
||||||
// BOOST_SERIALIZATION_REGISTER_ARCHIVE, below.
|
template <class Archive, class T> struct OutputBinding {};
|
||||||
template <class Serializable>
|
|
||||||
void instantiate_ptr_serialization(Serializable*, int, adl_tag ) {}
|
|
||||||
|
|
||||||
// The function declaration generated by this macro never actually
|
struct adl_tag {};
|
||||||
// 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
|
|
||||||
|
|
||||||
namespace boost {
|
//! Causes the static object bindings between an archive type and a serializable type T
|
||||||
namespace archive {
|
template <class Archive, class T>
|
||||||
namespace detail {
|
struct create_bindings
|
||||||
|
{
|
||||||
|
static const InputBinding<Archive, T> &
|
||||||
|
load(std::true_type)
|
||||||
|
{
|
||||||
|
return cereal::detail::StaticObject<InputBinding<Archive, T>>::getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
struct basic_pointer_iserializer{};
|
static const OutputBinding<Archive, T> &
|
||||||
struct basic_pointer_oserializer{};
|
save(std::true_type)
|
||||||
|
{
|
||||||
|
return cereal::detail::StaticObject<OutputBinding<Archive, T>>::getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
template <class A, class S>
|
inline static void load(std::false_type) {}
|
||||||
struct InputBinding{};
|
inline static void save(std::false_type) {}
|
||||||
template <class A, class S>
|
};
|
||||||
struct OutputBinding{};
|
|
||||||
|
|
||||||
template <class Archive, class Serializable>
|
//! When specialized, causes the compiler to instantiate its parameter
|
||||||
struct export_impl
|
template <void(*)()>
|
||||||
{
|
struct instantiate_function {};
|
||||||
static const InputBinding<Archive, Serializable> &
|
|
||||||
enable_load(std::true_type){
|
template <class Archive, class T>
|
||||||
return cereal::detail::StaticObject<InputBinding<Archive, Serializable>>::getInstance();
|
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> &
|
namespace detail2
|
||||||
enable_save(std::true_type){
|
{
|
||||||
return cereal::detail::StaticObject<OutputBinding<Archive, Serializable>>::getInstance();
|
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) {}
|
void bind(std::true_type) const
|
||||||
inline static void enable_save(std::false_type) {}
|
{ }
|
||||||
};
|
|
||||||
|
|
||||||
// On many platforms, naming a specialization of this template is
|
bind_to_archives const & bind() const
|
||||||
// enough to cause its argument to be instantiated.
|
{
|
||||||
template <void(*)()>
|
bind( std::is_abstract<T>() );
|
||||||
struct instantiate_function {};
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <class Archive, class Serializable>
|
template <class T>
|
||||||
struct ptr_serialization_support
|
struct init_binding;
|
||||||
{
|
} // end namespace
|
||||||
static void instantiate() __attribute__((__used__));
|
|
||||||
typedef instantiate_function<
|
|
||||||
&ptr_serialization_support::instantiate
|
|
||||||
> x;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Archive, class Serializable>
|
template <class T>
|
||||||
void
|
void instantiate_polymorphic_binding( T*, int, adl_tag ) {};
|
||||||
ptr_serialization_support<Archive,Serializable>::instantiate()
|
|
||||||
{
|
|
||||||
export_impl<Archive,Serializable>::enable_save(
|
|
||||||
typename
|
|
||||||
Archive::is_saving()
|
|
||||||
);
|
|
||||||
|
|
||||||
export_impl<Archive,Serializable>::enable_load(
|
#define CEREAL_REGISTER_ARCHIVE(Archive) \
|
||||||
typename
|
namespace cereal { namespace detail { \
|
||||||
Archive::is_loading()
|
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.
|
#define CEREAL_BIND_TO_ARCHIVES(T) \
|
||||||
// This was made this way so that export.hpp could be included
|
namespace cereal { \
|
||||||
// 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 { \
|
|
||||||
namespace detail { \
|
namespace detail { \
|
||||||
namespace extra_detail { \
|
namespace detail2 { \
|
||||||
template<> \
|
template<> \
|
||||||
struct init_guid< T > { \
|
struct init_binding<T> { \
|
||||||
static guid_initializer< T > const & g; \
|
static bind_to_archives<T> const & b; \
|
||||||
}; \
|
}; \
|
||||||
guid_initializer< T > const & init_guid< T >::g = \
|
bind_to_archives<T> const & init_binding<T>::b = \
|
||||||
::cereal::detail::StaticObject< \
|
::cereal::detail::StaticObject< \
|
||||||
guid_initializer< T > \
|
bind_to_archives<T > \
|
||||||
>::getInstance().export_guid(); \
|
>::getInstance().bind(); \
|
||||||
}}}}
|
}}} // end namespaces
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace cereal
|
||||||
|
|
||||||
|
#include <cereal/archives/binary.hpp>
|
||||||
|
|
||||||
struct Archive
|
struct MyType {};
|
||||||
{
|
|
||||||
typedef std::true_type is_saving;
|
|
||||||
typedef std::false_type is_loading;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MyType
|
CEREAL_REGISTER_ARCHIVE(BinaryInputArchive);
|
||||||
{};
|
CEREAL_BIND_TO_ARCHIVES(MyType);
|
||||||
BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive);
|
|
||||||
BOOST_CLASS_EXPORT_IMPLEMENT(MyType);
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void nop(T&&t) {}
|
void nop(T&&t) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user