diff --git a/include/boost/core/serialization.hpp b/include/boost/core/serialization.hpp index b432646..5111b38 100644 --- a/include/boost/core/serialization.hpp +++ b/include/boost/core/serialization.hpp @@ -27,6 +27,8 @@ namespace serialization template struct version; +class access; + // Our own version_type replacement. This has to be in // the `serialization` namespace, because its only purpose // is to add `serialization` as an associated namespace. @@ -54,17 +56,17 @@ using serialization::make_nvp; namespace detail { -template struct load_or_save; +template struct load_or_save_f; -template<> struct load_or_save +template<> struct load_or_save_f { template void operator()( A& a, T& t, unsigned int v ) const { - save( a, t, serialization::core_version_type( v ) ); + save( a, t, serialization::core_version_type( v ) ); } }; -template<> struct load_or_save +template<> struct load_or_save_f { template void operator()( A& a, T& t, unsigned int v ) const { @@ -76,7 +78,37 @@ template<> struct load_or_save template inline void split_free( A& a, T& t, unsigned int v ) { - detail::load_or_save< A::is_saving::value >()( a, t, v ); + detail::load_or_save_f< A::is_saving::value >()( a, t, v ); +} + +// split_member + +namespace detail +{ + +template struct load_or_save_m; + +template struct load_or_save_m +{ + template void operator()( A& a, T const& t, unsigned int v ) const + { + Access::member_save( a, t, v ); + } +}; + +template struct load_or_save_m +{ + template void operator()( A& a, T& t, unsigned int v ) const + { + Access::member_load( a, t, v ); + } +}; + +} // namespace detail + +template inline void split_member( A& a, T& t, unsigned int v ) +{ + detail::load_or_save_m< A::is_saving::value >()( a, t, v ); } } // namespace core diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 327e38e..45d4294 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -35,6 +35,7 @@ set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::serialization) boost_test(TYPE run SOURCES serialization_nvp_test.cpp) boost_test(TYPE run SOURCES serialization_split_free_test.cpp) +boost_test(TYPE run SOURCES serialization_split_member_test.cpp) endif() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f7a7319..192815e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -365,6 +365,7 @@ run size_test.cpp ; run serialization_nvp_test.cpp : : : /boost//serialization/off ; run serialization_split_free_test.cpp : : : /boost//serialization/off ; +run serialization_split_member_test.cpp : : : /boost//serialization/off ; use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/serialization_split_member_test.cpp b/test/serialization_split_member_test.cpp new file mode 100644 index 0000000..ec73d78 --- /dev/null +++ b/test/serialization_split_member_test.cpp @@ -0,0 +1,70 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if defined(__clang__) && defined(__has_warning) +# if __has_warning( "-Wdeprecated-copy" ) +# pragma clang diagnostic ignored "-Wdeprecated-copy" +# endif +#endif + +#include + +struct X +{ + int a, b; + +private: + + friend boost::serialization::access; + + template void load( Ar& ar, unsigned /*v*/ ) + { + ar >> a; + ar >> b; + } + + template void save( Ar& ar, unsigned /*v*/ ) const + { + ar << a; + ar << b; + } + + template void serialize( Ar& ar, unsigned v ) + { + boost::core::split_member( ar, *this, v ); + } +}; + +#include +#include +#include +#include +#include + +int main() +{ + std::ostringstream os; + + X x1 = { 7, 11 }; + + { + boost::archive::text_oarchive ar( os ); + ar << x1; + } + + std::string s = os.str(); + + X x2 = { 0, 0 }; + + { + std::istringstream is( s ); + boost::archive::text_iarchive ar( is ); + ar >> x2; + } + + BOOST_TEST_EQ( x1.a, x2.a ); + BOOST_TEST_EQ( x1.b, x2.b ); + + return boost::report_errors(); +}