2025-01-12 20:40:08 +08:00

123 lines
2.6 KiB
C++

// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define _CRT_SECURE_NO_WARNINGS
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/core/nvp.hpp>
#include <type_traits>
#include <cstdio>
#include <vector>
namespace app
{
template<class Archive, class T,
class D1 = boost::describe::describe_bases<T, boost::describe::mod_public>,
class D2 = boost::describe::describe_bases<T,
boost::describe::mod_protected | boost::describe::mod_private>,
class D3 = boost::describe::describe_members<T,
boost::describe::mod_public | boost::describe::mod_protected>,
class D4 = boost::describe::describe_members<T, boost::describe::mod_private>,
class En = std::enable_if_t< boost::mp11::mp_empty<D2>::value &&
boost::mp11::mp_empty<D4>::value && !std::is_union<T>::value> >
void serialize( Archive & ar, T & t, boost::serialization::version_type )
{
int k = 0;
// public bases: use base_object
boost::mp11::mp_for_each<D1>([&](auto D){
using B = typename decltype(D)::type;
char name[ 32 ];
std::sprintf( name, "base.%d", ++k );
ar & boost::make_nvp( name, boost::serialization::base_object<B>( t ) );
});
// public (and protected) members
boost::mp11::mp_for_each<D3>([&](auto D){
ar & boost::make_nvp( D.name, t.*D.pointer );
});
}
struct A1
{
int x;
};
BOOST_DESCRIBE_STRUCT(A1, (), (x))
struct A2
{
int y;
};
BOOST_DESCRIBE_STRUCT(A2, (), (y))
struct B: public A1, public A2
{
// these constructors aren't needed in C++17
B(): A1(), A2() {}
B( int x, int y ): A1{ x }, A2{ y } {}
};
BOOST_DESCRIBE_STRUCT(B, (A1, A2), ())
struct C
{
std::vector<B> v;
};
BOOST_DESCRIBE_STRUCT(C, (), (v))
} // namespace app
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <string>
#include <sstream>
#include <iostream>
int main()
{
app::C c1{ { { 1, 2 }, { 3, 4 }, { 5, 6 } } };
std::ostringstream os;
{
boost::archive::xml_oarchive ar( os );
ar << boost::make_nvp( "c1", c1 );
}
std::string s = os.str();
std::cout << s << std::endl;
app::C c2;
{
std::istringstream is( s );
boost::archive::xml_iarchive ar( is );
ar >> boost::make_nvp( "c2", c2 );
}
{
boost::archive::text_oarchive ar( std::cout );
ar << c2;
}
}