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. #include <boost/serialization/nvp.hpp>
  37. namespace boost {
  38. namespace serialization {
  39. template<class Archive>
  40. struct variant_save_visitor :
  41. boost::static_visitor<>
  42. {
  43. variant_save_visitor(Archive& ar) :
  44. m_ar(ar)
  45. {}
  46. template<class T>
  47. void operator()(T const & value) const
  48. {
  49. m_ar << BOOST_SERIALIZATION_NVP(value);
  50. }
  51. private:
  52. Archive & m_ar;
  53. };
  54. template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
  55. void save(
  56. Archive & ar,
  57. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const & v,
  58. unsigned int /*version*/
  59. ){
  60. int which = v.which();
  61. ar << BOOST_SERIALIZATION_NVP(which);
  62. typedef BOOST_DEDUCED_TYPENAME boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types;
  63. variant_save_visitor<Archive> visitor(ar);
  64. v.apply_visitor(visitor);
  65. }
  66. template<class S>
  67. struct variant_impl {
  68. struct load_null {
  69. template<class Archive, class V>
  70. static void invoke(
  71. Archive & /*ar*/,
  72. int /*which*/,
  73. V & /*v*/,
  74. const unsigned int /*version*/
  75. ){}
  76. };
  77. struct load_impl {
  78. template<class Archive, class V>
  79. static void invoke(
  80. Archive & ar,
  81. int which,
  82. V & v,
  83. const unsigned int version
  84. ){
  85. if(which == 0){
  86. // note: A non-intrusive implementation (such as this one)
  87. // necessary has to copy the value. This wouldn't be necessary
  88. // with an implementation that de-serialized to the address of the
  89. // aligned storage included in the variant.
  90. typedef BOOST_DEDUCED_TYPENAME mpl::front<S>::type head_type;
  91. head_type value;
  92. ar >> BOOST_SERIALIZATION_NVP(value);
  93. v = value;
  94. ar.reset_object_address(& boost::get<head_type>(v), & value);
  95. return;
  96. }
  97. typedef BOOST_DEDUCED_TYPENAME mpl::pop_front<S>::type type;
  98. variant_impl<type>::load(ar, which - 1, v, version);
  99. }
  100. };
  101. template<class Archive, class V>
  102. static void load(
  103. Archive & ar,
  104. int which,
  105. V & v,
  106. const unsigned int version
  107. ){
  108. typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<mpl::empty<S>,
  109. mpl::identity<load_null>,
  110. mpl::identity<load_impl>
  111. >::type typex;
  112. typex::invoke(ar, which, v, version);
  113. }
  114. };
  115. template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
  116. void load(
  117. Archive & ar,
  118. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& v,
  119. const unsigned int version
  120. ){
  121. int which;
  122. typedef BOOST_DEDUCED_TYPENAME boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types;
  123. ar >> BOOST_SERIALIZATION_NVP(which);
  124. if(which >= mpl::size<types>::value)
  125. // this might happen if a type was removed from the list of variant types
  126. boost::serialization::throw_exception(
  127. boost::archive::archive_exception(
  128. boost::archive::archive_exception::unsupported_version
  129. )
  130. );
  131. variant_impl<types>::load(ar, which, v, version);
  132. }
  133. template<class Archive,BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
  134. inline void serialize(
  135. Archive & ar,
  136. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & v,
  137. const unsigned int file_version
  138. ){
  139. split_free(ar,v,file_version);
  140. }
  141. } // namespace serialization
  142. } // namespace boost
  143. #endif //BOOST_SERIALIZATION_VARIANT_HPP