1 2 // Copyright 2006-2009 Daniel James. 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #if !defined(BOOST_UNORDERED_EXCEPTION_TEST_OBJECTS_HEADER) 7 #define BOOST_UNORDERED_EXCEPTION_TEST_OBJECTS_HEADER 8 9 #include "../helpers/exception_test.hpp" 10 11 #include "../helpers/count.hpp" 12 #include "../helpers/fwd.hpp" 13 #include "../helpers/generators.hpp" 14 #include "../helpers/memory.hpp" 15 #include "./fwd.hpp" 16 #include <boost/limits.hpp> 17 #include <cstddef> 18 #include <new> 19 20 namespace test { 21 namespace exception { 22 class object; 23 class hash; 24 class equal_to; 25 template <class T> class allocator; 26 object generate(object const*, random_generator); 27 std::pair<object, object> generate( 28 std::pair<object, object> const*, random_generator); 29 30 struct true_type 31 { 32 enum 33 { 34 value = true 35 }; 36 }; 37 38 struct false_type 39 { 40 enum 41 { 42 value = false 43 }; 44 }; 45 46 class object : private counted_object 47 { 48 public: 49 int tag1_, tag2_; 50 object()51 explicit object() : tag1_(0), tag2_(0) 52 { 53 UNORDERED_SCOPE(object::object()) 54 { 55 UNORDERED_EPOINT("Mock object default constructor."); 56 } 57 } 58 object(int t1,int t2=0)59 explicit object(int t1, int t2 = 0) : tag1_(t1), tag2_(t2) 60 { 61 UNORDERED_SCOPE(object::object(int)) 62 { 63 UNORDERED_EPOINT("Mock object constructor by value."); 64 } 65 } 66 object(object const & x)67 object(object const& x) 68 : counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_) 69 { 70 UNORDERED_SCOPE(object::object(object)) 71 { 72 UNORDERED_EPOINT("Mock object copy constructor."); 73 } 74 } 75 ~object()76 ~object() 77 { 78 tag1_ = -1; 79 tag2_ = -1; 80 } 81 operator =(object const & x)82 object& operator=(object const& x) 83 { 84 UNORDERED_SCOPE(object::operator=(object)) 85 { 86 tag1_ = x.tag1_; 87 UNORDERED_EPOINT("Mock object assign operator 1."); 88 tag2_ = x.tag2_; 89 // UNORDERED_EPOINT("Mock object assign operator 2."); 90 } 91 return *this; 92 } 93 operator ==(object const & x1,object const & x2)94 friend bool operator==(object const& x1, object const& x2) 95 { 96 UNORDERED_SCOPE(operator==(object, object)) 97 { 98 UNORDERED_EPOINT("Mock object equality operator."); 99 } 100 101 return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_; 102 } 103 operator !=(object const & x1,object const & x2)104 friend bool operator!=(object const& x1, object const& x2) 105 { 106 UNORDERED_SCOPE(operator!=(object, object)) 107 { 108 UNORDERED_EPOINT("Mock object inequality operator."); 109 } 110 111 return !(x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_); 112 } 113 114 // None of the last few functions are used by the unordered associative 115 // containers - so there aren't any exception points. operator <(object const & x1,object const & x2)116 friend bool operator<(object const& x1, object const& x2) 117 { 118 return x1.tag1_ < x2.tag1_ || 119 (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_); 120 } 121 generate(object const *,random_generator g)122 friend object generate(object const*, random_generator g) 123 { 124 int* x = 0; 125 return object(::test::generate(x, g), ::test::generate(x, g)); 126 } 127 operator <<(std::ostream & out,object const & o)128 friend std::ostream& operator<<(std::ostream& out, object const& o) 129 { 130 return out << "(" << o.tag1_ << "," << o.tag2_ << ")"; 131 } 132 }; 133 generate(std::pair<object,object> const *,random_generator g)134 std::pair<object, object> generate( 135 std::pair<object, object> const*, random_generator g) 136 { 137 int* x = 0; 138 return std::make_pair( 139 object(::test::generate(x, g), ::test::generate(x, g)), 140 object(::test::generate(x, g), ::test::generate(x, g))); 141 } 142 143 class hash 144 { 145 int tag_; 146 147 public: hash(int t=0)148 hash(int t = 0) : tag_(t) 149 { 150 UNORDERED_SCOPE(hash::object()) 151 { 152 UNORDERED_EPOINT("Mock hash default constructor."); 153 } 154 } 155 hash(hash const & x)156 hash(hash const& x) : tag_(x.tag_) 157 { 158 UNORDERED_SCOPE(hash::hash(hash)) 159 { 160 UNORDERED_EPOINT("Mock hash copy constructor."); 161 } 162 } 163 operator =(hash const & x)164 hash& operator=(hash const& x) 165 { 166 UNORDERED_SCOPE(hash::operator=(hash)) 167 { 168 UNORDERED_EPOINT("Mock hash assign operator 1."); 169 tag_ = x.tag_; 170 UNORDERED_EPOINT("Mock hash assign operator 2."); 171 } 172 return *this; 173 } 174 operator ()(object const & x) const175 std::size_t operator()(object const& x) const 176 { 177 UNORDERED_SCOPE(hash::operator()(object)) 178 { 179 UNORDERED_EPOINT("Mock hash function."); 180 } 181 182 return hash_impl(x); 183 } 184 operator ()(std::pair<object,object> const & x) const185 std::size_t operator()(std::pair<object, object> const& x) const 186 { 187 UNORDERED_SCOPE(hash::operator()(std::pair<object, object>)) 188 { 189 UNORDERED_EPOINT("Mock hash pair function."); 190 } 191 192 return hash_impl(x.first) * 193ul + hash_impl(x.second) * 97ul + 29ul; 193 } 194 hash_impl(object const & x) const195 std::size_t hash_impl(object const& x) const 196 { 197 int result; 198 switch (tag_) { 199 case 1: 200 result = x.tag1_; 201 break; 202 case 2: 203 result = x.tag2_; 204 break; 205 default: 206 result = x.tag1_ + x.tag2_; 207 } 208 return static_cast<std::size_t>(result); 209 } 210 operator ==(hash const & x1,hash const & x2)211 friend bool operator==(hash const& x1, hash const& x2) 212 { 213 UNORDERED_SCOPE(operator==(hash, hash)) 214 { 215 UNORDERED_EPOINT("Mock hash equality function."); 216 } 217 return x1.tag_ == x2.tag_; 218 } 219 operator !=(hash const & x1,hash const & x2)220 friend bool operator!=(hash const& x1, hash const& x2) 221 { 222 UNORDERED_SCOPE(hash::operator!=(hash, hash)) 223 { 224 UNORDERED_EPOINT("Mock hash inequality function."); 225 } 226 return x1.tag_ != x2.tag_; 227 } 228 }; 229 230 class less 231 { 232 int tag_; 233 234 public: less(int t=0)235 less(int t = 0) : tag_(t) {} 236 less(less const & x)237 less(less const& x) : tag_(x.tag_) {} 238 operator ()(object const & x1,object const & x2) const239 bool operator()(object const& x1, object const& x2) const 240 { 241 return less_impl(x1, x2); 242 } 243 operator ()(std::pair<object,object> const & x1,std::pair<object,object> const & x2) const244 bool operator()(std::pair<object, object> const& x1, 245 std::pair<object, object> const& x2) const 246 { 247 if (less_impl(x1.first, x2.first)) { 248 return true; 249 } 250 if (!less_impl(x1.first, x2.first)) { 251 return false; 252 } 253 return less_impl(x1.second, x2.second); 254 } 255 less_impl(object const & x1,object const & x2) const256 bool less_impl(object const& x1, object const& x2) const 257 { 258 switch (tag_) { 259 case 1: 260 return x1.tag1_ < x2.tag1_; 261 case 2: 262 return x1.tag2_ < x2.tag2_; 263 default: 264 return x1 < x2; 265 } 266 } 267 operator ==(less const & x1,less const & x2)268 friend bool operator==(less const& x1, less const& x2) 269 { 270 return x1.tag_ == x2.tag_; 271 } 272 operator !=(less const & x1,less const & x2)273 friend bool operator!=(less const& x1, less const& x2) 274 { 275 return x1.tag_ != x2.tag_; 276 } 277 }; 278 279 class equal_to 280 { 281 int tag_; 282 283 public: equal_to(int t=0)284 equal_to(int t = 0) : tag_(t) 285 { 286 UNORDERED_SCOPE(equal_to::equal_to()) 287 { 288 UNORDERED_EPOINT("Mock equal_to default constructor."); 289 } 290 } 291 equal_to(equal_to const & x)292 equal_to(equal_to const& x) : tag_(x.tag_) 293 { 294 UNORDERED_SCOPE(equal_to::equal_to(equal_to)) 295 { 296 UNORDERED_EPOINT("Mock equal_to copy constructor."); 297 } 298 } 299 operator =(equal_to const & x)300 equal_to& operator=(equal_to const& x) 301 { 302 UNORDERED_SCOPE(equal_to::operator=(equal_to)) 303 { 304 UNORDERED_EPOINT("Mock equal_to assign operator 1."); 305 tag_ = x.tag_; 306 UNORDERED_EPOINT("Mock equal_to assign operator 2."); 307 } 308 return *this; 309 } 310 operator ()(object const & x1,object const & x2) const311 bool operator()(object const& x1, object const& x2) const 312 { 313 UNORDERED_SCOPE(equal_to::operator()(object, object)) 314 { 315 UNORDERED_EPOINT("Mock equal_to function."); 316 } 317 318 return equal_impl(x1, x2); 319 } 320 operator ()(std::pair<object,object> const & x1,std::pair<object,object> const & x2) const321 bool operator()(std::pair<object, object> const& x1, 322 std::pair<object, object> const& x2) const 323 { 324 UNORDERED_SCOPE(equal_to::operator()( 325 std::pair<object, object>, std::pair<object, object>)) 326 { 327 UNORDERED_EPOINT("Mock equal_to function."); 328 } 329 330 return equal_impl(x1.first, x2.first) && 331 equal_impl(x1.second, x2.second); 332 } 333 equal_impl(object const & x1,object const & x2) const334 bool equal_impl(object const& x1, object const& x2) const 335 { 336 switch (tag_) { 337 case 1: 338 return x1.tag1_ == x2.tag1_; 339 case 2: 340 return x1.tag2_ == x2.tag2_; 341 default: 342 return x1 == x2; 343 } 344 } 345 operator ==(equal_to const & x1,equal_to const & x2)346 friend bool operator==(equal_to const& x1, equal_to const& x2) 347 { 348 UNORDERED_SCOPE(operator==(equal_to, equal_to)) 349 { 350 UNORDERED_EPOINT("Mock equal_to equality function."); 351 } 352 return x1.tag_ == x2.tag_; 353 } 354 operator !=(equal_to const & x1,equal_to const & x2)355 friend bool operator!=(equal_to const& x1, equal_to const& x2) 356 { 357 UNORDERED_SCOPE(operator!=(equal_to, equal_to)) 358 { 359 UNORDERED_EPOINT("Mock equal_to inequality function."); 360 } 361 return x1.tag_ != x2.tag_; 362 } 363 create_compare(equal_to x)364 friend less create_compare(equal_to x) { return less(x.tag_); } 365 }; 366 367 template <class T> class allocator 368 { 369 public: 370 int tag_; 371 typedef std::size_t size_type; 372 typedef std::ptrdiff_t difference_type; 373 typedef T* pointer; 374 typedef T const* const_pointer; 375 typedef T& reference; 376 typedef T const& const_reference; 377 typedef T value_type; 378 379 template <class U> struct rebind 380 { 381 typedef allocator<U> other; 382 }; 383 allocator(int t=0)384 explicit allocator(int t = 0) : tag_(t) 385 { 386 UNORDERED_SCOPE(allocator::allocator()) 387 { 388 UNORDERED_EPOINT("Mock allocator default constructor."); 389 } 390 test::detail::tracker.allocator_ref(); 391 } 392 allocator(allocator<Y> const & x)393 template <class Y> allocator(allocator<Y> const& x) : tag_(x.tag_) 394 { 395 test::detail::tracker.allocator_ref(); 396 } 397 allocator(allocator const & x)398 allocator(allocator const& x) : tag_(x.tag_) 399 { 400 test::detail::tracker.allocator_ref(); 401 } 402 ~allocator()403 ~allocator() { test::detail::tracker.allocator_unref(); } 404 operator =(allocator const & x)405 allocator& operator=(allocator const& x) 406 { 407 tag_ = x.tag_; 408 return *this; 409 } 410 411 // If address throws, then it can't be used in erase or the 412 // destructor, which is very limiting. I need to check up on 413 // this. 414 address(reference r)415 pointer address(reference r) 416 { 417 // UNORDERED_SCOPE(allocator::address(reference)) { 418 // UNORDERED_EPOINT("Mock allocator address function."); 419 //} 420 return pointer(&r); 421 } 422 address(const_reference r)423 const_pointer address(const_reference r) 424 { 425 // UNORDERED_SCOPE(allocator::address(const_reference)) { 426 // UNORDERED_EPOINT("Mock allocator const address function."); 427 //} 428 return const_pointer(&r); 429 } 430 allocate(size_type n)431 pointer allocate(size_type n) 432 { 433 T* ptr = 0; 434 UNORDERED_SCOPE(allocator::allocate(size_type)) 435 { 436 UNORDERED_EPOINT("Mock allocator allocate function."); 437 438 using namespace std; 439 ptr = (T*)malloc(n * sizeof(T)); 440 if (!ptr) 441 throw std::bad_alloc(); 442 } 443 test::detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); 444 return pointer(ptr); 445 446 // return pointer(static_cast<T*>(::operator new(n * sizeof(T)))); 447 } 448 allocate(size_type n,void const *)449 pointer allocate(size_type n, void const*) 450 { 451 T* ptr = 0; 452 UNORDERED_SCOPE(allocator::allocate(size_type, const_pointer)) 453 { 454 UNORDERED_EPOINT("Mock allocator allocate function."); 455 456 using namespace std; 457 ptr = (T*)malloc(n * sizeof(T)); 458 if (!ptr) 459 throw std::bad_alloc(); 460 } 461 test::detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); 462 return pointer(ptr); 463 464 // return pointer(static_cast<T*>(::operator new(n * sizeof(T)))); 465 } 466 deallocate(pointer p,size_type n)467 void deallocate(pointer p, size_type n) 468 { 469 //::operator delete((void*) p); 470 if (p) { 471 test::detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_); 472 using namespace std; 473 free(p); 474 } 475 } 476 construct(pointer p,T const & t)477 void construct(pointer p, T const& t) 478 { 479 UNORDERED_SCOPE(allocator::construct(T*, T)) 480 { 481 UNORDERED_EPOINT("Mock allocator construct function."); 482 new (p) T(t); 483 } 484 test::detail::tracker.track_construct((void*)p, sizeof(T), tag_); 485 } 486 487 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) construct(T * p,BOOST_FWD_REF (Args)...args)488 template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) 489 { 490 UNORDERED_SCOPE(allocator::construct(pointer, BOOST_FWD_REF(Args)...)) 491 { 492 UNORDERED_EPOINT("Mock allocator construct function."); 493 new (p) T(boost::forward<Args>(args)...); 494 } 495 test::detail::tracker.track_construct((void*)p, sizeof(T), tag_); 496 } 497 #endif 498 destroy(T * p)499 void destroy(T* p) 500 { 501 test::detail::tracker.track_destroy((void*)p, sizeof(T), tag_); 502 p->~T(); 503 } 504 max_size() const505 size_type max_size() const 506 { 507 UNORDERED_SCOPE(allocator::construct(pointer, T)) 508 { 509 UNORDERED_EPOINT("Mock allocator max_size function."); 510 } 511 return (std::numeric_limits<std::size_t>::max)(); 512 } 513 514 typedef true_type propagate_on_container_copy_assignment; 515 typedef true_type propagate_on_container_move_assignment; 516 typedef true_type propagate_on_container_swap; 517 }; 518 swap(allocator<T> & x,allocator<T> & y)519 template <class T> void swap(allocator<T>& x, allocator<T>& y) 520 { 521 std::swap(x.tag_, y.tag_); 522 } 523 524 // It's pretty much impossible to write a compliant swap when these 525 // two can throw. So they don't. 526 527 template <class T> operator ==(allocator<T> const & x,allocator<T> const & y)528 inline bool operator==(allocator<T> const& x, allocator<T> const& y) 529 { 530 // UNORDERED_SCOPE(operator==(allocator, allocator)) { 531 // UNORDERED_EPOINT("Mock allocator equality operator."); 532 //} 533 return x.tag_ == y.tag_; 534 } 535 536 template <class T> operator !=(allocator<T> const & x,allocator<T> const & y)537 inline bool operator!=(allocator<T> const& x, allocator<T> const& y) 538 { 539 // UNORDERED_SCOPE(operator!=(allocator, allocator)) { 540 // UNORDERED_EPOINT("Mock allocator inequality operator."); 541 //} 542 return x.tag_ != y.tag_; 543 } 544 545 template <class T> class allocator2 546 { 547 public: 548 int tag_; 549 typedef std::size_t size_type; 550 typedef std::ptrdiff_t difference_type; 551 typedef T* pointer; 552 typedef T const* const_pointer; 553 typedef T& reference; 554 typedef T const& const_reference; 555 typedef T value_type; 556 557 template <class U> struct rebind 558 { 559 typedef allocator2<U> other; 560 }; 561 allocator2(int t=0)562 explicit allocator2(int t = 0) : tag_(t) 563 { 564 UNORDERED_SCOPE(allocator2::allocator2()) 565 { 566 UNORDERED_EPOINT("Mock allocator2 default constructor."); 567 } 568 test::detail::tracker.allocator_ref(); 569 } 570 allocator2(allocator<T> const & x)571 allocator2(allocator<T> const& x) : tag_(x.tag_) 572 { 573 test::detail::tracker.allocator_ref(); 574 } 575 allocator2(allocator2<Y> const & x)576 template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_) 577 { 578 test::detail::tracker.allocator_ref(); 579 } 580 allocator2(allocator2 const & x)581 allocator2(allocator2 const& x) : tag_(x.tag_) 582 { 583 test::detail::tracker.allocator_ref(); 584 } 585 ~allocator2()586 ~allocator2() { test::detail::tracker.allocator_unref(); } 587 operator =(allocator2 const &)588 allocator2& operator=(allocator2 const&) { return *this; } 589 590 // If address throws, then it can't be used in erase or the 591 // destructor, which is very limiting. I need to check up on 592 // this. 593 address(reference r)594 pointer address(reference r) 595 { 596 // UNORDERED_SCOPE(allocator2::address(reference)) { 597 // UNORDERED_EPOINT("Mock allocator2 address function."); 598 //} 599 return pointer(&r); 600 } 601 address(const_reference r)602 const_pointer address(const_reference r) 603 { 604 // UNORDERED_SCOPE(allocator2::address(const_reference)) { 605 // UNORDERED_EPOINT("Mock allocator2 const address function."); 606 //} 607 return const_pointer(&r); 608 } 609 allocate(size_type n)610 pointer allocate(size_type n) 611 { 612 T* ptr = 0; 613 UNORDERED_SCOPE(allocator2::allocate(size_type)) 614 { 615 UNORDERED_EPOINT("Mock allocator2 allocate function."); 616 617 using namespace std; 618 ptr = (T*)malloc(n * sizeof(T)); 619 if (!ptr) 620 throw std::bad_alloc(); 621 } 622 test::detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); 623 return pointer(ptr); 624 625 // return pointer(static_cast<T*>(::operator new(n * sizeof(T)))); 626 } 627 allocate(size_type n,void const *)628 pointer allocate(size_type n, void const*) 629 { 630 T* ptr = 0; 631 UNORDERED_SCOPE(allocator2::allocate(size_type, const_pointer)) 632 { 633 UNORDERED_EPOINT("Mock allocator2 allocate function."); 634 635 using namespace std; 636 ptr = (T*)malloc(n * sizeof(T)); 637 if (!ptr) 638 throw std::bad_alloc(); 639 } 640 test::detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); 641 return pointer(ptr); 642 643 // return pointer(static_cast<T*>(::operator new(n * sizeof(T)))); 644 } 645 deallocate(pointer p,size_type n)646 void deallocate(pointer p, size_type n) 647 { 648 //::operator delete((void*) p); 649 if (p) { 650 test::detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_); 651 using namespace std; 652 free(p); 653 } 654 } 655 construct(pointer p,T const & t)656 void construct(pointer p, T const& t) 657 { 658 UNORDERED_SCOPE(allocator2::construct(T*, T)) 659 { 660 UNORDERED_EPOINT("Mock allocator2 construct function."); 661 new (p) T(t); 662 } 663 test::detail::tracker.track_construct((void*)p, sizeof(T), tag_); 664 } 665 666 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) construct(T * p,BOOST_FWD_REF (Args)...args)667 template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) 668 { 669 UNORDERED_SCOPE(allocator2::construct(pointer, BOOST_FWD_REF(Args)...)) 670 { 671 UNORDERED_EPOINT("Mock allocator2 construct function."); 672 new (p) T(boost::forward<Args>(args)...); 673 } 674 test::detail::tracker.track_construct((void*)p, sizeof(T), tag_); 675 } 676 #endif 677 destroy(T * p)678 void destroy(T* p) 679 { 680 test::detail::tracker.track_destroy((void*)p, sizeof(T), tag_); 681 p->~T(); 682 } 683 max_size() const684 size_type max_size() const 685 { 686 UNORDERED_SCOPE(allocator2::construct(pointer, T)) 687 { 688 UNORDERED_EPOINT("Mock allocator2 max_size function."); 689 } 690 return (std::numeric_limits<std::size_t>::max)(); 691 } 692 693 typedef false_type propagate_on_container_copy_assignment; 694 typedef false_type propagate_on_container_move_assignment; 695 typedef false_type propagate_on_container_swap; 696 }; 697 swap(allocator2<T> & x,allocator2<T> & y)698 template <class T> void swap(allocator2<T>& x, allocator2<T>& y) 699 { 700 std::swap(x.tag_, y.tag_); 701 } 702 703 // It's pretty much impossible to write a compliant swap when these 704 // two can throw. So they don't. 705 706 template <class T> operator ==(allocator2<T> const & x,allocator2<T> const & y)707 inline bool operator==(allocator2<T> const& x, allocator2<T> const& y) 708 { 709 // UNORDERED_SCOPE(operator==(allocator2, allocator2)) { 710 // UNORDERED_EPOINT("Mock allocator2 equality operator."); 711 //} 712 return x.tag_ == y.tag_; 713 } 714 715 template <class T> operator !=(allocator2<T> const & x,allocator2<T> const & y)716 inline bool operator!=(allocator2<T> const& x, allocator2<T> const& y) 717 { 718 // UNORDERED_SCOPE(operator!=(allocator2, allocator2)) { 719 // UNORDERED_EPOINT("Mock allocator2 inequality operator."); 720 //} 721 return x.tag_ != y.tag_; 722 } 723 } 724 } 725 726 namespace test { 727 template <typename X> struct equals_to_compare; 728 template <> struct equals_to_compare<test::exception::equal_to> 729 { 730 typedef test::exception::less type; 731 }; 732 } 733 734 // Workaround for ADL deficient compilers 735 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) 736 namespace test { generate(test::exception::object const * x,random_generator g)737 test::exception::object generate( 738 test::exception::object const* x, random_generator g) 739 { 740 return test::exception::generate(x, g); 741 } 742 generate(std::pair<test::exception::object,test::exception::object> const * x,random_generator g)743 std::pair<test::exception::object, test::exception::object> generate( 744 std::pair<test::exception::object, test::exception::object> const* x, 745 random_generator g) 746 { 747 return test::exception::generate(x, g); 748 } 749 } 750 #endif 751 752 #endif 753