From 3efeab031d39dc60402f43897a818332e49b2fba Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Thu, 27 Jun 2013 17:39:20 -0700 Subject: [PATCH] fixing up polymorph prototype --- Makefile | 4 +- include/cereal/cereal.hpp | 10 +- sandbox_rtti.cpp | 232 ++++++++++++++------------------------ 3 files changed, 97 insertions(+), 149 deletions(-) diff --git a/Makefile b/Makefile index 0b84d419..038dbf77 100644 --- a/Makefile +++ b/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} diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp index be5dfd5a..d5d538cf 100644 --- a/include/cereal/cereal.hpp +++ b/include/cereal/cereal.hpp @@ -146,9 +146,15 @@ namespace cereal enum Flags { AllowEmptyClassElision = 1 }; // ###################################################################### + namespace detail + { + struct OutputArchiveBase {}; + struct InputArchiveBase {}; + } + //! The base output archive class template - 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 InputArchive + class InputArchive : public detail::InputArchiveBase { public: InputArchive(ArchiveType * const self) : self(self) { } diff --git a/sandbox_rtti.cpp b/sandbox_rtti.cpp index 9ca8e439..a281ccd1 100644 --- a/sandbox_rtti.cpp +++ b/sandbox_rtti.cpp @@ -26,174 +26,116 @@ */ #include -#include #include -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 -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 -struct _ptr_serialization_support - : ptr_serialization_support +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 -void instantiate_ptr_serialization(Serializable*, int, adl_tag ) {} + //TODO + template struct InputBinding {}; + template 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 \ -typename _ptr_serialization_support::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 + struct create_bindings + { + static const InputBinding & + load(std::true_type) + { + return cereal::detail::StaticObject>::getInstance(); + } -struct basic_pointer_iserializer{}; -struct basic_pointer_oserializer{}; + static const OutputBinding & + save(std::true_type) + { + return cereal::detail::StaticObject>::getInstance(); + } -template -struct InputBinding{}; -template -struct OutputBinding{}; + inline static void load(std::false_type) {} + inline static void save(std::false_type) {} + }; -template -struct export_impl -{ - static const InputBinding & - enable_load(std::true_type){ - return cereal::detail::StaticObject>::getInstance(); + //! When specialized, causes the compiler to instantiate its parameter + template + struct instantiate_function {}; + + template + struct polymorphic_serialization_support + { + static void instantiate(); + typedef instantiate_function unused; + }; + + template + void polymorphic_serialization_support::instantiate() + { + create_bindings::save( std::is_base_of() ); + + create_bindings::load( std::is_base_of() ); } - static const OutputBinding & - enable_save(std::true_type){ - return cereal::detail::StaticObject>::getInstance(); - } + namespace detail2 + { + template + 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 -struct instantiate_function {}; + bind_to_archives const & bind() const + { + bind( std::is_abstract() ); + return *this; + } + }; -template -struct ptr_serialization_support -{ - static void instantiate() __attribute__((__used__)); - typedef instantiate_function< - &ptr_serialization_support::instantiate - > x; -}; + template + struct init_binding; + } // end namespace -template -void -ptr_serialization_support::instantiate() -{ - export_impl::enable_save( - typename - Archive::is_saving() - ); + template + void instantiate_polymorphic_binding( T*, int, adl_tag ) {}; - export_impl::enable_load( - typename - Archive::is_loading() - ); -} +#define CEREAL_REGISTER_ARCHIVE(Archive) \ + namespace cereal { namespace detail { \ + template \ + typename polymorphic_serialization_support::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 -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()); - return *this; - } -}; - -template -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 { \ + static bind_to_archives const & b; \ }; \ - guid_initializer< T > const & init_guid< T >::g = \ - ::cereal::detail::StaticObject< \ - guid_initializer< T > \ - >::getInstance().export_guid(); \ - }}}} + bind_to_archives const & init_binding::b = \ + ::cereal::detail::StaticObject< \ + bind_to_archives \ + >::getInstance().bind(); \ + }}} // end namespaces + } // namespace detail +} // namespace cereal +#include -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 void nop(T&&t) {}