variant2.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #ifndef BOOST_SERIALIZATION_VARIANT2_HPP
  2. #define BOOST_SERIALIZATION_VARIANT2_HPP
  3. // MS compatible compilers support #pragma once
  4. #if defined(_MSC_VER)
  5. # pragma once
  6. #endif
  7. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  8. // variant.hpp - non-intrusive serialization of variant types
  9. //
  10. // copyright (c) 2019 Samuel Debionne, ESRF
  11. //
  12. // Use, modification and distribution is subject to the Boost Software
  13. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  14. // http://www.boost.org/LICENSE_1_0.txt)
  15. //
  16. // See http://www.boost.org for updates, documentation, and revision history.
  17. //
  18. // Widely inspired form boost::variant serialization
  19. //
  20. #include <boost/serialization/throw_exception.hpp>
  21. #include <variant>
  22. #include <boost/archive/archive_exception.hpp>
  23. #include <boost/mp11/list.hpp>
  24. #include <boost/serialization/split_free.hpp>
  25. #include <boost/serialization/serialization.hpp>
  26. #include <boost/serialization/nvp.hpp>
  27. namespace boost {
  28. namespace serialization {
  29. template<class Archive>
  30. struct variant2_save_visitor
  31. {
  32. variant2_save_visitor(Archive& ar) :
  33. m_ar(ar)
  34. {}
  35. template<class T>
  36. void operator()(T const & value) const
  37. {
  38. m_ar << BOOST_SERIALIZATION_NVP(value);
  39. }
  40. private:
  41. Archive & m_ar;
  42. };
  43. template<class Archive>
  44. struct variant2_load_visitor
  45. {
  46. variant2_load_visitor(Archive& ar) :
  47. m_ar(ar)
  48. {}
  49. template<class T>
  50. void operator()(T & value) const
  51. {
  52. m_ar >> BOOST_SERIALIZATION_NVP(value);
  53. }
  54. private:
  55. Archive & m_ar;
  56. };
  57. template<class Archive, class ...Types>
  58. void save(
  59. Archive & ar,
  60. variant2::variant<Types...> const & v,
  61. unsigned int /*version*/
  62. ){
  63. const std::size_t which = v.index();
  64. ar << BOOST_SERIALIZATION_NVP(which);
  65. variant2_save_visitor<Archive> visitor(ar);
  66. std::visit(visitor, v);
  67. }
  68. template<class Seq>
  69. struct variant_impl
  70. {
  71. template<class Archive, class V>
  72. static void load (
  73. Archive & ar,
  74. std::size_t which,
  75. V & v,
  76. const unsigned int version
  77. ){
  78. if(which == 0){
  79. // note: A non-intrusive implementation (such as this one)
  80. // necessary has to copy the value. This wouldn't be necessary
  81. // with an implementation that de-serialized to the address of the
  82. // aligned storage included in the variant.
  83. using type = mp11::mp_front<Seq>;
  84. type value;
  85. ar >> BOOST_SERIALIZATION_NVP(value);
  86. v = std::move(value);
  87. type * new_address = & variant2::get<type>(v);
  88. ar.reset_object_address(new_address, & value);
  89. return;
  90. }
  91. //typedef typename mpl::pop_front<S>::type type;
  92. using types = mp11::mp_pop_front<Seq>;
  93. variant_impl<types>::load(ar, which - 1, v, version);
  94. }
  95. };
  96. template<class Seq>
  97. struct variant_impl<Seq>
  98. {
  99. template<class Archive, class V>
  100. static void load (
  101. Archive & /*ar*/,
  102. std::size_t /*which*/,
  103. V & /*v*/,
  104. const unsigned int /*version*/
  105. ){}
  106. };
  107. template<class Archive, class... Types>
  108. void load(
  109. Archive & ar,
  110. variant2::variant<Types...> & v,
  111. const unsigned int version
  112. ){
  113. std::size_t which;
  114. ar >> BOOST_SERIALIZATION_NVP(which);
  115. if(which >= sizeof...(Types))
  116. // this might happen if a type was removed from the list of variant types
  117. boost::serialization::throw_exception(
  118. boost::archive::archive_exception(
  119. boost::archive::archive_exception::unsupported_version
  120. )
  121. );
  122. variant_impl<sizeof...(Types), mp11::mp_list<Types...>>::load(ar, which, v, version);
  123. }
  124. template<class Archive,class... Types>
  125. inline void serialize(
  126. Archive & ar,
  127. variant2::variant<Types...> & v,
  128. const unsigned int file_version
  129. ){
  130. split_free(ar,v,file_version);
  131. }
  132. // Specialization for std::monostate
  133. template<class Archive>
  134. void serialize(Archive &ar, variant2::monostate &, const unsigned int /*version*/)
  135. {}
  136. } // namespace serialization
  137. } // namespace boost
  138. //template<typename T0_, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)>
  139. #include <boost/serialization/tracking.hpp>
  140. namespace boost {
  141. namespace serialization {
  142. template<class... Types>
  143. struct tracking_level<
  144. variant2::variant<Types...>
  145. >{
  146. typedef mpl::integral_c_tag tag;
  147. typedef mpl::int_< ::boost::serialization::track_always> type;
  148. BOOST_STATIC_CONSTANT(int, value = type::value);
  149. };
  150. } // namespace serialization
  151. } // namespace boost
  152. #endif //BOOST_SERIALIZATION_VARIANT2_HPP