variant.hpp 4.7 KB

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