variant.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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 : boost::static_visitor<> {
  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. typedef BOOST_DEDUCED_TYPENAME boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types;
  60. variant_save_visitor<Archive> visitor(ar);
  61. v.apply_visitor(visitor);
  62. }
  63. template<class S>
  64. struct variant_impl {
  65. struct load_null {
  66. template<class Archive, class V>
  67. static void invoke(
  68. Archive & /*ar*/,
  69. int /*which*/,
  70. V & /*v*/,
  71. const unsigned int /*version*/
  72. ){}
  73. };
  74. struct load_impl {
  75. template<class Archive, class V>
  76. static void invoke(
  77. Archive & ar,
  78. int which,
  79. V & v,
  80. const unsigned int version
  81. ){
  82. if(which == 0){
  83. // note: A non-intrusive implementation (such as this one)
  84. // necessary has to copy the value. This wouldn't be necessary
  85. // with an implementation that de-serialized to the address of the
  86. // aligned storage included in the variant.
  87. typedef BOOST_DEDUCED_TYPENAME mpl::front<S>::type head_type;
  88. head_type value;
  89. ar >> BOOST_SERIALIZATION_NVP(value);
  90. v = value;
  91. ar.reset_object_address(& boost::get<head_type>(v), & value);
  92. return;
  93. }
  94. typedef BOOST_DEDUCED_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 BOOST_DEDUCED_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 BOOST_DEDUCED_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. #endif //BOOST_SERIALIZATION_VARIANT_HPP