variant.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #ifndef BOOST_SERIALIZATION_VARIANT_HPP
  2. #define BOOST_SERIALIZATION_VARIANT_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) 2005
  11. // troy d. straszheim <troy@resophonic.com>
  12. // http://www.resophonic.com
  13. //
  14. // Use, modification and distribution is subject to the Boost Software
  15. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  16. // http://www.boost.org/LICENSE_1_0.txt)
  17. //
  18. // See http://www.boost.org for updates, documentation, and revision history.
  19. //
  20. // thanks to Robert Ramey, Peter Dimov, and Richard Crossley.
  21. //
  22. #include <boost/mpl/front.hpp>
  23. #include <boost/mpl/pop_front.hpp>
  24. #include <boost/mpl/eval_if.hpp>
  25. #include <boost/mpl/identity.hpp>
  26. #include <boost/mpl/size.hpp>
  27. #include <boost/mpl/empty.hpp>
  28. #include <boost/serialization/throw_exception.hpp>
  29. #include <boost/variant.hpp>
  30. #include <boost/archive/archive_exception.hpp>
  31. #include <boost/serialization/split_free.hpp>
  32. #include <boost/serialization/serialization.hpp>
  33. #include <boost/serialization/nvp.hpp>
  34. namespace boost {
  35. namespace serialization {
  36. template<class Archive>
  37. struct variant_save_visitor :
  38. boost::static_visitor<>
  39. {
  40. variant_save_visitor(Archive& ar) :
  41. m_ar(ar)
  42. {}
  43. template<class T>
  44. void operator()(T const & value) const
  45. {
  46. m_ar << BOOST_SERIALIZATION_NVP(value);
  47. }
  48. private:
  49. Archive & m_ar;
  50. };
  51. template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
  52. void save(
  53. Archive & ar,
  54. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const & v,
  55. unsigned int /*version*/
  56. ){
  57. int which = v.which();
  58. ar << BOOST_SERIALIZATION_NVP(which);
  59. variant_save_visitor<Archive> visitor(ar);
  60. v.apply_visitor(visitor);
  61. }
  62. template<class S>
  63. struct variant_impl {
  64. struct load_null {
  65. template<class Archive, class V>
  66. static void invoke(
  67. Archive & /*ar*/,
  68. int /*which*/,
  69. V & /*v*/,
  70. const unsigned int /*version*/
  71. ){}
  72. };
  73. struct load_impl {
  74. template<class Archive, class V>
  75. static void invoke(
  76. Archive & ar,
  77. int which,
  78. V & v,
  79. const unsigned int version
  80. ){
  81. if(which == 0){
  82. // note: A non-intrusive implementation (such as this one)
  83. // necessary has to copy the value. This wouldn't be necessary
  84. // with an implementation that de-serialized to the address of the
  85. // aligned storage included in the variant.
  86. typedef typename mpl::front<S>::type head_type;
  87. head_type value;
  88. ar >> BOOST_SERIALIZATION_NVP(value);
  89. v = value;
  90. head_type * new_address = & boost::get<head_type>(v);
  91. ar.reset_object_address(new_address, & value);
  92. return;
  93. }
  94. typedef typename mpl::pop_front<S>::type type;
  95. variant_impl<type>::load(ar, which - 1, v, version);
  96. }
  97. };
  98. template<class Archive, class V>
  99. static void load(
  100. Archive & ar,
  101. int which,
  102. V & v,
  103. const unsigned int version
  104. ){
  105. typedef typename mpl::eval_if<mpl::empty<S>,
  106. mpl::identity<load_null>,
  107. mpl::identity<load_impl>
  108. >::type typex;
  109. typex::invoke(ar, which, v, version);
  110. }
  111. };
  112. template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
  113. void load(
  114. Archive & ar,
  115. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& v,
  116. const unsigned int version
  117. ){
  118. int which;
  119. typedef typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types;
  120. ar >> BOOST_SERIALIZATION_NVP(which);
  121. if(which >= mpl::size<types>::value)
  122. // this might happen if a type was removed from the list of variant types
  123. boost::serialization::throw_exception(
  124. boost::archive::archive_exception(
  125. boost::archive::archive_exception::unsupported_version
  126. )
  127. );
  128. variant_impl<types>::load(ar, which, v, version);
  129. }
  130. template<class Archive,BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
  131. inline void serialize(
  132. Archive & ar,
  133. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & v,
  134. const unsigned int file_version
  135. ){
  136. split_free(ar,v,file_version);
  137. }
  138. } // namespace serialization
  139. } // namespace boost
  140. //template<typename T0_, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)>
  141. #include <boost/serialization/tracking.hpp>
  142. namespace boost {
  143. namespace serialization {
  144. template<BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
  145. struct tracking_level<
  146. variant<BOOST_VARIANT_ENUM_PARAMS(T)>
  147. >{
  148. typedef mpl::integral_c_tag tag;
  149. typedef mpl::int_< ::boost::serialization::track_always> type;
  150. BOOST_STATIC_CONSTANT(int, value = type::value);
  151. };
  152. } // namespace serialization
  153. } // namespace boost
  154. #endif //BOOST_SERIALIZATION_VARIANT_HPP