1 /*
2   Copyright (c) 2014, Randolph Voorhies, Shane Grant
3   All rights reserved.
4 
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions are met:
7       * Redistributions of source code must retain the above copyright
8         notice, this list of conditions and the following disclaimer.
9       * Redistributions in binary form must reproduce the above copyright
10         notice, this list of conditions and the following disclaimer in the
11         documentation and/or other materials provided with the distribution.
12       * Neither the name of cereal nor the
13         names of its contributors may be used to endorse or promote products
14         derived from this software without specific prior written permission.
15 
16   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
20   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
28 #include <type_traits>
29 #include <cereal/archives/binary.hpp>
30 #include <cereal/archives/xml.hpp>
31 #include <cereal/types/polymorphic.hpp>
32 #include <sstream>
33 #include <fstream>
34 #include <iostream>
35 
36 struct Base
37 {
38   int y;
39   virtual void foo() = 0;
40 
41   template<class Archive>
saveBase42     void save(Archive & ar) const
43     {
44       std::cout << "Saving Base" << std::endl;
45       ar( y );
46     }
47 
48   template<class Archive>
loadBase49     void load(Archive & ar)
50     {
51       std::cout << "Loading Base" << std::endl;
52       ar( y );
53     }
54 };
55 
56 struct MyType : public Base
57 {
58   int x;
59 
fooMyType60   void foo() {}
61 
62   template<class Archive>
saveMyType63     void save(Archive & ar) const
64     {
65       std::cout << "Saving MyType" << std::endl;
66       ar( cereal::virtual_base_class<Base>( this ) );
67     }
68 
69   template<class Archive>
loadMyType70     void load(Archive & ar)
71     {
72       std::cout << "Loading MyType" << std::endl;
73       ar( cereal::base_class<Base>( this ) );
74     }
75 };
76 CEREAL_REGISTER_TYPE(MyType)
77 
78 struct YourType : public Base
79 {
YourTypeYourType80   YourType(int xx) : x(xx) {}
YourTypeYourType81   YourType() : x(-1) {}
82   int x;
83 
fooYourType84   void foo() {}
85 
86   template<class Archive>
saveYourType87     void save(Archive & ar) const
88     {
89       std::cout << "Saving YourType" << std::endl;
90       ar( x );
91     }
92 
93   template<class Archive>
loadYourType94     void load(Archive & ar)
95     {
96       std::cout << "Loading YourType" << std::endl;
97       ar( x );
98     }
99 };
100 
101 CEREAL_REGISTER_TYPE(YourType)
102 CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, YourType)
103 
104 struct OurBase
105 {
fooOurBase106   virtual void foo() {}
107 
108   template<class Archive>
serializeOurBase109     void serialize(Archive &)
110     { }
111 };
112 
113 struct OurType : public OurBase
114 {
OurTypeOurType115   OurType() : OurBase(), x() {}
OurTypeOurType116   OurType(int x_) : x(x_) {}
fooOurType117   void foo() {}
118 
119   int x;
120 
121   template<class Archive>
serializeOurType122     void serialize(Archive & ar)
123     {
124       ar( x );
125     }
126 };
127 
128 struct BaseVirtual
129 {
130   int x;
131   template <class Archive>
serializeBaseVirtual132   void serialize( Archive & ar )
133   { ar( x ); }
134   virtual void foo() = 0;
135 };
136 
137 struct DerivedVirtual : public virtual BaseVirtual
138 {
139   int y;
fooDerivedVirtual140   virtual void foo() {}
141 
142   template <class Archive>
saveDerivedVirtual143   void save( Archive & ar ) const
144   {
145     ar( cereal::virtual_base_class<BaseVirtual>( this ) );
146     ar( y );
147   }
148 
149   template <class Archive>
loadDerivedVirtual150   void load( Archive & ar )
151   {
152     ar( cereal::virtual_base_class<BaseVirtual>( this ) );
153     ar( y );
154   }
155 };
156 
157 struct TestType
158 {
159   int x;
160   template <class Archive>
serializeTestType161   void serialize( Archive & ar )
162   {
163     ar( x );
164   }
165 };
166 
167 namespace cereal
168 {
169   template <class Archive> struct specialize<Archive, DerivedVirtual, cereal::specialization::member_load_save> {};
170   template <class Archive> struct specialize<Archive, TestType, cereal::specialization::member_serialize> {};
171 }
172 
173 struct AAA
174 {
175   virtual void foo() = 0;
176 };
177 
178 struct BBB : AAA
179 {
fooBBB180   void foo() {}
181   template <class Archive>
serializeBBB182   void serialize( Archive & ) {}
183 };
184 
CEREAL_REGISTER_TYPE(BBB)185 CEREAL_REGISTER_TYPE(BBB)
186 
187 template <class T> void nop(T&&) {}
188 
main()189 int main()
190 {
191   {
192     std::ofstream ostream("rtti.txt");
193     //cereal::BinaryOutputArchive oarchive(ostream);
194     cereal::XMLOutputArchive oarchive(ostream);
195 
196     std::shared_ptr<Base> ptr1 = std::make_shared<MyType>();
197     std::shared_ptr<Base> ptr2 = std::make_shared<YourType>(33);
198     std::unique_ptr<Base> ptr3(new MyType());
199     std::weak_ptr<Base>   ptr4 = ptr2;
200 
201     std::shared_ptr<OurType> ptr5 = std::make_shared<OurType>(99);
202 
203     oarchive(ptr1);
204     oarchive(ptr2);
205     oarchive(ptr3);
206     oarchive(ptr4);
207     oarchive(ptr5);
208 
209     //std::shared_ptr<AAA> a = std::make_shared<BBB>();
210     //oarchive(a);
211   }
212 
213   {
214     std::ifstream istream("rtti.txt");
215     //cereal::BinaryInputArchive iarchive(istream);
216     cereal::XMLInputArchive iarchive(istream);
217 
218     std::shared_ptr<Base> ptr1;
219     std::shared_ptr<Base> ptr2;
220     std::unique_ptr<Base> ptr3;
221     std::weak_ptr<Base>   ptr4;
222 
223     std::shared_ptr<OurType> ptr5;
224 
225     iarchive(ptr1);
226     iarchive(ptr2);
227     iarchive(ptr3);
228     iarchive(ptr4);
229     iarchive(ptr5);
230   }
231 }
232