mirror of
https://github.com/USCiLab/cereal.git
synced 2025-10-18 01:45:52 +02:00
Added base_class to complement virtual_base_class
This commit is contained in:
@@ -34,7 +34,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <cereal/details/traits.hpp>
|
#include <cereal/details/traits.hpp>
|
||||||
#include <cereal/types/virtual_base_class.hpp>
|
#include <cereal/types/base_class.hpp>
|
||||||
#include <cereal/types/common.hpp>
|
#include <cereal/types/common.hpp>
|
||||||
|
|
||||||
namespace cereal
|
namespace cereal
|
||||||
@@ -284,6 +284,15 @@ namespace cereal
|
|||||||
return *self;
|
return *self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Serialization of a base_class wrapper
|
||||||
|
/*! \sa base_class */
|
||||||
|
template <class T> inline
|
||||||
|
ArchiveType & processImpl(base_class<T> b)
|
||||||
|
{
|
||||||
|
self->processImpl( *b.base_ptr );
|
||||||
|
return *self;
|
||||||
|
}
|
||||||
|
|
||||||
//! Member serialization
|
//! Member serialization
|
||||||
template <class T> inline
|
template <class T> inline
|
||||||
typename std::enable_if<traits::is_specialized_member_serialize<T, ArchiveType>() ||
|
typename std::enable_if<traits::is_specialized_member_serialize<T, ArchiveType>() ||
|
||||||
@@ -495,6 +504,16 @@ namespace cereal
|
|||||||
return *self;
|
return *self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Serialization of a base_class wrapper
|
||||||
|
/*! \sa base_class */
|
||||||
|
template <class T> inline
|
||||||
|
ArchiveType & processImpl(base_class<T> b)
|
||||||
|
{
|
||||||
|
self->processImpl( *b.base_ptr );
|
||||||
|
return *self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//! Member serialization
|
//! Member serialization
|
||||||
template <class T> inline
|
template <class T> inline
|
||||||
typename std::enable_if<traits::is_specialized_member_serialize<T, ArchiveType>() ||
|
typename std::enable_if<traits::is_specialized_member_serialize<T, ArchiveType>() ||
|
||||||
|
|||||||
@@ -24,53 +24,118 @@
|
|||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#ifndef CEREAL_TYPES_VIRTUAL_BASE_CLASS_HPP_
|
#ifndef CEREAL_TYPES_BASE_CLASS_HPP_
|
||||||
#define CEREAL_TYPES_VIRTUAL_BASE_CLASS_HPP_
|
#define CEREAL_TYPES_BASE_CLASS_HPP_
|
||||||
|
|
||||||
namespace cereal
|
namespace cereal
|
||||||
{
|
{
|
||||||
//! Casts a derived class to its base class in a way that allows cereal to track inheritance
|
//! Casts a derived class to its non-virtual base class in a way that safely supports abstract classes
|
||||||
|
/*! This should be used in cases when a derived type needs to serialize its base type. This is better than directly
|
||||||
|
using static_cast, as it allows for serialization of pure virtual (abstract) base classes.
|
||||||
|
|
||||||
|
\sa virtual_base_class
|
||||||
|
|
||||||
|
@code{.cpp}
|
||||||
|
struct MyBase
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
virtual void foo() = 0;
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void serialize( Archive & ar )
|
||||||
|
{
|
||||||
|
ar( x );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyDerived : public MyBase //<-- Note non-virtual inheritance
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
|
||||||
|
virtual void foo() {};
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void serialize( Archive & ar )
|
||||||
|
{
|
||||||
|
ar( cereal::base_class<MyBase>(this) );
|
||||||
|
ar( y );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@endcode */
|
||||||
|
template<class Base>
|
||||||
|
struct base_class
|
||||||
|
{
|
||||||
|
template<class Derived>
|
||||||
|
base_class(Derived const * derived) :
|
||||||
|
base_ptr(const_cast<Base*>(static_cast<Base const *>(derived)))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Base * base_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Casts a derived class to its virtual base class in a way that allows cereal to track inheritance
|
||||||
/*! This should be used in cases when a derived type features virtual inheritance from some
|
/*! This should be used in cases when a derived type features virtual inheritance from some
|
||||||
base type. This allows cereal to track the inheritance and to avoid making duplicate copies
|
base type. This allows cereal to track the inheritance and to avoid making duplicate copies
|
||||||
during serialization.
|
during serialization.
|
||||||
|
|
||||||
It is safe to use virtual_base_class in all circumstances for serializing base classes, even in cases
|
It is safe to use virtual_base_class in all circumstances for serializing base classes, even in cases
|
||||||
where virtual inheritance does not take place, though it may be slightly faster to utilize
|
where virtual inheritance does not take place, though it may be slightly faster to utilize
|
||||||
static_cast<> if you do not need to worry about virtual inheritance
|
cereal::base_class<> if you do not need to worry about virtual inheritance.
|
||||||
|
|
||||||
|
\sa base_class
|
||||||
|
|
||||||
@code{.cpp}
|
@code{.cpp}
|
||||||
struct MyBase
|
struct MyBase
|
||||||
{ };
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
struct MyLeft : virtual MyBase
|
|
||||||
{
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize( Archive & ar )
|
void serialize( Archive & ar )
|
||||||
{
|
{
|
||||||
ar( cereal::base_clas<MyBase>( this ) );
|
ar( x );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyLeft : virtual MyBase //<-- Note the virtual inheritance
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void serialize( Archive & ar )
|
||||||
|
{
|
||||||
|
ar( cereal::virtual_base_class<MyBase>( this ) );
|
||||||
|
ar( y );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MyRight : virtual MyBase
|
struct MyRight : virtual MyBase
|
||||||
{
|
{
|
||||||
|
int z;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize( Archive & ar )
|
void serialize( Archive & ar )
|
||||||
{
|
{
|
||||||
ar( cereal::base_clas<MyBase>( this ) );
|
ar( cereal::virtual_base_clas<MyBase>( this ) );
|
||||||
|
ar( z );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// diamond virtual inheritance; contains one copy if each base class
|
// diamond virtual inheritance; contains one copy of each base class
|
||||||
struct MyDerived : virtual MyLeft, virtual MyRight
|
struct MyDerived : virtual MyLeft, virtual MyRight
|
||||||
{
|
{
|
||||||
|
int a;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize( Archive & ar )
|
void serialize( Archive & ar )
|
||||||
{
|
{
|
||||||
ar( cereal::virtual_base_class<MyLeft>( this ) ); // safely serialize data members in MyLeft
|
ar( cereal::virtual_base_class<MyLeft>( this ) ); // safely serialize data members in MyLeft
|
||||||
ar( cereal::virtual_base_class<MyRight>( this ) ); // safely serialize data members in MyRight
|
ar( cereal::virtual_base_class<MyRight>( this ) ); // safely serialize data members in MyRight
|
||||||
|
ar( a );
|
||||||
|
|
||||||
// Because we used virtual_base_class, cereal will ensure that only one instance of MyBase is
|
// Because we used virtual_base_class, cereal will ensure that only one instance of MyBase is
|
||||||
// serialized as we traverse the inheritance heirarchy.
|
// serialized as we traverse the inheritance heirarchy. This means that there will be one copy
|
||||||
|
// each of the variables x, y, z, and a
|
||||||
|
|
||||||
// If we had chosen to use static_cast<> instead, cereal would perform no tracking and
|
// If we had chosen to use static_cast<> instead, cereal would perform no tracking and
|
||||||
// assume that every base class should be serialized (in this case leading to a duplicate
|
// assume that every base class should be serialized (in this case leading to a duplicate
|
||||||
@@ -86,5 +151,6 @@ namespace cereal
|
|||||||
|
|
||||||
Base * base_ptr;
|
Base * base_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cereal
|
} // namespace cereal
|
||||||
#endif // CEREAL_TYPES_VIRTUAL_BASE_CLASS_HPP_
|
#endif // CEREAL_TYPES_BASE_CLASS_HPP_
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
#include <cereal/types/memory.hpp>
|
#include <cereal/types/memory.hpp>
|
||||||
#include <cereal/types/complex.hpp>
|
#include <cereal/types/complex.hpp>
|
||||||
#include <cereal/types/boost_variant.hpp>
|
#include <cereal/types/boost_variant.hpp>
|
||||||
#include <cereal/types/virtual_base_class.hpp>
|
#include <cereal/types/base_class.hpp>
|
||||||
|
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|||||||
@@ -34,18 +34,21 @@
|
|||||||
|
|
||||||
struct Base
|
struct Base
|
||||||
{
|
{
|
||||||
|
int y;
|
||||||
virtual void foo() = 0;
|
virtual void foo() = 0;
|
||||||
|
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
void save(Archive & ar) const
|
void save(Archive & ar) const
|
||||||
{
|
{
|
||||||
std::cout << "Saving Base" << std::endl;
|
std::cout << "Saving Base" << std::endl;
|
||||||
|
ar( y );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
void load(Archive & ar)
|
void load(Archive & ar)
|
||||||
{
|
{
|
||||||
std::cout << "Loading Base" << std::endl;
|
std::cout << "Loading Base" << std::endl;
|
||||||
|
ar( y );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -59,12 +62,14 @@ struct MyType : public Base
|
|||||||
void save(Archive & ar) const
|
void save(Archive & ar) const
|
||||||
{
|
{
|
||||||
std::cout << "Saving MyType" << std::endl;
|
std::cout << "Saving MyType" << std::endl;
|
||||||
|
ar( cereal::virtual_base_class<Base>( this ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
void load(Archive & ar)
|
void load(Archive & ar)
|
||||||
{
|
{
|
||||||
std::cout << "Loading MyType" << std::endl;
|
std::cout << "Loading MyType" << std::endl;
|
||||||
|
ar( cereal::base_class<Base>( this ) );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
CEREAL_REGISTER_TYPE(MyType);
|
CEREAL_REGISTER_TYPE(MyType);
|
||||||
|
|||||||
Reference in New Issue
Block a user