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