mirror of
https://github.com/USCiLab/cereal.git
synced 2025-10-18 01:45:52 +02:00
204 lines
7.4 KiB
C++
204 lines
7.4 KiB
C++
/*
|
|
Copyright (c) 2013, 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
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
* 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
|
|
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#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>
|
|
{
|
|
typedef int type;
|
|
};
|
|
|
|
// 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 ) {}
|
|
|
|
// 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
|
|
|
|
namespace boost {
|
|
namespace archive {
|
|
namespace detail {
|
|
|
|
struct basic_pointer_iserializer{};
|
|
struct basic_pointer_oserializer{};
|
|
|
|
template <class A, class S>
|
|
struct InputBinding{};
|
|
template <class A, class S>
|
|
struct OutputBinding{};
|
|
|
|
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();
|
|
}
|
|
|
|
static const OutputBinding<Archive, Serializable> &
|
|
enable_save(std::true_type){
|
|
return cereal::detail::StaticObject<OutputBinding<Archive, Serializable>>::getInstance();
|
|
}
|
|
|
|
inline static void enable_load(std::false_type) {}
|
|
inline static void enable_save(std::false_type) {}
|
|
};
|
|
|
|
// On many platforms, naming a specialization of this template is
|
|
// enough to cause its argument to be instantiated.
|
|
template <void(*)()>
|
|
struct instantiate_function {};
|
|
|
|
template <class Archive, class Serializable>
|
|
struct ptr_serialization_support
|
|
{
|
|
static void instantiate() __attribute__((__used__));
|
|
typedef instantiate_function<
|
|
&ptr_serialization_support::instantiate
|
|
> x;
|
|
};
|
|
|
|
template <class Archive, class Serializable>
|
|
void
|
|
ptr_serialization_support<Archive,Serializable>::instantiate()
|
|
{
|
|
export_impl<Archive,Serializable>::enable_save(
|
|
typename
|
|
Archive::is_saving()
|
|
);
|
|
|
|
export_impl<Archive,Serializable>::enable_load(
|
|
typename
|
|
Archive::is_loading()
|
|
);
|
|
}
|
|
|
|
// 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 { \
|
|
namespace detail { \
|
|
namespace extra_detail { \
|
|
template<> \
|
|
struct init_guid< T > { \
|
|
static guid_initializer< T > const & g; \
|
|
}; \
|
|
guid_initializer< T > const & init_guid< T >::g = \
|
|
::cereal::detail::StaticObject< \
|
|
guid_initializer< T > \
|
|
>::getInstance().export_guid(); \
|
|
}}}}
|
|
|
|
|
|
struct Archive
|
|
{
|
|
typedef std::true_type is_saving;
|
|
typedef std::false_type is_loading;
|
|
};
|
|
|
|
struct MyType
|
|
{};
|
|
BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive);
|
|
BOOST_CLASS_EXPORT_IMPLEMENT(MyType);
|
|
|
|
template <class T>
|
|
void nop(T&&t) {}
|
|
int main()
|
|
{
|
|
//cereal::Singleton<boost::archive::detail::extra_detail::guid_initializer<MyType>>::getInstance();
|
|
}
|