| 1 | /* Boost.MultiIndex test for copying and assignment. |
| 2 | * |
| 3 | * Copyright 2003-2018 Joaquin M Lopez Munoz. |
| 4 | * Distributed under the Boost Software License, Version 1.0. |
| 5 | * (See accompanying file LICENSE_1_0.txt or copy at |
| 6 | * http://www.boost.org/LICENSE_1_0.txt) |
| 7 | * |
| 8 | * See http://www.boost.org/libs/multi_index for library home page. |
| 9 | */ |
| 10 | |
| 11 | #include "test_copy_assignment.hpp" |
| 12 | |
| 13 | #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
| 14 | #include <algorithm> |
| 15 | #include <boost/move/utility_core.hpp> |
| 16 | #include <list> |
| 17 | #include <numeric> |
| 18 | #include <vector> |
| 19 | #include "pre_multi_index.hpp" |
| 20 | #include "employee.hpp" |
| 21 | #include "small_allocator.hpp" |
| 22 | #include <boost/detail/lightweight_test.hpp> |
| 23 | |
| 24 | using namespace boost::multi_index; |
| 25 | |
| 26 | #if BOOST_WORKAROUND(__MWERKS__,<=0x3003) |
| 27 | /* The "ISO C++ Template Parser" option makes CW8.3 incorrectly fail at |
| 28 | * expressions of the form sizeof(x) where x is an array local to a |
| 29 | * template function. |
| 30 | */ |
| 31 | |
| 32 | #pragma parse_func_templ off |
| 33 | #endif |
| 34 | |
| 35 | typedef multi_index_container<int> copyable_and_movable; |
| 36 | |
| 37 | struct holder |
| 38 | { |
| 39 | copyable_and_movable c; |
| 40 | }; |
| 41 | |
| 42 | template<typename Sequence> |
| 43 | static void test_assign() |
| 44 | { |
| 45 | Sequence s; |
| 46 | |
| 47 | int a[]={0,1,2,3,4,5}; |
| 48 | std::size_t sa=sizeof(a)/sizeof(a[0]); |
| 49 | |
| 50 | s.assign(&a[0],&a[sa]); |
| 51 | BOOST_TEST(s.size()==sa&&std::equal(s.begin(),s.end(),&a[0])); |
| 52 | |
| 53 | s.assign((const int*)(&a[0]),(const int*)(&a[sa])); |
| 54 | BOOST_TEST(s.size()==sa&&std::equal(s.begin(),s.end(),&a[0])); |
| 55 | |
| 56 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) |
| 57 | s.assign({0,1,2,3,4,5}); |
| 58 | #else |
| 59 | s.assign(&a[0],&a[sa]); |
| 60 | #endif |
| 61 | |
| 62 | BOOST_TEST(s.size()==sa&&std::equal(s.begin(),s.end(),&a[0])); |
| 63 | |
| 64 | s.assign((std::size_t)18,37); |
| 65 | BOOST_TEST(s.size()==18&&std::accumulate(s.begin(),s.end(),0)==666); |
| 66 | |
| 67 | s.assign((std::size_t)12,167); |
| 68 | BOOST_TEST(s.size()==12&&std::accumulate(s.begin(),s.end(),0)==2004); |
| 69 | } |
| 70 | |
| 71 | #if BOOST_WORKAROUND(__MWERKS__,<=0x3003) |
| 72 | #pragma parse_func_templ reset |
| 73 | #endif |
| 74 | |
| 75 | template<typename Sequence> |
| 76 | static void test_integral_assign() |
| 77 | { |
| 78 | /* Special cases described in 23.1.1/9: integral types must not |
| 79 | * be taken as iterators in assign(f,l) and insert(p,f,l). |
| 80 | */ |
| 81 | |
| 82 | Sequence s; |
| 83 | |
| 84 | s.assign(5,10); |
| 85 | BOOST_TEST(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50); |
| 86 | s.assign(2u,5u); |
| 87 | BOOST_TEST(s.size()==2&&std::accumulate(s.begin(),s.end(),0)==10); |
| 88 | |
| 89 | s.clear(); |
| 90 | s.insert(s.begin(),5,10); |
| 91 | BOOST_TEST(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50); |
| 92 | s.insert(s.begin(),2u,5u); |
| 93 | BOOST_TEST(s.size()==7&&std::accumulate(s.begin(),s.end(),0)==60); |
| 94 | } |
| 95 | |
| 96 | employee_set produce_employee_set() |
| 97 | { |
| 98 | employee_set es; |
| 99 | es.insert(x: employee(0,"Petr" ,60,2837)); |
| 100 | es.insert(x: employee(1,"Jiri" ,25,2143)); |
| 101 | es.insert(x: employee(2,"Radka" ,40,4875)); |
| 102 | es.insert(x: employee(3,"Milan" ,38,3474)); |
| 103 | return es; |
| 104 | } |
| 105 | |
| 106 | void test_copy_assignment() |
| 107 | { |
| 108 | employee_set es; |
| 109 | employee_set es2(es); |
| 110 | |
| 111 | employee_set::allocator_type al=es.get_allocator(); |
| 112 | al=get<1>(m&: es).get_allocator(); |
| 113 | al=get<2>(m&: es).get_allocator(); |
| 114 | al=get<3>(m&: es).get_allocator(); |
| 115 | al=get<4>(m&: es).get_allocator(); |
| 116 | al=get<5>(m&: es).get_allocator(); |
| 117 | |
| 118 | BOOST_TEST(es2.empty()); |
| 119 | |
| 120 | es2.insert(x: employee(0,"Joe" ,31,1123)); |
| 121 | es2.insert(x: employee(1,"Robert" ,27,5601)); |
| 122 | es2.insert(x: employee(2,"John" ,40,7889)); |
| 123 | es2.insert(x: employee(2,"Aristotle" ,2388,3357)); /* clash */ |
| 124 | es2.insert(x: employee(3,"Albert" ,20,9012)); |
| 125 | es2.insert(x: employee(4,"John" ,57,1002)); |
| 126 | es2.insert(x: employee(0,"Andrew" ,60,2302)); /* clash */ |
| 127 | |
| 128 | employee_set es3(es2); |
| 129 | |
| 130 | BOOST_TEST(es2==es3); |
| 131 | BOOST_TEST(get<2>(es2)==get<2>(es3)); |
| 132 | BOOST_TEST(get<3>(es2)==get<3>(es3)); |
| 133 | BOOST_TEST(get<5>(es2)==get<5>(es3)); |
| 134 | |
| 135 | employee_set es4=employee_set(non_std_allocator<employee>()); |
| 136 | employee_set_by_name& i1=get<name>(m&: es4); |
| 137 | i1=get<1>(m&: es2); |
| 138 | |
| 139 | BOOST_TEST(es4==es2); |
| 140 | |
| 141 | employee_set es5=employee_set(employee_set::ctor_args_list()); |
| 142 | employee_set_by_age& i2=get<age>(m&: es5); |
| 143 | i2=get<2>(m&: es2); |
| 144 | |
| 145 | BOOST_TEST(i2==get<2>(es2)); |
| 146 | |
| 147 | employee_set es6; |
| 148 | employee_set_as_inserted& i3=get<as_inserted>(m&: es6); |
| 149 | i3=get<3>(m&: es2); |
| 150 | |
| 151 | BOOST_TEST(i3==get<3>(es2)); |
| 152 | |
| 153 | employee_set es7; |
| 154 | employee_set_randomly& i5=get<randomly>(m&: es7); |
| 155 | i5=get<5>(m&: es2); |
| 156 | |
| 157 | BOOST_TEST(i5==get<5>(es2)); |
| 158 | |
| 159 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)&&\ |
| 160 | !BOOST_WORKAROUND(BOOST_MSVC,==1800) /* MSVC 12.0 chokes on what follows */ |
| 161 | employee_set es8({{0,"Rose" ,40,4512},{1,"Mary" ,38,3345},{2,"Jo" ,25,7102}}); |
| 162 | employee_set es9; |
| 163 | es9={{0,"Rose" ,40,4512},{1,"Mary" ,38,3345},{2,"Jo" ,25,7102}, |
| 164 | {0,"Rose" ,40,4512}}; |
| 165 | |
| 166 | BOOST_TEST(es8.size()==3); |
| 167 | BOOST_TEST(es9==es8); |
| 168 | |
| 169 | es9.clear(); |
| 170 | get<0>(m&: es9)={{0,"Rose" ,40,4512},{1,"Mary" ,38,3345},{2,"Jo" ,25,7102}, |
| 171 | {0,"Rose" ,40,4512}}; |
| 172 | BOOST_TEST(es9==es8); |
| 173 | |
| 174 | es9.clear(); |
| 175 | get<0>(m&: es9)={{0,"Rose" ,40,4512},{2,"Jo" ,25,7102},{1,"Mary" ,38,3345}}; |
| 176 | BOOST_TEST(es9==es8); |
| 177 | |
| 178 | es9.clear(); |
| 179 | get<1>(m&: es9)={{1,"Mary" ,38,3345},{0,"Rose" ,40,4512},{2,"Jo" ,25,7102}, |
| 180 | {0,"Rose" ,40,4512}}; |
| 181 | BOOST_TEST(es9==es8); |
| 182 | |
| 183 | es9.clear(); |
| 184 | get<2>(m&: es9)={{2,"Jo" ,25,7102},{0,"Rose" ,40,4512},{1,"Mary" ,38,3345}}; |
| 185 | BOOST_TEST(es9==es8); |
| 186 | |
| 187 | es9.clear(); |
| 188 | get<3>(m&: es9)={{0,"Rose" ,40,4512},{1,"Mary" ,38,3345},{1,"Mary" ,38,3345}, |
| 189 | {2,"Jo" ,25,7102}}; |
| 190 | BOOST_TEST(es9==es8); |
| 191 | |
| 192 | es9.clear(); |
| 193 | get<4>(m&: es9)={{1,"Mary" ,38,3345},{2,"Jo" ,25,7102},{0,"Rose" ,40,4512}}; |
| 194 | BOOST_TEST(es9==es8); |
| 195 | |
| 196 | es9.clear(); |
| 197 | get<5>(m&: es9)={{1,"Mary" ,38,3345},{2,"Jo" ,25,7102},{0,"Rose" ,40,4512}, |
| 198 | {2,"Jo" ,25,7102}}; |
| 199 | BOOST_TEST(es9==es8); |
| 200 | #endif |
| 201 | |
| 202 | employee_set es10(produce_employee_set()),es11(produce_employee_set()); |
| 203 | BOOST_TEST(es10==es11); |
| 204 | |
| 205 | employee_set es12(boost::move(t&: es10)); |
| 206 | BOOST_TEST(es10.empty()); |
| 207 | BOOST_TEST(es11==es12); |
| 208 | |
| 209 | es10=boost::move(t&: es12); |
| 210 | BOOST_TEST(es12.empty()); |
| 211 | BOOST_TEST(es11==es10); |
| 212 | |
| 213 | std::list<employee> l; |
| 214 | l.push_back(x: employee(3,"Anna" ,31,5388)); |
| 215 | l.push_back(x: employee(1,"Rachel" ,27,9012)); |
| 216 | l.push_back(x: employee(2,"Agatha" ,40,1520)); |
| 217 | |
| 218 | employee_set es13(l.begin(),l.end()); |
| 219 | |
| 220 | l.sort(); |
| 221 | |
| 222 | BOOST_TEST(es13.size()==l.size()&& |
| 223 | std::equal(es13.begin(),es13.end(),l.begin())); |
| 224 | |
| 225 | test_assign<multi_index_container<int,indexed_by<sequenced<> > > >(); |
| 226 | test_integral_assign< |
| 227 | multi_index_container<int,indexed_by<sequenced<> > > >(); |
| 228 | |
| 229 | test_assign<multi_index_container<int,indexed_by<random_access<> > > >(); |
| 230 | test_integral_assign< |
| 231 | multi_index_container<int,indexed_by<random_access<> > > >(); |
| 232 | |
| 233 | /* Testcase for problem described at http://www.boost.org/doc/html/move/ |
| 234 | * emulation_limitations.html#move.emulation_limitations.assignment_operator |
| 235 | */ |
| 236 | |
| 237 | holder h((holder())); |
| 238 | h=holder(); |
| 239 | |
| 240 | #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) |
| 241 | { |
| 242 | /* testcase for https://svn.boost.org/trac10/ticket/13518 */ |
| 243 | |
| 244 | multi_index_container<int> x={}; |
| 245 | } |
| 246 | #endif |
| 247 | |
| 248 | typedef small_allocator<int> small_alloc; |
| 249 | typedef multi_index_container< |
| 250 | int, |
| 251 | indexed_by< |
| 252 | ordered_unique<identity<int> >, |
| 253 | ranked_unique<identity<int> >, |
| 254 | hashed_unique<identity<int> >, |
| 255 | sequenced<>, |
| 256 | random_access<> |
| 257 | >, |
| 258 | small_alloc |
| 259 | > small_container; |
| 260 | typedef small_container::nth_index<0>::type small_container_0; |
| 261 | typedef small_container::nth_index<1>::type small_container_1; |
| 262 | typedef small_container::nth_index<2>::type small_container_2; |
| 263 | typedef small_container::nth_index<3>::type small_container_3; |
| 264 | typedef small_container::nth_index<4>::type small_container_4; |
| 265 | |
| 266 | BOOST_STATIC_ASSERT(( |
| 267 | boost::is_same<small_container::size_type,small_alloc::size_type>::value)); |
| 268 | BOOST_STATIC_ASSERT(( |
| 269 | boost::is_same< |
| 270 | small_container::difference_type,small_alloc::difference_type>::value)); |
| 271 | BOOST_STATIC_ASSERT(( |
| 272 | boost::is_same<small_container_0::size_type,small_alloc::size_type>::value)); |
| 273 | BOOST_STATIC_ASSERT(( |
| 274 | boost::is_same< |
| 275 | small_container_0::difference_type,small_alloc::difference_type>::value)); |
| 276 | BOOST_STATIC_ASSERT(( |
| 277 | boost::is_same<small_container_1::size_type,small_alloc::size_type>::value)); |
| 278 | BOOST_STATIC_ASSERT(( |
| 279 | boost::is_same< |
| 280 | small_container_1::difference_type,small_alloc::difference_type>::value)); |
| 281 | BOOST_STATIC_ASSERT(( |
| 282 | boost::is_same<small_container_2::size_type,small_alloc::size_type>::value)); |
| 283 | BOOST_STATIC_ASSERT(( |
| 284 | boost::is_same< |
| 285 | small_container_2::difference_type,small_alloc::difference_type>::value)); |
| 286 | BOOST_STATIC_ASSERT(( |
| 287 | boost::is_same<small_container_3::size_type,small_alloc::size_type>::value)); |
| 288 | BOOST_STATIC_ASSERT(( |
| 289 | boost::is_same< |
| 290 | small_container_3::difference_type,small_alloc::difference_type>::value)); |
| 291 | BOOST_STATIC_ASSERT(( |
| 292 | boost::is_same<small_container_4::size_type,small_alloc::size_type>::value)); |
| 293 | BOOST_STATIC_ASSERT(( |
| 294 | boost::is_same< |
| 295 | small_container_4::difference_type,small_alloc::difference_type>::value)); |
| 296 | |
| 297 | small_container sc; |
| 298 | small_container_0& sc0=sc.get<0>(); |
| 299 | small_container_1& sc1=sc.get<1>(); |
| 300 | small_container_2& sc2=sc.get<2>(); |
| 301 | small_container_3& sc3=sc.get<3>(); |
| 302 | small_container_4& sc4=sc.get<4>(); |
| 303 | small_alloc::size_type s, |
| 304 | ms=(small_alloc::size_type)(-1); |
| 305 | |
| 306 | sc.insert(x: 0); |
| 307 | |
| 308 | s=sc0.size(); |
| 309 | BOOST_TEST(sc0.max_size()<=ms); |
| 310 | s=sc0.erase(x: 1); |
| 311 | s=sc0.count(x: 0); |
| 312 | s=sc0.count(x: 0,comp: std::less<int>()); |
| 313 | |
| 314 | s=sc1.size(); |
| 315 | BOOST_TEST(sc1.max_size()<=ms); |
| 316 | s=sc1.erase(x: 1); |
| 317 | s=sc1.count(x: 0); |
| 318 | s=sc1.count(x: 0,comp: std::less<int>()); |
| 319 | (void)sc1.nth(n: s); |
| 320 | s=sc1.rank(position: sc1.begin()); |
| 321 | s=sc1.find_rank(x: 0); |
| 322 | s=sc1.find_rank(x: 0,comp: std::less<int>()); |
| 323 | s=sc1.lower_bound_rank(x: 0); |
| 324 | s=sc1.lower_bound_rank(x: 0,comp: std::less<int>()); |
| 325 | s=sc1.upper_bound_rank(x: 0); |
| 326 | s=sc1.upper_bound_rank(x: 0,comp: std::less<int>()); |
| 327 | s=sc1.equal_range_rank(x: 0).first; |
| 328 | s=sc1.equal_range_rank(x: 0).second; |
| 329 | s=sc1.range_rank(lower: unbounded,upper: unbounded).first; |
| 330 | s=sc1.range_rank(lower: unbounded,upper: unbounded).second; |
| 331 | |
| 332 | s=sc2.size(); |
| 333 | BOOST_TEST(sc2.max_size()<=ms); |
| 334 | s=sc2.erase(k: 1); |
| 335 | s=sc2.count(k: 0); |
| 336 | s=sc2.count(k: 0,hash: boost::hash<int>(),eq: std::equal_to<int>()); |
| 337 | s=sc2.bucket_count(); |
| 338 | BOOST_TEST(sc2.max_bucket_count()<=ms); |
| 339 | BOOST_TEST(sc2.bucket_size((small_alloc::size_type)(0))<=ms); |
| 340 | BOOST_TEST(sc2.bucket_size(0)<=ms); |
| 341 | (void)sc2.begin(n: 0); |
| 342 | (void)sc2.end(n: 0); |
| 343 | (void)sc2.cbegin(n: 0); |
| 344 | (void)sc2.cend(n: 0); |
| 345 | sc2.rehash(n: 2); |
| 346 | sc2.reserve(n: 2); |
| 347 | |
| 348 | s=sc3.size(); |
| 349 | BOOST_TEST(sc3.max_size()<=ms); |
| 350 | sc3.resize(n: 0); |
| 351 | sc3.resize(n: 0,x: 0); |
| 352 | sc3.assign(n: (small_alloc::size_type)(1),value: 0); |
| 353 | sc3.insert(position: sc3.begin(),n: (small_alloc::size_type)(0),x: 0); |
| 354 | |
| 355 | s=sc4.size(); |
| 356 | BOOST_TEST(sc4.max_size()<=ms); |
| 357 | BOOST_TEST(sc4.capacity()<=ms); |
| 358 | sc4.reserve(n: 0); |
| 359 | sc4.resize(n: 0); |
| 360 | sc4.resize(n: 0,x: 0); |
| 361 | sc4.assign(n: (small_alloc::size_type)(1),value: 0); |
| 362 | (void)sc4[0]; |
| 363 | (void)sc4.at(n: 0); |
| 364 | sc4.insert(position: sc4.begin(),n: (small_alloc::size_type)(0),x: 0); |
| 365 | } |
| 366 | |