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 <cereal/cereal.hpp>
29 #include <cereal/archives/binary.hpp>
30 #include <cereal/archives/portable_binary.hpp>
31 #include <cereal/archives/xml.hpp>
32 
33 #include <cereal/types/string.hpp>
34 #include <cereal/types/utility.hpp>
35 #include <cereal/types/memory.hpp>
36 #include <cereal/types/complex.hpp>
37 #include <cereal/types/base_class.hpp>
38 #include <cereal/types/array.hpp>
39 #include <cereal/types/vector.hpp>
40 #include <cereal/types/map.hpp>
41 #include <cereal/types/utility.hpp>
42 #include <cereal/types/bitset.hpp>
43 #include <cereal/types/polymorphic.hpp>
44 
45 //#include <cxxabi.h>
46 #include <sstream>
47 #include <fstream>
48 #include <cassert>
49 #include <complex>
50 #include <iostream>
51 #include <random>
52 
53 class Base
54 {
55   private:
56     friend class cereal::access;
57     template <class Archive>
serialize(Archive & ar)58     void serialize( Archive & ar )
59     {
60       std::cout << "Base serialize" << std::endl;
61       ar( x );
62     }
63 
64     virtual void foo() = 0;
65 
66   public:
67     int x;
68 };
69 
70 class Derived : public Base
71 {
72   public:
73     using Base::x;
Derived()74     Derived() : Base(), y() {}
Derived(int d,int b)75     Derived( int d, int b )
76     {
77       y = d;
78       x = b;
79     }
80 
81     template <class Archive>
save(Archive & ar) const82     void save( Archive & ar ) const
83     {
84       ar( cereal::virtual_base_class<Base>(this) );
85       std::cout << "Derived save" << std::endl;
86       ar( y );
87     }
88 
89     template <class Archive>
load(Archive & ar)90     void load( Archive & ar )
91     {
92       ar( cereal::virtual_base_class<Base>(this) );
93       std::cout << "Derived load" << std::endl;
94       ar( y );
95     }
96 
foo()97     void foo() {}
98 
99     int y;
100 };
101 
102 namespace cereal
103 {
104   template <class Archive> struct specialize<Archive, Derived, cereal::specialization::member_load_save> {};
105 }
106 
107 CEREAL_REGISTER_TYPE(Derived)
108 
109 // ###################################
110 struct Test1
111 {
112   int a;
113 
114   private:
115     friend class cereal::access;
116     template<class Archive>
serializeTest1117     void serialize(Archive & ar)
118     {
119       ar(CEREAL_NVP(a));
120     }
121 };
122 
123 // ###################################
124 class Test2
125 {
126   public:
Test2()127     Test2() {}
Test2(int x)128     Test2( int x ) : a( x ) {}
129     int a;
130 
131   private:
132     friend class cereal::access;
133 
134     template<class Archive>
save(Archive & ar) const135       void save(Archive & ar) const
136       {
137         ar(a);
138       }
139 
140     template<class Archive>
load(Archive & ar)141       void load(Archive & ar)
142       {
143         ar(a);
144       }
145 };
146 
147 // ###################################
148 struct Test3
149 {
150   int a;
151 };
152 
153 template<class Archive>
serialize(Archive & ar,Test3 & t)154 void serialize(Archive & ar, Test3 & t)
155 {
156   ar(CEREAL_NVP(t.a));
157 }
158 
159 namespace test4
160 {
161   // ###################################
162   struct Test4
163   {
164     int a;
165   };
166 
167   template<class Archive>
save(Archive & ar,Test4 const & t)168   void save(Archive & ar, Test4 const & t)
169   {
170     ar(CEREAL_NVP(t.a));
171   }
172 
173   template<class Archive>
load(Archive & ar,Test4 & t)174   void load(Archive & ar, Test4 & t)
175   {
176     ar(CEREAL_NVP(t.a));
177   }
178 }
179 
180 class Private
181 {
182   public:
Private()183     Private() : a('z') {}
184 
185   private:
186     char a;
187 
188     friend class cereal::access;
189 
190     template<class Archive>
serialize(Archive & ar)191       void serialize(Archive & ar)
192       {
193         ar(a);
194       }
195 };
196 
197 struct Everything
198 {
199   int x;
200   int y;
201   Test1 t1;
202   Test2 t2;
203   Test3 t3;
204   test4::Test4 t4;
205   std::string s;
206 
207   template<class Archive>
serializeEverything208   void serialize(Archive & ar)
209   {
210     ar(CEREAL_NVP(x));
211     ar(CEREAL_NVP(y));
212     ar(CEREAL_NVP(t1));
213     ar(CEREAL_NVP(t2));
214     ar(CEREAL_NVP(t3));
215     ar(CEREAL_NVP(t4));
216     ar(CEREAL_NVP(s));
217   }
218 
operator ==Everything219   bool operator==(Everything const & o)
220   {
221     return
222       x == o.x &&
223       y == o.y &&
224       t1.a == o.t1.a &&
225       t2.a == o.t2.a &&
226       t3.a == o.t3.a &&
227       t4.a == o.t4.a &&
228       s == o.s;
229   }
230 };
231 
232 struct EmptyStruct
233 {
234   template<class Archive>
serializeEmptyStruct235   void serialize(Archive &)
236   {
237     std::cout << "Side effects!" << std::endl;
238   }
239 };
240 
241 struct NonEmptyStruct
242 {
243   int x, y, z;
244 };
245 
246 struct NoDefaultCtor
247 {
248 private:
NoDefaultCtorNoDefaultCtor249   NoDefaultCtor() {};
250   int z;
NoDefaultCtorNoDefaultCtor251   NoDefaultCtor( int x, bool ) :y(x) {}
252 public:
NoDefaultCtorNoDefaultCtor253   NoDefaultCtor(int x) : y(x)
254   { }
255 
256   friend class cereal::access;
257 
258   int y;
259 
260   template <class Archive>
serializeNoDefaultCtor261   void serialize( Archive & ar )
262   {
263     ar( y );
264   }
265 
266   template <class Archive>
load_and_constructNoDefaultCtor267   static void load_and_construct( Archive & ar, cereal::construct<NoDefaultCtor> & construct )
268   {
269     int yy;
270     ar( yy );
271     construct( yy, true );
272     construct->z = 33;
273     construct.ptr()->z = 33;
274   }
275 };
276 
277 //namespace cereal
278 //{
279 //  template <>
280 //  struct LoadAndConstruct<NoDefaultCtor>
281 //  {
282 //    template <class Archive>
283 //    static void load_and_construct( Archive & ar, cereal::construct<NoDefaultCtor> & construct )
284 //    {
285 //      int y;
286 //      ar( y );
287 //      construct( y );
288 //    }
289 //  };
290 //}
291 
292 struct unordered_naming
293 {
294   int x;
295   int y;
296   int z;
297 
298   template <class Archive>
saveunordered_naming299   void save( Archive & ar ) const
300   {
301     ar( CEREAL_NVP(x),
302         CEREAL_NVP(z),
303         CEREAL_NVP(y) );
304   }
305 
306   template <class Archive>
loadunordered_naming307   void load( Archive & ar )
308   {
309     ar( x,
310         CEREAL_NVP(y),
311         CEREAL_NVP(z) );
312   }
313 
operator ==unordered_naming314   bool operator==( unordered_naming const & other ) const
315   {
316     return x == other.x && y == other.y && z == other.z;
317   }
318 };
319 
operator <<(std::ostream & os,unordered_naming const & s)320 std::ostream& operator<<(std::ostream& os, unordered_naming const & s)
321 {
322   os << "[x: " << s.x << " y: " << s.y << " z: " << s.z << "]";
323   return os;
324 }
325 
326 template <class IArchive, class OArchive>
test_unordered_loads()327 void test_unordered_loads()
328 {
329   std::random_device rd;
330   std::mt19937 gen(rd());
331 
332   auto rngI = [](){ return 1; };
333   auto rngF = [](){ return 2.0f; };
334   auto rngD = [](){ return 3.2; };
335 
336   for(int i=0; i<100; ++i)
337   {
338     auto const name1 = "1";
339     auto const name2 = "2";
340     auto const name3 = "3";
341     auto const name4 = "4";
342     auto const name5 = "5";
343     auto const name6 = "6";
344     auto const name7 = "7";
345 
346     int o_int1 = rngI();
347     double o_double2 = rngD();
348     std::vector<bool> o_vecbool3 = { true, false, true, false, true };
349     int o_int4 = rngI();
350     int o_int5 = rngI();
351     int o_int6 = rngI();
352     std::pair<float, unordered_naming> o_un7;
353     o_un7.first = rngF();
354     o_un7.second.x = rngI();
355     o_un7.second.y = rngI();
356     o_un7.second.z = rngI();
357 
358     {
359       std::ofstream os("test.xml");
360       OArchive oar(os);
361 
362       oar( cereal::make_nvp( name1, o_int1 ),
363            cereal::make_nvp( name2, o_double2 ),
364            cereal::make_nvp( name3, o_vecbool3 ),
365            cereal::make_nvp( name4, o_int4 ),
366            cereal::make_nvp( name5, o_int5 ),
367            cereal::make_nvp( name6, o_int6 ),
368            cereal::make_nvp( name7, o_un7 ) );
369     }
370 
371     decltype(o_int1) i_int1;
372     decltype(o_double2) i_double2;
373     decltype(o_vecbool3) i_vecbool3;
374     decltype(o_int4) i_int4;
375     decltype(o_int5) i_int5;
376     decltype(o_int6) i_int6;
377     decltype(o_un7) i_un7;
378 
379     std::ifstream is("test.xml");
380     {
381       IArchive iar(is);
382 
383       iar( cereal::make_nvp( name7, o_un7 ),
384            cereal::make_nvp( name2, i_double2 ),
385            cereal::make_nvp( name4, i_int4 ),
386            cereal::make_nvp( name3, i_vecbool3 ),
387            cereal::make_nvp( name1, i_int1 ),
388            cereal::make_nvp( name5, i_int5 ),
389            i_int6 );
390     }
391   }
392 }
393 
394 class BoostTransitionMS
395 {
396   public:
BoostTransitionMS()397     BoostTransitionMS() {}
BoostTransitionMS(int xx)398     BoostTransitionMS( int xx ) : x(xx) {}
399 
getX()400     int getX(){ return x; }
setX(int xx)401     void setX( int xx ){ x = xx; }
402 
403   private:
404     friend class cereal::access;
405     int x;
406 
407     template <class Archive>
serialize(Archive & ar,const std::uint32_t)408     void serialize( Archive & ar, const std::uint32_t /*version*/ )
409     { ar( x ); }
410 };
411 
412 class BoostTransitionSplit
413 {
414   public:
BoostTransitionSplit()415     BoostTransitionSplit() {}
BoostTransitionSplit(int xx)416     BoostTransitionSplit( int xx ) : x(xx) {}
417 
getX()418     int getX(){ return x; }
setX(int xx)419     void setX( int xx ){ x = xx; }
420 
421   private:
422     friend class cereal::access;
423     int x;
424 
425     template <class Archive>
save(Archive & ar,const std::uint32_t) const426     void save( Archive & ar, const std::uint32_t /*version*/ ) const
427     { ar( x ); }
428 
429     template <class Archive>
load(Archive & ar,const std::uint32_t)430     void load( Archive & ar, const std::uint32_t /*version*/ )
431     { ar( x ); }
432 };
433 
434 class BoostTransitionNMS
435 {
436   public:
BoostTransitionNMS()437     BoostTransitionNMS() {}
BoostTransitionNMS(int xx)438     BoostTransitionNMS( int xx ) : x(xx) {}
439 
440     int x;
441 };
442 
443 template <class Archive>
serialize(Archive & ar,BoostTransitionNMS & bnms,const std::uint32_t version)444 void serialize( Archive & ar, BoostTransitionNMS & bnms, const std::uint32_t version )
445 { ar( bnms.x ); std::cout << "NMS version: " << version << std::endl; }
446 
447 struct BoostTransitionNMSplit
448 {
449   public:
BoostTransitionNMSplitBoostTransitionNMSplit450     BoostTransitionNMSplit() {}
BoostTransitionNMSplitBoostTransitionNMSplit451     BoostTransitionNMSplit( int xx ) : x(xx) {}
452 
453     int x;
454 };
455 
456 template <class Archive>
save(Archive & ar,BoostTransitionNMSplit const & bnsplit,const std::uint32_t version)457 void save( Archive & ar, BoostTransitionNMSplit const & bnsplit, const std::uint32_t version )
458 { ar( bnsplit.x ); std::cout << "NMsave version: " << version << std::endl; }
459 
460 template <class Archive>
load(Archive & ar,BoostTransitionNMSplit & bnsplit,const std::uint32_t version)461 void load( Archive & ar, BoostTransitionNMSplit & bnsplit, const std::uint32_t version )
462 { ar( bnsplit.x ); std::cout << "NMload version: " << version << std::endl; }
463 
464 // ######################################################################
main()465 int main()
466 {
467   std::cout << std::boolalpha << std::endl;
468 
469   Everything e_out;
470   e_out.x = 99;
471   e_out.y = 100;
472   e_out.t1 = {1};
473   e_out.t2 = {2};
474   e_out.t3 = {3};
475   e_out.t4 = {4};
476   e_out.s = "Hello, World!";
477   std::unique_ptr<NoDefaultCtor> nodefault( new NoDefaultCtor( 3 ) );
478 
479   Test2 t2 = {22};
480 
481   {
482     std::ofstream os("out.txt", std::ios::binary);
483     cereal::BinaryOutputArchive archive(os);
484     archive(CEREAL_NVP(e_out));
485     archive(t2);
486     archive(nodefault);
487   }
488 
489   Everything e_in;
490 
491   std::unique_ptr<NoDefaultCtor> nodefaultin( new NoDefaultCtor( 1 ) );
492 
493   {
494     std::ifstream is("out.txt", std::ios::binary);
495     cereal::BinaryInputArchive archive(is);
496     archive(CEREAL_NVP(e_in));
497     archive(t2);
498     archive(nodefaultin);
499     std::remove("out.txt");
500   }
501 
502   assert(e_in == e_out);
503   assert(nodefault->y == nodefaultin->y);
504 
505   {
506     cereal::BinaryOutputArchive archive(std::cout);
507     int xxx[] = {-1, 95, 3};
508     archive( xxx );
509 
510     cereal::XMLOutputArchive archive2(std::cout, cereal::XMLOutputArchive::Options(std::numeric_limits<double>::max_digits10, true, true));
511     archive2( xxx );
512 
513     std::vector<int> yyy = {1, 2, 3};
514     archive2( yyy );
515 
516     archive2.saveBinaryValue( xxx, sizeof(int)*3 );
517   }
518 
519   {
520     std::ofstream os("out.xml");
521     cereal::XMLOutputArchive oar( os );
522     //cereal::XMLOutputArchive oar( std::cout );
523 
524     oar( cereal::make_nvp("hello", 5 ) );
525 
526     std::string bla("bla");
527     oar( bla );
528 
529     auto intptr = std::make_shared<int>(99);
530     oar( CEREAL_NVP(intptr) );
531 
532     std::map<std::string, int> map1 =
533     {
534       {"one",   1},
535       {"two",   2},
536       {"three", 3}
537     };
538 
539     oar( CEREAL_NVP(map1) );
540 
541     int x = 3;
542     oar( CEREAL_NVP(x) );
543     oar( 5 );
544     oar( 3.3 );
545     oar( 3.2f );
546     oar( true );
547 
548     std::array<int,5> arr = {{1, 2, 3, 4, 5}};
549     oar( arr );
550 
551     std::vector<std::string> vec = {"hey",
552                                     "there",
553                                     "buddy"};
554 
555     std::vector<std::vector<std::string>> vec2 = {vec, vec, vec};
556 
557     oar( cereal::make_nvp("EVERYTHING", e_out) );
558     oar( vec );
559     oar( vec2 );
560 
561     int xxx[] = {-1, 95, 3};
562     oar.saveBinaryValue( xxx, sizeof(int)*3, "xxxbinary" );
563     //oar.saveBinaryValue( xxx, sizeof(int)*3 );
564 
565     std::unique_ptr<Derived> d1( new Derived(3, 4) );
566     std::unique_ptr<Base> d2( new Derived(4, 5) );
567     std::shared_ptr<Base> d3( new Derived(5, 6) );
568     oar( d1 );
569     oar( d2 );
570     oar( d3 );
571   }
572 
573   {
574     std::ifstream is("out.xml");
575     cereal::XMLInputArchive iar( is );
576 
577     int hello;
578     iar( cereal::make_nvp("hello", hello) );
579     assert( hello == 5 );
580 
581     std::string bla;
582     iar( bla );
583     assert( bla == "bla" );
584 
585     std::shared_ptr<int> intptr;
586     iar( CEREAL_NVP(intptr) );
587     assert( *intptr == 99 );
588 
589     std::map<std::string, int> map1;
590 
591     iar( CEREAL_NVP(map1) );
592     assert( map1["one"]   == 1 );
593     assert( map1["two"]   == 2 );
594     assert( map1["three"] == 3 );
595 
596 
597     int x;
598     iar( CEREAL_NVP(x) );
599     assert( x == 3 );
600 
601     int x5;
602     iar( x5 );
603     assert( x5 == 5 );
604 
605     double x33;
606     iar( x33 );
607     assert( x33 == 3.3 );
608 
609     float x32;
610     iar( x32 );
611     assert( x32 == 3.2f );
612 
613     bool xtrue;
614     iar( xtrue );
615     assert( xtrue == true );
616 
617     std::array<int,5> arr;
618     iar( arr );
619     for( int i = 0; i < 5; ++i )
620       assert( arr[i] == (i+1) );
621 
622     Everything e;
623     iar( cereal::make_nvp("EVERYTHING", e) );
624     assert( e == e_out );
625 
626     std::vector<std::string> vec;
627     iar( vec );
628     assert( vec[0] == "hey" );
629     assert( vec[1] == "there" );
630     assert( vec[2] == "buddy" );
631 
632     std::vector<std::vector<std::string>> vec2;
633     iar( vec2 );
634     for( auto & v : vec2 )
635     {
636       assert( v[0] == "hey" );
637       assert( v[1] == "there" );
638       assert( v[2] == "buddy" );
639     }
640 
641     int xxx[3];
642     iar.loadBinaryValue( xxx, sizeof(int)*3 );
643     assert( xxx[0] == -1 );
644     assert( xxx[1] == 95 );
645     assert( xxx[2] == 3 );
646 
647     std::unique_ptr<Derived> d1;
648     std::unique_ptr<Base> d2;
649     std::shared_ptr<Base> d3;
650 
651     iar( d1 );
652     assert( d1->x == 4 && d1->y == 3 );
653     iar( d2 );
654     assert( dynamic_cast<Derived*>(d2.get())->x == 5 && dynamic_cast<Derived*>(d2.get())->y == 4 );
655     iar( d3 );
656     assert( dynamic_cast<Derived*>(d3.get())->x == 6 && dynamic_cast<Derived*>(d3.get())->y == 5 );
657   }
658 
659   {
660     std::ofstream b("endian.out", std::ios::binary);
661     cereal::PortableBinaryOutputArchive oar(b);
662 
663     bool bb = true;
664     char a = 'a';
665     int x = 1234;
666     float y = 1.324f;
667     double z = 3.1452;
668     long double d = 1.123451234512345;
669     long long j = 2394873298472343;
670 
671     oar( bb, a, x, y, z, d, j );
672     std::cout << bb << " " << a << " " << x << " " << y << " " << z << " " << d << " " << j << std::endl;
673     // valgrind will complain about uninitialized bytes here - seems to be the padding caused by the long double and
674     // long long allocations (this padding just exists on the stack and is never used anywhere)
675     // see https://bugs.kde.org/show_bug.cgi?id=197915
676   }
677   {
678     std::ifstream b("endian.out", std::ios::binary);
679     cereal::PortableBinaryInputArchive iar(b);
680 
681     bool bb;
682     char a;
683     int x;
684     float y;
685     double z;
686     long double d;
687     long long j;
688 
689     iar( bb, a, x, y, z, d, j );
690 
691     std::cout << bb << " " << a << " " << x << " " << y << " " << z << " " << d << " " << j << std::endl;
692 
693     std::remove("endian.out");
694   }
695 
696   {
697     std::ofstream ss("xml_ordering.out");
698     cereal::XMLOutputArchive ar(ss);
699 
700     double one = 1;
701     double two = 2;
702     double three = 3;
703     std::vector<int> four = {1, 2, 3, 4};
704 
705     // Output is ordered 3 2 1 4
706     ar( three, CEREAL_NVP(two), one, cereal::make_nvp("five", four) );
707   }
708 
709   {
710     std::ifstream ss("xml_ordering.out");
711     cereal::XMLInputArchive ar(ss);
712 
713     // Output prodered out of order, try to load in order 1 2 3 4
714     double one;
715     double two;
716     double three;
717     std::vector<int> four;
718 
719     ar( one ); // cereal can only give warnings if you used an NVP!
720     ar( CEREAL_NVP( two ) );
721     ar( three );
722 
723     try
724     {
725       ar( CEREAL_NVP( three ) );
726     }
727     catch( cereal::Exception const & e )
728     {
729       std::cout << e.what() << std::endl;
730       std::cout << "Looked for three but we didn't use an NVP when saving" << std::endl;
731     }
732     ar( cereal::make_nvp("five", four) );
733     ar( cereal::make_nvp("five", four) ); // do it a second time since it shouldn't matter as we provide the name
734 
735     std::cout << one << std::endl;
736     std::cout << two << std::endl;
737     std::cout << three << std::endl;
738     for( auto i : four ) std::cout << i << " ";
739     std::cout << std::endl;
740   }
741 
742   {
743     // Boost transition layer stuff
744     std::ofstream ss("cereal_version.out");
745     cereal::XMLOutputArchive ar(ss);
746 
747     BoostTransitionMS b(3);
748     ar( b, b );
749 
750     BoostTransitionSplit c(4);
751     ar( c, c );
752 
753     BoostTransitionNMS d(5);
754     ar( d, d );
755 
756     BoostTransitionNMSplit e(32);
757     ar( e, e );
758   }
759 
760   {
761     // Boost transition layer stuff
762     std::ifstream ss("cereal_version.out");
763     cereal::XMLInputArchive ar(ss);
764 
765     BoostTransitionMS b;
766     ar( b );
767     assert( b.getX() == 3 );
768     b.setX( 0 );
769     ar( b );
770     assert( b.getX() == 3 );
771 
772     BoostTransitionSplit c;
773     ar( c );
774     assert( c.getX() == 4 );
775     c.setX( 0 );
776     ar( c );
777     assert( c.getX() == 4 );
778 
779     BoostTransitionNMS d;
780     ar( d );
781     assert( d.x == 5 );
782     d.x = 0;
783     ar( d );
784     assert( d.x == 5 );
785 
786     BoostTransitionNMSplit e;
787     ar( e );
788     assert( e.x == 32 );
789     e.x = 0;
790     ar( e );
791     assert( e.x == 32 );
792   }
793 
794 #ifdef CEREAL_FUTURE_EXPERIMENTAL
795   {
796     // Any testing
797     int x = 32;
798     int * xx = &x;
799     std::string y("hello");
800     cereal::detail::Any a(xx);
801     auto b = a;
802 
803     std::cout << *((int *)a) << std::endl;
804     *((int*)a) = 44;
805     std::cout << *((int *)b) << std::endl;
806     std::cout << *((int *)a) << std::endl;
807 
808     a = cereal::detail::Any(y);
809     std::string a_out = a;
810     std::cout << a_out << std::endl;
811   }
812 #endif // CEREAL_FUTURE_EXPERIMENTAL
813 
814   return 0;
815 }
816 
817 CEREAL_CLASS_VERSION(BoostTransitionMS, 1)
818 CEREAL_CLASS_VERSION(BoostTransitionSplit, 2)
819 CEREAL_CLASS_VERSION(BoostTransitionNMS, 3)
820 // keep the other at default version (0)
821