test_diamond.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  2. // test_diamond.cpp
  3. // (C) Copyright 2002-2009 Vladimir Prus and Robert Ramey.
  4. // Use, modification and distribution is subject to the Boost Software
  5. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // test of serialization library for diamond inheritence situations
  8. #include <cstddef> // NULL
  9. #include <fstream>
  10. #include <iostream>
  11. #include <boost/config.hpp>
  12. #include <cstdio> // remove
  13. #if defined(BOOST_NO_STDC_NAMESPACE)
  14. namespace std{
  15. using ::remove;
  16. }
  17. #endif
  18. #include "test_tools.hpp"
  19. #include <boost/serialization/map.hpp>
  20. #include <boost/serialization/utility.hpp>
  21. #include <boost/serialization/split_member.hpp>
  22. #include <boost/serialization/tracking.hpp>
  23. #include <boost/serialization/base_object.hpp>
  24. #include <boost/serialization/nvp.hpp>
  25. #include <boost/serialization/export.hpp>
  26. int save_count = 0; // used to detect when base class is saved multiple times
  27. int load_count = 0; // used to detect when base class is loaded multiple times
  28. class base {
  29. public:
  30. base() : i(0) {}
  31. base(int i) : i(i)
  32. {
  33. m[i] = "text";
  34. }
  35. template<class Archive>
  36. void save(Archive &ar, const unsigned int /* file_version */) const
  37. {
  38. std::cout << "Saving base\n";
  39. ar << BOOST_SERIALIZATION_NVP(i);
  40. ar << BOOST_SERIALIZATION_NVP(m);
  41. ++save_count;
  42. }
  43. template<class Archive>
  44. void load(Archive & ar, const unsigned int /* file_version */)
  45. {
  46. std::cout << "Restoring base\n";
  47. ar >> BOOST_SERIALIZATION_NVP(i);
  48. ar >> BOOST_SERIALIZATION_NVP(m);
  49. ++load_count;
  50. }
  51. BOOST_SERIALIZATION_SPLIT_MEMBER()
  52. bool operator==(const base& another) const
  53. {
  54. return i == another.i && m == another.m;
  55. }
  56. // make polymorphic by marking at least one function virtual
  57. virtual ~base() {};
  58. private:
  59. int i;
  60. std::map<int, std::string> m;
  61. };
  62. // note: the default is for object tracking to be performed if and only
  63. // if and object of the corresponding class is anywhere serialized
  64. // through a pointer. In this example, that doesn't occur so
  65. // by default, the shared base object wouldn't normally be tracked.
  66. // This would leave to multiple save/load operation of the data in
  67. // this shared base class. This wouldn't cause an error, but it would
  68. // be a waste of time. So set the tracking behavior trait of the base
  69. // class to always track serialized objects of that class. This permits
  70. // the system to detect and elminate redundent save/load operations.
  71. // (It is concievable that this might someday be detected automatically
  72. // but for now, this is not done so we have to rely on the programmer
  73. // to specify this trait)
  74. BOOST_CLASS_TRACKING(base, track_always)
  75. class derived1 : virtual public base {
  76. public:
  77. template<class Archive>
  78. void save(Archive &ar, const unsigned int /* file_version */) const
  79. {
  80. std::cout << "Saving derived1\n";
  81. ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
  82. }
  83. template<class Archive>
  84. void load(Archive & ar, const unsigned int /* file_version */)
  85. {
  86. std::cout << "Restoring derived1\n";
  87. ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
  88. }
  89. BOOST_SERIALIZATION_SPLIT_MEMBER()
  90. };
  91. class derived2 : virtual public base {
  92. public:
  93. template<class Archive>
  94. void save(Archive &ar, const unsigned int /* file_version */) const
  95. {
  96. std::cout << "Saving derived2\n";
  97. ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
  98. }
  99. template<class Archive>
  100. void load(Archive & ar, const unsigned int /* file_version */)
  101. {
  102. std::cout << "Restoring derived2\n";
  103. ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
  104. }
  105. BOOST_SERIALIZATION_SPLIT_MEMBER()
  106. };
  107. class final : public derived1, public derived2 {
  108. public:
  109. final() {}
  110. final(int i) : base(i) {}
  111. template<class Archive>
  112. void save(Archive &ar, const unsigned int /* file_version */) const
  113. {
  114. std::cout << "Saving final\n";
  115. ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived1);
  116. ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived2);
  117. }
  118. template<class Archive>
  119. void load(Archive & ar, const unsigned int /* file_version */)
  120. {
  121. std::cout << "Restoring final\n";
  122. ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived1);
  123. ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived2);
  124. }
  125. BOOST_SERIALIZATION_SPLIT_MEMBER()
  126. };
  127. BOOST_CLASS_EXPORT(final)
  128. int
  129. test_main( int /* argc */, char* /* argv */[] )
  130. {
  131. const char * testfile = boost::archive::tmpnam(NULL);
  132. BOOST_REQUIRE(NULL != testfile);
  133. const final b(3);
  134. {
  135. test_ostream ofs(testfile, TEST_STREAM_FLAGS);
  136. test_oarchive oa(ofs);
  137. oa << boost::serialization::make_nvp("b", b);
  138. }
  139. final b2;
  140. {
  141. test_istream ifs(testfile, TEST_STREAM_FLAGS);
  142. test_iarchive ia(ifs);
  143. ia >> boost::serialization::make_nvp("b2", b2);
  144. }
  145. BOOST_CHECK(1 == save_count);
  146. BOOST_CHECK(1 == load_count);
  147. BOOST_CHECK(b2 == b);
  148. std::remove(testfile);
  149. // do the same test with pointers
  150. testfile = boost::archive::tmpnam(NULL);
  151. BOOST_REQUIRE(NULL != testfile);
  152. save_count = 0;
  153. load_count = 0;
  154. const base* bp = new final( 3 );
  155. {
  156. test_ostream ofs(testfile);
  157. test_oarchive oa(ofs);
  158. oa << BOOST_SERIALIZATION_NVP(bp);
  159. }
  160. base* bp2;
  161. {
  162. test_istream ifs(testfile);
  163. test_iarchive ia(ifs);
  164. ia >> BOOST_SERIALIZATION_NVP(bp2);
  165. }
  166. BOOST_CHECK(1 == save_count);
  167. BOOST_CHECK(1 == load_count);
  168. BOOST_CHECK(*bp2 == *bp);
  169. delete bp;
  170. std::remove(testfile);
  171. return EXIT_SUCCESS;
  172. }