-
Notifications
You must be signed in to change notification settings - Fork 141
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
imported/implemented boost/serialization/variant and test_variant
imported/implemented boost/serialization/variant now contains code for serialization of boost::variant, boost::variant2 and std::variant. Care has been taken to depend only on the public interfaces of these types. Hence, it is reasonable to hope that the archives are compatible in that one type could be saved and subsequently loaded into a compatible type. Hopefully this will be useful in some way. At a minimum it minimizes code duplication.
- Loading branch information
1 parent
61a2b12
commit 897dec4
Showing
6 changed files
with
251 additions
and
481 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,12 @@ | |
// troy d. straszheim <[email protected]> | ||
// http://www.resophonic.com | ||
// | ||
// copyright (c) 2019 Samuel Debionne, ESRF | ||
// | ||
// copyright (c) 2023 | ||
// Robert Ramey <[email protected]> | ||
// http://www.rrsd.com | ||
// | ||
// Use, modification and distribution is subject to the Boost Software | ||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||
// http://www.boost.org/LICENSE_1_0.txt) | ||
|
@@ -31,27 +37,57 @@ | |
|
||
#include <boost/serialization/throw_exception.hpp> | ||
|
||
#include <boost/variant.hpp> | ||
// Boost Variant supports all C++ versions back to C++03 | ||
#include <boost/variant/variant.hpp> | ||
#include <boost/variant/get.hpp> | ||
|
||
// Boost Variant2 supports all C++ versions back to C++11 | ||
#if BOOST_CXX_VERSION >= 201103L | ||
#include <boost/variant2/variant.hpp> | ||
#include <type_traits> | ||
#endif | ||
|
||
// Boost Variant2 supports all C++ versions back to C++11 | ||
#ifndef BOOST_NO_CXX17_HDR_VARIANT | ||
#include <variant> | ||
//#include <type_traits> | ||
#endif | ||
|
||
#include <boost/archive/archive_exception.hpp> | ||
|
||
#include <boost/serialization/split_free.hpp> | ||
#include <boost/serialization/serialization.hpp> | ||
#include <boost/serialization/nvp.hpp> | ||
|
||
// use visitor from boost::variant | ||
template<class Visitor, BOOST_VARIANT_ENUM_PARAMS(class T)> | ||
typename Visitor::result_type visit( | ||
Visitor visitor, | ||
const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & t | ||
){ | ||
return boost::apply_visitor(visitor, t); | ||
} | ||
template<class Visitor, BOOST_VARIANT_ENUM_PARAMS(class T)> | ||
typename Visitor::result_type visit( | ||
Visitor visitor, | ||
const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & t, | ||
const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & u | ||
){ | ||
return boost::apply_visitor(visitor, t, u); | ||
} | ||
|
||
namespace boost { | ||
namespace serialization { | ||
|
||
template<class Archive> | ||
struct variant_save_visitor : | ||
boost::static_visitor<> | ||
boost::static_visitor<void> | ||
{ | ||
variant_save_visitor(Archive& ar) : | ||
m_ar(ar) | ||
{} | ||
template<class T> | ||
void operator()(T const & value) const | ||
{ | ||
void operator()(T const & value) const { | ||
m_ar << BOOST_SERIALIZATION_NVP(value); | ||
} | ||
private: | ||
|
@@ -67,27 +103,55 @@ void save( | |
int which = v.which(); | ||
ar << BOOST_SERIALIZATION_NVP(which); | ||
variant_save_visitor<Archive> visitor(ar); | ||
v.apply_visitor(visitor); | ||
visit(visitor, v); | ||
} | ||
|
||
#if BOOST_CXX_VERSION >= 201103L | ||
template<class Archive, class ...Types> | ||
void save( | ||
Archive & ar, | ||
boost::variant2::variant<Types...> const & v, | ||
unsigned int /*version*/ | ||
){ | ||
int which = v.index(); | ||
ar << BOOST_SERIALIZATION_NVP(which); | ||
const variant_save_visitor<Archive> visitor(ar); | ||
visit(visitor, v); | ||
} | ||
#endif | ||
|
||
#ifndef BOOST_NO_CXX17_HDR_VARIANT | ||
template<class Archive, class ...Types> | ||
void save( | ||
Archive & ar, | ||
std::variant<Types...> const & v, | ||
unsigned int /*version*/ | ||
){ | ||
int which = v.index(); | ||
ar << BOOST_SERIALIZATION_NVP(which); | ||
const variant_save_visitor<Archive> visitor(ar); | ||
visit(visitor, v); | ||
} | ||
#endif | ||
|
||
template<class S> | ||
struct variant_impl { | ||
|
||
struct load_null { | ||
template<class Archive, class V> | ||
static void invoke( | ||
Archive & /*ar*/, | ||
int /*which*/, | ||
std::size_t /*which*/, | ||
V & /*v*/, | ||
const unsigned int /*version*/ | ||
){} | ||
}; | ||
|
||
struct load_impl { | ||
struct load_member { | ||
template<class Archive, class V> | ||
static void invoke( | ||
Archive & ar, | ||
int which, | ||
std::size_t which, | ||
V & v, | ||
const unsigned int version | ||
){ | ||
|
@@ -99,31 +163,30 @@ struct variant_impl { | |
typedef typename mpl::front<S>::type head_type; | ||
head_type value; | ||
ar >> BOOST_SERIALIZATION_NVP(value); | ||
v = value; | ||
head_type * new_address = & boost::get<head_type>(v); | ||
v = std::move(value);; | ||
head_type * new_address = & get<head_type>(v); | ||
ar.reset_object_address(new_address, & value); | ||
return; | ||
} | ||
typedef typename mpl::pop_front<S>::type type; | ||
variant_impl<type>::load(ar, which - 1, v, version); | ||
variant_impl<type>::load_impl(ar, which - 1, v, version); | ||
} | ||
}; | ||
|
||
template<class Archive, class V> | ||
static void load( | ||
static void load_impl( | ||
Archive & ar, | ||
int which, | ||
std::size_t which, | ||
V & v, | ||
const unsigned int version | ||
){ | ||
typedef typename mpl::eval_if<mpl::empty<S>, | ||
mpl::identity<load_null>, | ||
mpl::identity<load_impl> | ||
mpl::identity<load_member> | ||
>::type typex; | ||
typex::invoke(ar, which, v, version); | ||
} | ||
|
||
}; | ||
}; // variant_impl | ||
|
||
template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)> | ||
void load( | ||
|
@@ -134,34 +197,99 @@ void load( | |
int which; | ||
typedef typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types; | ||
ar >> BOOST_SERIALIZATION_NVP(which); | ||
if(which >= mpl::size<types>::value) | ||
if(which >= mpl::size<types>::value){ | ||
// this might happen if a type was removed from the list of variant types | ||
boost::serialization::throw_exception( | ||
boost::archive::archive_exception( | ||
boost::archive::archive_exception::unsupported_version | ||
) | ||
); | ||
} | ||
variant_impl<types>::load_impl(ar, which, v, version); | ||
} | ||
|
||
#if BOOST_CXX_VERSION >= 201103L | ||
template<class Archive, class ... Types> | ||
void load( | ||
Archive & ar, | ||
boost::variant2::variant<Types...> & v, | ||
const unsigned int version | ||
){ | ||
int which; | ||
typedef typename boost::variant<Types...>::types types; | ||
ar >> BOOST_SERIALIZATION_NVP(which); | ||
if(which >= sizeof...(Types)){ | ||
// this might happen if a type was removed from the list of variant types | ||
boost::serialization::throw_exception( | ||
boost::archive::archive_exception( | ||
boost::archive::archive_exception::unsupported_version | ||
) | ||
); | ||
} | ||
variant_impl<types>::load_impl(ar, which, v, version); | ||
} | ||
#endif | ||
|
||
#ifndef BOOST_NO_CXX17_HDR_VARIANT | ||
template<class Archive, class ... Types> | ||
void load( | ||
Archive & ar, | ||
std::variant<Types...> & v, | ||
const unsigned int version | ||
){ | ||
int which; | ||
typedef typename boost::variant<Types...>::types types; | ||
ar >> BOOST_SERIALIZATION_NVP(which); | ||
if(which >= sizeof...(Types)){ | ||
// this might happen if a type was removed from the list of variant types | ||
boost::serialization::throw_exception( | ||
boost::archive::archive_exception( | ||
boost::archive::archive_exception::unsupported_version | ||
) | ||
); | ||
variant_impl<types>::load(ar, which, v, version); | ||
} | ||
variant_impl<types>::load_impl(ar, which, v, version); | ||
} | ||
#endif | ||
|
||
template<class Archive,BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)> | ||
inline void serialize( | ||
Archive & ar, | ||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & v, | ||
const unsigned int file_version | ||
){ | ||
split_free(ar,v,file_version); | ||
boost::serialization::split_free(ar,v,file_version); | ||
} | ||
|
||
#if BOOST_CXX_VERSION >= 201103L | ||
template<class Archive, class ... Types> | ||
inline void serialize( | ||
Archive & ar, | ||
boost::variant2::variant<Types...> & v, | ||
const unsigned int file_version | ||
){ | ||
boost::serialization::split_free(ar,v,file_version); | ||
} | ||
#endif | ||
|
||
#ifndef BOOST_NO_CXX17_HDR_VARIANT | ||
template<class Archive, class ... Types> | ||
inline void serialize( | ||
Archive & ar, | ||
std::variant<Types...> & v, | ||
const unsigned int file_version | ||
){ | ||
boost::serialization::split_free(ar,v,file_version); | ||
} | ||
#endif | ||
|
||
} // namespace serialization | ||
} // namespace boost | ||
|
||
//template<typename T0_, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)> | ||
|
||
#include <boost/serialization/tracking.hpp> | ||
|
||
namespace boost { | ||
namespace serialization { | ||
namespace serialization { | ||
|
||
template<BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)> | ||
struct tracking_level< | ||
|
@@ -172,6 +300,17 @@ struct tracking_level< | |
BOOST_STATIC_CONSTANT(int, value = type::value); | ||
}; | ||
|
||
#ifndef BOOST_NO_CXX17_HDR_VARIANT | ||
template<class... Types> | ||
struct tracking_level< | ||
std::variant<Types...> | ||
>{ | ||
typedef mpl::integral_c_tag tag; | ||
typedef mpl::int_< ::boost::serialization::track_always> type; | ||
BOOST_STATIC_CONSTANT(int, value = type::value); | ||
}; | ||
#endif | ||
|
||
} // namespace serialization | ||
} // namespace boost | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.