-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add std::variant boost serialization support
- Loading branch information
1 parent
51b5bb1
commit 0fdda31
Showing
1 changed file
with
205 additions
and
0 deletions.
There are no files selected for viewing
205 changes: 205 additions & 0 deletions
205
tesseract_common/include/tesseract_common/std_variant_serialization.h
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 |
---|---|---|
@@ -0,0 +1,205 @@ | ||
#ifndef TESSERACT_COMMON_STD_VARIANT_SERIALIZATION_H | ||
#define TESSERACT_COMMON_STD_VARIANT_SERIALIZATION_H | ||
|
||
#if BOOST_VERSION > 108300 | ||
#include <boost/serialization/std_variant.hpp> | ||
#else | ||
|
||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 | ||
// variant.hpp - non-intrusive serialization of variant types | ||
// | ||
// copyright (c) 2019 Samuel Debionne, ESRF | ||
// | ||
// 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) | ||
// | ||
// See http://www.boost.org for updates, documentation, and revision history. | ||
// | ||
// Widely inspired form boost::variant serialization | ||
// | ||
|
||
#include <boost/serialization/throw_exception.hpp> | ||
|
||
#include <variant> | ||
|
||
#include <boost/archive/archive_exception.hpp> | ||
|
||
#include <boost/serialization/split_free.hpp> | ||
#include <boost/serialization/serialization.hpp> | ||
#include <boost/serialization/nvp.hpp> | ||
|
||
namespace boost { | ||
namespace serialization { | ||
|
||
template<class Archive> | ||
struct std_variant_save_visitor | ||
{ | ||
std_variant_save_visitor(Archive& ar) : | ||
m_ar(ar) | ||
{} | ||
template<class T> | ||
void operator()(T const & value) const | ||
{ | ||
m_ar << BOOST_SERIALIZATION_NVP(value); | ||
} | ||
private: | ||
Archive & m_ar; | ||
}; | ||
|
||
|
||
template<class Archive> | ||
struct std_variant_load_visitor | ||
{ | ||
std_variant_load_visitor(Archive& ar) : | ||
m_ar(ar) | ||
{} | ||
template<class T> | ||
void operator()(T & value) const | ||
{ | ||
m_ar >> BOOST_SERIALIZATION_NVP(value); | ||
} | ||
private: | ||
Archive & m_ar; | ||
}; | ||
|
||
template<class Archive, class ...Types> | ||
void save( | ||
Archive & ar, | ||
std::variant<Types...> const & v, | ||
unsigned int /*version*/ | ||
){ | ||
const std::size_t which = v.index(); | ||
ar << BOOST_SERIALIZATION_NVP(which); | ||
std_variant_save_visitor<Archive> visitor(ar); | ||
std::visit(visitor, v); | ||
} | ||
|
||
// Minimalist metaprogramming for handling parameter pack | ||
namespace mp { | ||
namespace detail { | ||
template <typename Seq> | ||
struct front_impl; | ||
|
||
template <template <typename...> class Seq, typename T, typename... Ts> | ||
struct front_impl<Seq<T, Ts...>> { | ||
using type = T; | ||
}; | ||
|
||
template <typename Seq> | ||
struct pop_front_impl; | ||
|
||
template <template <typename...> class Seq, typename T, typename... Ts> | ||
struct pop_front_impl<Seq<T, Ts...>> { | ||
using type = Seq<Ts...>; | ||
}; | ||
} //namespace detail | ||
|
||
template <typename... Ts> | ||
struct typelist {}; | ||
|
||
template <typename Seq> | ||
using front = typename detail::front_impl<Seq>::type; | ||
|
||
template <typename Seq> | ||
using pop_front = typename detail::pop_front_impl<Seq>::type; | ||
} // namespace mp | ||
|
||
template<std::size_t N, class Seq> | ||
struct variant_impl | ||
{ | ||
template<class Archive, class V> | ||
static void load ( | ||
Archive & ar, | ||
std::size_t which, | ||
V & v, | ||
const unsigned int version | ||
){ | ||
if(which == 0){ | ||
// note: A non-intrusive implementation (such as this one) | ||
// necessary has to copy the value. This wouldn't be necessary | ||
// with an implementation that de-serialized to the address of the | ||
// aligned storage included in the variant. | ||
using type = mp::front<Seq>; | ||
type value; | ||
ar >> BOOST_SERIALIZATION_NVP(value); | ||
v = std::move(value); | ||
type * new_address = & std::get<type>(v); | ||
ar.reset_object_address(new_address, & value); | ||
return; | ||
} | ||
//typedef typename mpl::pop_front<S>::type type; | ||
using types = mp::pop_front<Seq>; | ||
variant_impl<N - 1, types>::load(ar, which - 1, v, version); | ||
} | ||
}; | ||
|
||
template<class Seq> | ||
struct variant_impl<0, Seq> | ||
{ | ||
template<class Archive, class V> | ||
static void load ( | ||
Archive & /*ar*/, | ||
std::size_t /*which*/, | ||
V & /*v*/, | ||
const unsigned int /*version*/ | ||
){} | ||
}; | ||
|
||
template<class Archive, class... Types> | ||
void load( | ||
Archive & ar, | ||
std::variant<Types...>& v, | ||
const unsigned int version | ||
){ | ||
std::size_t which; | ||
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<sizeof...(Types), mp::typelist<Types...>>::load(ar, which, v, version); | ||
} | ||
|
||
template<class Archive,class... Types> | ||
inline void serialize( | ||
Archive & ar, | ||
std::variant<Types...> & v, | ||
const unsigned int file_version | ||
){ | ||
split_free(ar,v,file_version); | ||
} | ||
|
||
// Specialization for std::monostate | ||
template<class Archive> | ||
void serialize(Archive &ar, std::monostate &, const unsigned int /*version*/) | ||
{} | ||
|
||
} // namespace serialization | ||
} // namespace boost | ||
|
||
//template<typename T0_, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)> | ||
|
||
#include <boost/serialization/tracking.hpp> | ||
|
||
namespace boost { | ||
namespace serialization { | ||
|
||
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); | ||
}; | ||
|
||
} // namespace serialization | ||
} // namespace boost | ||
|
||
#endif | ||
|
||
#endif // TESSERACT_COMMON_STD_VARIANT_SERIALIZATION_H |