2 Copyright (c) 2014, Randolph Voorhies, Shane Grant
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.
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.
28 #include <boost/test/unit_test.hpp>
33 PolyBase( int xx, float yy ) : x(xx), y(yy) {}
37 template <class Archive>
38 void serialize( Archive & ar )
43 virtual void foo() = 0;
45 bool operator==( PolyBase const & other ) const
47 return x == other.x && std::abs(y - other.y) < 1e-5;
51 struct PolyDerived : PolyBase
54 PolyDerived( int xx, float yy, bool aa, double bb ) :
55 PolyBase( xx, yy ), a(aa), b(bb) {}
60 template <class Archive>
61 void serialize( Archive & ar )
63 ar( cereal::base_class<PolyBase>( this ),
67 bool operator==( PolyDerived const & other ) const
69 return PolyBase::operator==( other ) && a == other.a && std::abs(b - other.b) < 1e-5;
75 struct PolyLA : std::enable_shared_from_this<PolyLA>
77 virtual void foo() = 0;
80 struct PolyDerivedLA : public PolyLA
82 PolyDerivedLA( int xx ) : x( xx ) { }
85 std::vector<std::shared_ptr<PolyLA>> vec;
87 template <class Archive>
88 void serialize( Archive & ar )
94 template <class Archive>
95 static void load_and_construct( Archive & ar, cereal::construct<PolyDerivedLA> & construct )
100 ar( construct->vec );
105 bool operator==( PolyDerivedLA const & other ) const
109 if( vec.size() != other.vec.size() )
111 for( size_t i = 0; i < vec.size(); ++i )
112 if( !(*std::dynamic_pointer_cast<PolyDerivedLA>(vec[i]) == *std::dynamic_pointer_cast<PolyDerivedLA>(other.vec[i])) )
119 std::ostream& operator<<(std::ostream& os, PolyDerivedLA const & s)
121 os << "[x: " << s.x << "] ";
122 for( auto const & v : s.vec )
123 os << " child: " << (*std::dynamic_pointer_cast<PolyDerivedLA>(v));
127 std::ostream& operator<<(std::ostream& os, PolyDerived const & s)
129 os << "[x: " << s.x << " y: " << s.y << " a: " << s.a << " b: " << s.b << "]";
133 CEREAL_REGISTER_TYPE(PolyDerived)
134 CEREAL_REGISTER_TYPE(PolyDerivedLA)
136 template <class IArchive, class OArchive>
137 void test_polymorphic()
139 std::random_device rd;
140 std::mt19937 gen(rd());
142 auto rngB = [&](){ return random_value<int>( gen ) % 2 == 0; };
143 auto rngI = [&](){ return random_value<int>( gen ); };
144 auto rngF = [&](){ return random_value<float>( gen ); };
145 auto rngD = [&](){ return random_value<double>( gen ); };
147 for(int ii=0; ii<100; ++ii)
149 std::shared_ptr<PolyBase> o_shared = std::make_shared<PolyDerived>( rngI(), rngF(), rngB(), rngD() );
150 std::weak_ptr<PolyBase> o_weak = o_shared;
151 std::unique_ptr<PolyBase> o_unique( new PolyDerived( rngI(), rngF(), rngB(), rngD() ) );
153 auto pda = std::make_shared<PolyDerivedLA>( rngI() );
154 pda->vec.emplace_back( std::make_shared<PolyDerivedLA>( rngI() ) );
155 std::shared_ptr<PolyLA> o_sharedLA = pda;
157 std::ostringstream os;
161 oar( o_shared, o_weak, o_unique );
165 decltype(o_shared) i_shared;
166 decltype(o_weak) i_weak;
167 decltype(o_unique) i_unique;
168 decltype(o_sharedLA) i_sharedLA;
170 std::istringstream is(os.str());
174 iar( i_shared, i_weak, i_unique );
178 auto i_locked = i_weak.lock();
179 auto o_locked = o_weak.lock();
181 auto i_sharedLA2 = i_sharedLA->shared_from_this();
183 BOOST_CHECK_EQUAL(i_shared.get(), i_locked.get());
184 BOOST_CHECK_EQUAL(*((PolyDerived*)i_shared.get()), *((PolyDerived*)o_shared.get()));
185 BOOST_CHECK_EQUAL(*((PolyDerived*)i_shared.get()), *((PolyDerived*)i_locked.get()));
186 BOOST_CHECK_EQUAL(*((PolyDerived*)i_locked.get()), *((PolyDerived*)o_locked.get()));
187 BOOST_CHECK_EQUAL(*((PolyDerived*)i_unique.get()), *((PolyDerived*)o_unique.get()));
188 BOOST_CHECK_EQUAL(*((PolyDerivedLA*)i_sharedLA.get()), *((PolyDerivedLA*)o_sharedLA.get()));
189 BOOST_CHECK_EQUAL(*((PolyDerivedLA*)i_sharedLA2.get()), *((PolyDerivedLA*)o_sharedLA.get()));
193 BOOST_AUTO_TEST_CASE( binary_polymorphic )
195 test_polymorphic<cereal::BinaryInputArchive, cereal::BinaryOutputArchive>();
198 BOOST_AUTO_TEST_CASE( portable_binary_polymorphic )
200 test_polymorphic<cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive>();
203 BOOST_AUTO_TEST_CASE( xml_polymorphic )
205 test_polymorphic<cereal::XMLInputArchive, cereal::XMLOutputArchive>();
208 BOOST_AUTO_TEST_CASE( json_polymorphic )
210 test_polymorphic<cereal::JSONInputArchive, cereal::JSONOutputArchive>();