1 // Copyright (c) 2001-2007 Max-Planck-Institute Saarbruecken (Germany). 2 // All rights reserved. 3 // 4 // This file is part of CGAL (www.cgal.org) 5 // 6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/STL_Extension/include/CGAL/Handle_with_policy.h $ 7 // $Id: Handle_with_policy.h 0d66e19 2020-07-24T17:05:10+02:00 Mael Rouxel-Labbé 8 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial 9 // 10 // Author(s) : Michael Seel <seel@mpi-inf.mpg.de> 11 // Arno Eigenwillig <arno@mpi-inf.mpg.de> 12 // Lutz Kettner <kettner@mpi-inf.mpg.de> 13 14 #ifndef CGAL_HANDLE_WITH_POLICY_H 15 #define CGAL_HANDLE_WITH_POLICY_H 16 17 #include <CGAL/basic.h> 18 #include <CGAL/memory.h> 19 #include <CGAL/type_traits.h> 20 21 #include <CGAL/assertions.h> 22 #include <CGAL/use.h> 23 24 #include <boost/mpl/if.hpp> 25 26 #include <cstddef> 27 28 #ifdef CGAL_USE_LEDA 29 # include <LEDA/system/memory.h> 30 #endif 31 32 33 34 namespace CGAL { 35 36 /*! \brief <tt>\#include <CGAL/Handle_with_policy.h></tt> for handles with policy 37 parameter for reference counting and union-find strategy. Uses 38 \c LEDA_MEMORY if available. 39 40 There are two fundamentally different usages of this base class: 41 42 - with a single representation class. In this case the handle 43 manages allocation and deallocation and the type \c T can 44 be an arbitrary type---the handle adds the necessary reference 45 counter internally. 46 47 - with a hierarchy of representation classes. Type \c T will be 48 the common base class of this hierarchy and it has to be derived 49 itself from a specific base class, which can be accessed directly 50 or generically from the policy class. The allocator in the 51 handle will not be used in this scenario, since the handle class 52 does not allocate any representations. Instead, the handle class 53 derived from this handle base class is allocating the different 54 representations with the \c new operator. In this case, 55 the allocator in the base class of \c T is used. 56 57 We give an example for each usage. See also the documentation 58 of \c Handle_with_policy. 59 60 \b Example 61 62 We use a single representation class to store an integer. The second 63 constructor makes use of one of the forwarding template constructors 64 that simply forward their parameter list to the representation 65 constructors. They exist for up to ten parameters. The third 66 constructor illustrates how the \c USE_WITH_INITIALIZE_WITH can be 67 used. It is useful if extensive computations are necessary before the 68 representation can be created. 69 70 \code 71 struct Int_rep { 72 int val; 73 Int_rep( int i = 0) : val(i) {} 74 Int_rep( int i, int j) : val(i+j) {} 75 Int_rep( int i, int j, int k) : val(i+j+k) {} 76 }; 77 78 template < class Unify> 79 struct Int_t : public Handle_with_policy< Int_rep, Unify > { 80 typedef Handle_with_policy< Int_rep, Unify > Base; 81 Int_t( int i = 0) : Base( i) {} 82 Int_t( int i, int j) : Base( i, j) {} // template constructors 83 Int_t( int i, int j, int k) : Base( Base::USE_WITH_INITIALIZE_WITH) { 84 initialize_with( i, j + k); 85 } 86 int value() const { return ptr()->val; } 87 void set_value( int i) { 88 copy_on_write(); 89 ptr()->val = i; 90 } 91 bool operator==( const Int_t<Unify>& i) const { 92 bool equal = (value() == i.value()); 93 if ( equal) 94 Base::unify(i); 95 return equal; 96 } 97 }; 98 \endcode 99 100 \b Example 101 102 We use a class hierarchy of two representation classes: one base class 103 for representing one integer, and a derived class to represent an 104 additional integer. To also added virtual get and set functions to 105 make this example similar to the one above. 106 107 We use the generic solution to pick the base class for \c Int_vrep 108 from the policy class. So all representations are class templates with 109 a policy and an allocator as parameter and the handle class 110 instantiates them. If this flexibility is not needed, one could derive 111 directly from the appropriate base class, i.e., \c 112 ::CGAL::Reference_counted_hierarchy<Alloc> or \c 113 ::CGAL::Reference_counted_hierarchy_with_union<Alloc>. \c Alloc is an 114 allocator of \c char's here. 115 116 \code 117 template <class Policy, class Alloc> 118 struct Int_vrep : public Policy::Hierarchy_base< Alloc>::Type { 119 int val; 120 virtual ::CGAL::Reference_counted_hierarchy<Alloc>* clone() { 121 return new Int_vrep( *this); 122 } 123 virtual int get_val() const { return val; } 124 virtual void set_val( int i) { val = i; } 125 Int_vrep( int i = 0) : val(i) {} 126 }; 127 128 template <class Policy, class Alloc> 129 struct Int_vrep2 : public Int_vrep<Policy,Alloc> { 130 int val2; 131 virtual ::CGAL::Reference_counted_hierarchy<Alloc>* clone() { 132 return new Int_vrep2( *this); 133 } 134 virtual int get_val() const { return val + val2; } 135 virtual void set_val( int i) { val = i - val2; } 136 Int_vrep2( int i, int j) : Int_vrep<Policy,Alloc>(i), val2(j) {} 137 }; 138 139 template < class Unify, class Alloc = CGAL_ALLOCATOR(char) > 140 struct Int_vt : public Handle_with_policy< Int_vrep<Unify,Alloc>, Unify > { 141 typedef Handle_with_policy< Int_vrep<Unify,Alloc>, Unify > Base; 142 Int_vt( int i = 0) : Base( new Int_vrep<Unify,Alloc>(i)) {} 143 Int_vt( int i, int j) : Base( new Int_vrep2<Unify,Alloc>(i,j)) {} 144 145 int value() const { return ptr()->get_val(); } 146 void set_value( int i) { 147 copy_on_write(); 148 ptr()->set_val(i); 149 } 150 bool operator==( const Int_vt<Unify>& i) const { 151 bool equal = (value() == i.value()); 152 if ( equal) 153 Base::unify(i); 154 return equal; 155 } 156 }; 157 \endcode 158 159 */ 160 //@{ 161 162 // Forward declarations of HandlePolicy classes 163 class Handle_policy_in_place; 164 class Handle_policy_no_union; 165 class Handle_policy_union; 166 class Handle_policy_union_and_reset; 167 168 // Reference counted representation 169 // ================================ 170 171 //! the base class for bodies of reference counted representations \c T. 172 template <class T_> 173 class Reference_counted { 174 public: 175 typedef T_ rep_type; 176 typedef Reference_counted<rep_type> Self; 177 typedef rep_type* Rep_pointer; 178 private: 179 mutable unsigned int count; // reference counter 180 rep_type rep; 181 public: Reference_counted()182 Reference_counted() : count(1) {} Reference_counted(const rep_type & t)183 Reference_counted( const rep_type& t) : count(1), rep(t) {} Reference_counted(const Self & r)184 Reference_counted( const Self& r) : count(1), rep(r.rep) {} 185 clear()186 void clear() { rep = rep_type(); } base_ptr()187 Rep_pointer base_ptr() { return &rep; } add_reference()188 void add_reference() { ++count; } remove_reference()189 void remove_reference() { --count; } is_shared()190 bool is_shared() const { return count > 1; } union_size()191 int union_size() const { return 1+count; } add_union_size(int)192 void add_union_size(int) {} 193 }; 194 195 /*!\brief 196 * Base class for bodies of reference counted representations \c T 197 * with a forwarding pointer for identical representations. 198 */ 199 template <class T_> 200 class Reference_counted_with_forwarding { 201 public: 202 typedef T_ rep_type; 203 typedef Reference_counted_with_forwarding<rep_type> Self; 204 typedef rep_type* Rep_pointer; 205 friend class Handle_policy_union; 206 friend class Handle_policy_union_and_reset; 207 private: 208 mutable unsigned int count; // reference counter 209 mutable Self* next; // forwarding pointer to valid rep or 0 210 mutable int u_size; // union set size incl this rep and its handle 211 mutable rep_type rep; 212 public: Reference_counted_with_forwarding()213 Reference_counted_with_forwarding() 214 : count(1), next(0), u_size(2) {} Reference_counted_with_forwarding(const rep_type & t)215 Reference_counted_with_forwarding( const rep_type& t) 216 : count(1), next(0), u_size(2), rep(t) {} Reference_counted_with_forwarding(const Self & r)217 Reference_counted_with_forwarding( const Self& r) 218 : count(1), next(0), u_size(2), rep(r.rep) {} 219 clear()220 void clear() { rep = rep_type(); } base_ptr()221 Rep_pointer base_ptr() { return &rep; } add_reference()222 void add_reference() { ++count; } remove_reference()223 void remove_reference() { --count; } is_shared()224 bool is_shared() const { return count > 1; } is_forwarding()225 bool is_forwarding() const { return next != 0; } union_size()226 int union_size() const { return u_size; } add_union_size(int a)227 void add_union_size(int a) { 228 CGAL_precondition( u_size + a > 0); 229 u_size += a; 230 } 231 }; 232 233 234 struct Reference_counted_hierarchy_base {}; 235 236 237 /*!\brief Base class for reference counted representations with a class 238 * hierarchy of different representations. Needs an allocator for \c char's 239 * as parameter. 240 */ 241 template <class Allocator_ = CGAL_ALLOCATOR(char)> 242 class Reference_counted_hierarchy : public Reference_counted_hierarchy_base { 243 // make sure it's always a char allocator 244 typedef std::allocator_traits<Allocator_> Allocator_traits; 245 typedef typename Allocator_traits::template rebind_alloc<char> Char_allocator; 246 247 static Char_allocator alloc; 248 249 public: new(size_t bytes)250 void* operator new(size_t bytes) { return alloc.allocate( bytes); } delete(void * p,size_t bytes)251 void operator delete(void* p, size_t bytes) { 252 alloc.deallocate((char*)p, bytes); 253 } 254 255 public: 256 typedef Allocator_ Allocator; 257 typedef Reference_counted_hierarchy<Allocator> Self; 258 typedef Self* Rep_pointer; 259 private: 260 mutable unsigned int count; // reference counter 261 public: Reference_counted_hierarchy()262 Reference_counted_hierarchy() : count(1) {} Reference_counted_hierarchy(const Self &)263 Reference_counted_hierarchy( const Self&) : count(1) {} 264 base_ptr()265 Rep_pointer base_ptr() { return this; } add_reference()266 void add_reference() { ++count; } remove_reference()267 void remove_reference() { --count; } is_shared()268 bool is_shared() const { return count > 1; } union_size()269 int union_size() const { return 1+count; } add_union_size(int)270 void add_union_size(int) {} 271 272 //! returns a copy of \c this. Can be implemented like 273 //! <tt>return new Derived_type( *this);</tt> 274 virtual Self* clone() = 0; 275 //! the virtual destructor is essential for proper memory management here. ~Reference_counted_hierarchy()276 virtual ~Reference_counted_hierarchy() {} 277 //! can be used to minimize memory consumption once it is known that this 278 //! representation is not used anymore and only needed to keep a fowarding 279 //! pointer. One example would be cleaning up dynamically allocated 280 //! data, or another example would be overwriting a \c leda::real with 281 //! a default constructed value to free its old expression tree. However, 282 //! this function can also be savely ignored and kept empty. clear()283 virtual void clear() {} 284 }; 285 286 template <class Alloc> 287 typename Reference_counted_hierarchy<Alloc>::Char_allocator 288 Reference_counted_hierarchy<Alloc>::alloc; 289 290 /*!\brief Base class for reference counted representations with a class 291 * hierarchy of different representations. Needs an allocator for \c char's 292 * as parameter. 293 */ 294 template <class Allocator_ = CGAL_ALLOCATOR(char)> 295 class Reference_counted_hierarchy_with_union 296 : public Reference_counted_hierarchy<Allocator_> 297 { 298 friend class Handle_policy_union; 299 friend class Handle_policy_union_and_reset; 300 public: 301 typedef Allocator_ Allocator; 302 typedef Reference_counted_hierarchy_with_union<Allocator> Self; 303 private: 304 mutable Self* next; // forwarding pointer to valid rep or 0 305 mutable int u_size; // union set size incl this rep and its handle 306 public: Reference_counted_hierarchy_with_union()307 Reference_counted_hierarchy_with_union() : 308 Reference_counted_hierarchy<Allocator_>(), next(0), u_size(2) {} is_forwarding()309 bool is_forwarding() const { return next != 0; } union_size()310 int union_size() const { return u_size; } add_union_size(int a)311 void add_union_size(int a) { 312 CGAL_precondition( u_size + a > 0); 313 u_size += a; 314 } 315 }; 316 317 318 // Handle for reference counted representation 319 // =========================================== 320 321 namespace Intern { 322 // Some helper classes to select representation between single class 323 // representations and class hierarchy representations. 324 325 // the representation type including a reference counter. 326 // The handle allocates objects of this type. This is the version 327 // for the single representation type. 328 template <class T, int HandleHierarchyPolicy> 329 struct Rep_bind_reference_counted { 330 typedef Reference_counted<T> Rep; 331 }; 332 333 // the representation type including a reference counter. 334 // The handle allocates objects of this type. This is the version 335 // for the class hierarchy of representation types. 336 template <class T> 337 struct Rep_bind_reference_counted<T, true> { 338 typedef T Rep; 339 }; 340 341 // the two versions for Reference_counted_with_forwarding 342 template <class T, int HandleHierarchyPolicy> 343 struct Rep_bind_reference_counted_with_forwarding { 344 typedef Reference_counted_with_forwarding<T> Rep; 345 }; 346 347 // the representation type including a reference counter. 348 // The handle allocates objects of this type. This is the version 349 // for the class hierarchy of representation types. 350 template <class T> 351 struct Rep_bind_reference_counted_with_forwarding<T, true> { 352 Rep_bind_reference_counted_with_forwarding() { 353 // make sure we derived from the right type 354 typedef typename T::Allocator Alloc; 355 typedef ::CGAL::Reference_counted_hierarchy_with_union<Alloc> 356 Reference_counted_hierarchy_with_union; 357 CGAL_USE_TYPE(Reference_counted_hierarchy_with_union); 358 CGAL_static_assertion(( 359 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_with_union, T >::value )); 360 } 361 typedef T Rep; 362 }; 363 364 } 365 366 /*! \brief Policy class for \c Handle_with_policy that stores the 367 representation directly without reference counting and without dynamic 368 memory allocation, is actually \e not a model of the \c HandlePolicy 369 concept, but can be used instead of one. It selects a different 370 specialized implementation of \c Handle_with_policy. It works only with 371 the single representation type, not with a class hierarchy of 372 representation types since they need the pointer in the handle 373 for the polymorphy. 374 */ 375 class Handle_policy_in_place {}; 376 377 /*!\brief 378 * Policy class for \c Handle_with_policy<T> that ignores unifying of 379 * identical representations \c T, is a model of the \c HandlePolicy concept. 380 */ 381 class Handle_policy_no_union { 382 public: 383 /*!\brief 384 * A rebind mechanism to create the representation type. 385 */ 386 template <class T, int hierarchy> 387 struct Rep_bind { 388 //! the representation type including a reference counter. 389 //! The handle allocates objects of this type. 390 typedef typename 391 Intern::Rep_bind_reference_counted<T,hierarchy>::Rep Rep; 392 }; 393 394 /*!\brief 395 * A rebind mechanism to access the base class for class hierarchies 396 * of representations. 397 * 398 * The base classes can be used directly, but this 399 * rebind mechamism allows the implementation of handle-rep classes 400 * that are parameterized with the policy class only and adapt to 401 * the necessary base class. 402 */ 403 template <class Alloc> 404 struct Hierarchy_base { 405 //! type that can be used as base class for the representation type. 406 typedef Reference_counted_hierarchy<Alloc> Type; 407 }; 408 409 /*! \brief unifies the representations of the two handles \a h and \a g. 410 * The effect is void here. 411 * 412 * \pre The representations represent the same value and one could be 413 * replaced by the other. 414 */ 415 template <class H> 416 static void unify( const H& h, const H& g) { 417 (void)h; // avoid warnings for unused parameters 418 (void)g; // but keep the names in the definition for the doc. 419 } 420 421 //! finds the currently valid representation for the handle \a h 422 //! and returns a pointer to its stored value of type \a T. 423 template <class H> 424 static typename H::Rep_pointer find( const H& h) { 425 return h.ptr_->base_ptr(); 426 } 427 }; 428 429 /*!\brief 430 * Policy class for \c Handle_with_policy that implements unifying of 431 * identical representations \c T with trees and path compression, is a 432 * model of the \c HandlePolicy concept. 433 */ 434 class Handle_policy_union { 435 public: 436 /*!\brief 437 * A rebind mechanism to create the representation type. 438 */ 439 template <class T, int hierarchy> 440 struct Rep_bind { 441 //! this default constructor contains some compile-time checks. 442 Rep_bind() { 443 //Intern::Rep_bind_reference_counted_with_forwarding<T, hierarchy> 444 // check; 445 // (void)check; 446 (void)Intern::Rep_bind_reference_counted_with_forwarding<T, hierarchy>(); 447 } 448 //! the representation type including a reference counter. 449 //! The handle allocates objects of this type. 450 typedef typename Intern::Rep_bind_reference_counted_with_forwarding<T, 451 hierarchy>::Rep Rep; 452 }; 453 454 /*!\brief 455 * A rebind mechanism to access the base class for class hierarchies 456 * of representations. 457 * 458 * The base classes can be used directly, but this 459 * rebind mechamism allows the implementation of handle-rep classes 460 * that are parameterized with the policy class only and adapt to 461 * the necessary base class. 462 */ 463 template <class Alloc> 464 struct Hierarchy_base { 465 //! type that can be used as base class for the representation type. 466 typedef Reference_counted_hierarchy_with_union<Alloc> Type; 467 }; 468 469 /*! \brief unifies the representations of the two handles \a h and \a g. 470 Performs union. 471 \pre The representations represent the same value and one can be 472 replaced by the other. The handles \a h and \a g are already 473 the representatives found by the find operation and \a h is not 474 equal to \a g. The tree representing the union of \a h has size 475 not smaller than the corresponding tree size of \a g. 476 */ 477 template <class H> 478 static void unify_large_small( const H& h, const H& g) { 479 typename H::Rep* hrep = h.ptr_; 480 typename H::Rep* grep = g.ptr_; 481 CGAL_precondition( ! grep->is_forwarding()); 482 CGAL_precondition( hrep->union_size() >= grep->union_size()); 483 grep->add_union_size(-1); 484 // make g point to h's rep. 485 if ( grep->is_shared()) { 486 // grep survises the loss of one reference 487 // and hrep gets one more reference 488 grep->remove_reference(); 489 hrep->add_reference(); 490 hrep->add_union_size( grep->union_size()); 491 grep->next = hrep; 492 } else { 493 g.delete_rep( grep); // did not survive loss of handle g 494 } 495 // redirect handle g and incr. hrep's counter 496 g.ptr_ = hrep; 497 hrep->add_reference(); 498 hrep->add_union_size(1); 499 } 500 501 /*! \brief unifies the representations of the two handles \a h and \a g. 502 Performs union with path compression. 503 \pre The representations represent the same value and one can be 504 replaced by the other. 505 */ 506 template <class H> 507 static void unify( const H& h, const H& g) { 508 if ( find(h) != find(g)) { 509 if ( h.ptr_->union_size() > g.ptr_->union_size()) 510 unify_large_small( h, g); // make g point to h's rep. 511 else 512 unify_large_small( g, h); // make h point to g's rep. 513 } 514 } 515 516 /*! \brief finds the currently valid representation for the handle \a h 517 and returns a pointer to its stored value of type \a T. Performs 518 path-compression to speed-up later union operations. 519 */ 520 template <class H> 521 static typename H::Rep_pointer find( const H& h) { 522 typedef typename H::Rep Rep; 523 if ( h.ptr_->is_forwarding()) { 524 // find new valid representation 525 Rep* new_rep = h.ptr_; 526 while ( new_rep->next != 0) 527 new_rep = static_cast<Rep*>(new_rep->next); 528 // path compression: assign new rep to all reps seen on the path 529 // update reference count properly: all reps on the path lose 530 // one reference, and the new_rep gains all of them unless 531 // the rep on the path get actually deleted. 532 Rep* rep = h.ptr_; 533 while ( rep != new_rep) { 534 Rep* tmp = static_cast<Rep*>(rep->next); 535 if ( rep->is_shared()) { 536 // rep survives the loss of one reference 537 // and new_rep gets one more reference 538 rep->remove_reference(); 539 if ( tmp != new_rep) { 540 // re-link rep to the new_rep 541 rep->next = new_rep; 542 new_rep->add_reference(); 543 } 544 } else { 545 h.delete_rep( rep); // we have to delete the current rep 546 tmp->remove_reference(); 547 } 548 rep = tmp; 549 } 550 // hook h to new_rep 551 h.ptr_ = new_rep; 552 new_rep->add_reference(); 553 } 554 return h.ptr_->base_ptr(); 555 } 556 }; 557 558 /*!\brief Policy class for \c Handle_with_policy that implements unifying of 559 * identical representations \c T with trees and path compression. 560 * 561 * It also 562 * sets the unused representation immediately to the default constructed 563 * representation \c T(), which can help to free memory if the 564 * representation is dynamically allocated and potentially large, e.g., 565 * \c leda::real. This class is a model of the \c HandlePolicy concept. 566 */ 567 class Handle_policy_union_and_reset { 568 public: 569 /*!\brief 570 * A rebind mechanism to create the representation type. 571 */ 572 template <class T, int hierarchy> 573 struct Rep_bind { 574 //! this default constructor contains some compile-time checks. 575 Rep_bind() { 576 //Intern::Rep_bind_reference_counted_with_forwarding<T, hierarchy> 577 // check; 578 // (void)check; 579 (void)Intern::Rep_bind_reference_counted_with_forwarding<T, hierarchy>(); 580 } 581 //! the representation type including a reference counter. 582 //! The handle allocates objects of this type. 583 typedef typename Intern::Rep_bind_reference_counted_with_forwarding<T, 584 hierarchy>::Rep Rep; 585 }; 586 587 /*!\brief 588 * A rebind mechanism to access the base class for class hierarchies 589 * of representations. 590 * 591 * The base classes can be used directly, but this 592 * rebind mechamism allows the implementation of handle-rep classes 593 * that are parameterized with the policy class only and adapt to 594 * the necessary base class. 595 */ 596 template <class Alloc> 597 struct Hierarchy_base { 598 //! type that can be used as base class for the representation type. 599 typedef Reference_counted_hierarchy_with_union<Alloc> Type; 600 }; 601 602 // abbreviation to re-use its implementation below. 603 typedef Handle_policy_union U; 604 605 /*! \brief unifies the representations of the two handles \a h and \a g. 606 Performs union with path compression and assigns a default 607 constructed value of the representation type \c Rep to the 608 superfluous representation. 609 \pre The representations represent the same value and one can be 610 replaced by the other. 611 */ 612 template <class H> 613 static void unify( const H& h, const H& g) { 614 if ( find(h) != find(g)) { 615 if ( h.ptr_->union_size() > g.ptr_->union_size()) { 616 // reset representation in g to default construction of T 617 if ( g.ptr_->is_shared()) 618 g.ptr_->clear(); 619 U::unify_large_small( h, g); // make g point to h's rep. 620 } else { 621 // reset representation in h to default construction of T 622 if ( h.ptr_->is_shared()) 623 h.ptr_->clear(); 624 U::unify_large_small( g, h); // make h point to g's rep. 625 } 626 } 627 } 628 629 /*! \brief finds the currently valid representation for the handle \a h 630 and returns a pointer to its stored value of type \a T. Performs 631 path-compression to speed-up later union operations. 632 */ 633 template <class H> 634 static typename H::Rep_pointer find( const H& h) { return U::find(h); } 635 }; 636 637 638 /*! \brief the base class for handles of reference counted representations of 639 \c T. 640 641 There are two fundamentally different usages of this base class: 642 643 - with a single representation class. In this case the handle 644 manages allocation and deallocation and the type \c T can 645 be an arbitrary type---the handle adds the necessary reference 646 counter internally. 647 648 - with a hierarchy of representation classes. Type \c T will be 649 the common base class of this hierarchy and it has to be derived 650 itself from either \c ::CGAL::Reference_counted_hierarchy or 651 \c ::CGAL::Reference_counted_hierarchy_with_union, both parameterized 652 with an allocator. The allocator in the handle will not be used in 653 this scenario, since the handle class does not allocate any 654 representations. Instead, the handle class derived from this handle 655 base class is allocating the different representations with the 656 \c new operator. In this case, the allocator in the base class 657 of \c T is used. 658 659 The handle class distinguishes between these two alternative 660 usages by checking if \c T is derived from one of the two base 661 classes mentioned for the second alternative. If not, it picks the 662 first alternative. 663 664 In the second alternative, the correct base class, \c 665 ::CGAL::Reference_counted_hierarchy_with_union, has to be used 666 if the policy class is one of \c class Handle_policy_union r \c 667 Handle_policy_union_and_reset. Otherwise, the other base class can 668 be used to save space. 669 670 The policy class \c Handle_policy_in_place is incompatible with the class 671 hierarchy for representation classes since the pointer in the 672 handle class would be missing. 673 674 The dependency of the base classes for \c T and the policy classes 675 is also encoded in the policy classes and can be used to write 676 generic handle-rep scheme classes. To do that one can derive \c T 677 from the expressions \c Policy::Hierarchy_base<Alloc>::Type 678 assuming that \c Policy is the handle policy and \c Alloc is the 679 allocator. Btw, the allocator is used as an allocator of character 680 arrays here. 681 682 \see \link Handle Handle for Reference Counting\endlink for 683 an example for each of the two alternative usages. 684 685 The template parameters are: 686 - \b T: is one of the two following: 687 - an arbitrary type but it must be a model of the 688 \c DefaultConstructible concept if the default constructor 689 of the handle is used. 690 - a type derived from \c Reference_counted_hierarchy<Alloc> or 691 \c Reference_counted_hierarchy_with_union<Alloc> implementing 692 their virtual member function interface, namely a \c clone() 693 function. 694 695 - \b HandlePolicy: a model of the \c HandlePolicy concept or the 696 \c Handle_policy_in_place class template that selects a specialized 697 implementation without reference counting. Has the 698 default \c Handle_policy_no_union. 699 700 - \b Allocator_: a model of the \c Allocator concept, 701 has the default \c CGAL_ALLOCATOR(T). 702 703 */ 704 template <class T_, 705 class HandlePolicy = Handle_policy_no_union, 706 class Allocator_ = CGAL_ALLOCATOR(T_)> 707 class Handle_with_policy { 708 public: 709 710 //! first template parameter 711 typedef T_ Handled_type; 712 713 //! the handle type itself. 714 typedef Handle_with_policy< Handled_type, HandlePolicy, Allocator_> Self; 715 716 //! the instantiated model of the \c HandlePolicy concept. 717 typedef HandlePolicy Handle_policy; 718 719 //! the allocator type. 720 typedef Allocator_ Allocator; 721 722 enum { is_class_hierarchy = 723 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_base, Handled_type>::value }; 724 725 typedef typename Handle_policy::template Rep_bind< Handled_type, is_class_hierarchy > Bind; 726 727 // instantiate Rep_bind to activate compile time check in there 728 static Bind bind; 729 730 // Define type that is used for function matching 731 typedef typename ::boost::mpl::if_c< 732 is_class_hierarchy, 733 ::CGAL::Tag_true, 734 ::CGAL::Tag_false >::type 735 Class_hierarchy; 736 737 //! the internal representation, i.e., \c T plus a reference count 738 //! (if needed), or just \c T if we derived from the base class to 739 //! support a class hierarchy for the representations. 740 typedef typename Bind::Rep Rep; 741 742 typedef typename Rep::Rep_pointer Rep_pointer; 743 744 typedef std::allocator_traits<Allocator_> Allocator_traits; 745 typedef typename Allocator_traits::template rebind_alloc<Rep> Rep_allocator; 746 747 //! integer type for identifying a representation. 748 typedef std::ptrdiff_t Id_type; 749 750 friend class Handle_policy_no_union; 751 friend class Handle_policy_union; 752 friend class Handle_policy_union_and_reset; 753 private: 754 mutable Rep* ptr_; 755 756 // We have to distinguish between allocating single representations 757 // and where we have a class hierarchy of representations, where the 758 // user is responsible for allocating the first representations 759 // and we can just \c clone and delete them. 760 static Rep_allocator allocator; 761 762 static Rep* new_rep( const Rep& rep) { 763 CGAL_static_assertion( !( 764 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_base, Handled_type >::value )); 765 Rep* p = allocator.allocate(1); 766 std::allocator_traits<Rep_allocator>::construct(allocator, p, rep); 767 return p; 768 } 769 static void delete_rep( Rep* p, ::CGAL::Tag_false ) { 770 std::allocator_traits<Rep_allocator>::destroy(allocator, p); 771 allocator.deallocate( p, 1); 772 } 773 static void delete_rep( Rep* p, ::CGAL::Tag_true ) { 774 delete p; 775 } 776 static void delete_rep( Rep* p) { delete_rep(p, Class_hierarchy()); } 777 778 static Rep* clone_rep( Rep* p, ::CGAL::Tag_false ) { 779 return new_rep( *p); 780 } 781 static Rep* clone_rep( Rep* p, ::CGAL::Tag_true ) { 782 return static_cast<Rep*>(p->clone()); 783 } 784 static Rep* clone_rep( Rep* p) { return clone_rep( p, Class_hierarchy()); } 785 786 void remove_reference() { 787 // cleans up the possible chain of forwarding reps 788 Handle_policy::find( *this); 789 if ( ! is_shared()) { 790 delete_rep( ptr_); 791 } else { 792 ptr_->remove_reference(); 793 ptr_->add_union_size( -1); 794 } 795 } 796 797 template <class TT> 798 Rep* make_from_single_arg( const TT& t, ::CGAL::Tag_false ) { 799 return new_rep( Rep( Handled_type(t))); 800 } 801 template <class TT> 802 Rep* make_from_single_arg( TT t, ::CGAL::Tag_true ) { 803 //Bind bind_; // trigger compile-time check 804 // (void)bind_; 805 (void)Bind(); // shouldn't this be enough to trigger? 806 return t; // has to be a pointer convertible to Rep* 807 } 808 809 protected: 810 //! protected access to the stored representation 811 Handled_type* ptr() { return static_cast<Handled_type*>(Handle_policy::find(*this));} 812 //! protected access to the stored representation 813 const Handled_type* ptr() const { 814 return static_cast<const Handled_type*>(Handle_policy::find( *this)); 815 } 816 817 //! unify two representations. \pre The two representations describe 818 //! the same value and one can be replaced by the other, i.e., the 819 //! values are immutable, or protected from changes with \c copy_on_write() 820 //! calls! 821 void unify( const Self& h) const { Handle_policy::unify( *this, h); } 822 823 //! can be called before modifying a shared representation 824 //! to get an own copy of the representation which avoids effecting the 825 //! other sharing handles. Does nothing if representation is actually 826 //! not shared. 827 void copy_on_write() { 828 Handle_policy::find( *this); 829 if ( is_shared() ) { 830 Rep* tmp_ptr = clone_rep( ptr_); 831 ptr_->remove_reference(); 832 ptr_->add_union_size( -1); 833 ptr_ = tmp_ptr; 834 } 835 } 836 837 //! used with special protected constructor 838 enum Use_with_initialize_with { 839 USE_WITH_INITIALIZE_WITH //!< used with special protected constructor 840 //!< of \c Handle_with_policy. 841 }; 842 843 //! special constructor, postpones the construction of the representation 844 //! to one of the \c initialize_with() functions. An object is in an 845 //! invalid state (and will report a failed precondition later) if 846 //! it is not initialized with an \c initialize_with() function call 847 //! after this constructor. Applicable for single representation but 848 //! also for a class hierarchy of representations. 849 Handle_with_policy( Use_with_initialize_with) : ptr_( 0) {} 850 851 //! constructor used for class hierarchies of representations, where 852 //! the handle class derived from this handle creates the different 853 //! representations itself with the \c new operator. Except for this 854 //! constructor, the one with the \c Use_with_initialize_with 855 //! argument, and the single argument template constructor no other 856 //! constructor will work for class hierarchies of representations. 857 Handle_with_policy( Rep* p) : ptr_( p) { 858 CGAL_static_assertion(( 859 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_base, Handled_type >::value )); 860 //Bind bind_; // trigger compile-time check 861 //(void)bind_; 862 (void)Bind(); 863 } 864 865 //! initializes the representation after the constructor from 866 //! \c USE_WITH_INITIALIZE_WITH has been used. Applicable for a 867 //! class hierarchy of representations only, where the derived handle class 868 //! created the representation \c p with the \c new operator. No other 869 //! version of \c initialize_with is applicable in this case except 870 //! the template version with one argument. 871 void initialize_with( Rep* p) { 872 CGAL_static_assertion(( 873 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_base, Handled_type >::value )); 874 //Bind bind_; // trigger compile-time check 875 //(void)bind_; 876 (void)Bind(); 877 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 878 "representation has already been initialized."); 879 ptr_ = p; 880 } 881 882 //! initializes the representation after the constructor from 883 //! \c USE_WITH_INITIALIZE_WITH has been used. 884 //! In case of the class hierarchy of representation classes, 885 //! this function is also chosen for pointers to newly allocated 886 //! representations that are types derived from \c T. In that case, 887 //! the pointer is just assigned to the internal pointer. 888 template <class T1> 889 void initialize_with( const T1& t1) { 890 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 891 "representation has already been initialized."); 892 ptr_ = make_from_single_arg( t1, Class_hierarchy()); 893 } 894 895 //! initializes the representation after the constructor from 896 //! \c USE_WITH_INITIALIZE_WITH has been used. 897 template <class T1, class T2> 898 void initialize_with( const T1& t1, const T2& t2) { 899 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 900 "representation has already been initialized."); 901 ptr_ = new_rep( Rep( Handled_type(t1,t2))); 902 } 903 904 //! initializes the representation after the constructor from 905 //! \c USE_WITH_INITIALIZE_WITH has been used. 906 template <class T1, class T2, class T3> 907 void initialize_with( const T1& t1, const T2& t2, const T3& t3) { 908 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 909 "representation has already been initialized."); 910 ptr_ = new_rep( Rep( Handled_type(t1,t2,t3))); 911 } 912 913 //! initializes the representation after the constructor from 914 //! \c USE_WITH_INITIALIZE_WITH has been used. 915 template <class T1, class T2, class T3, class T4> 916 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 917 const T4& t4) { 918 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 919 "representation has already been initialized."); 920 ptr_ = new_rep( Rep( Handled_type(t1,t2,t3,t4))); 921 } 922 923 //! initializes the representation after the constructor from 924 //! \c USE_WITH_INITIALIZE_WITH has been used. 925 template <class T1, class T2, class T3, class T4, class T5> 926 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 927 const T4& t4, const T5& t5) { 928 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 929 "representation has already been initialized."); 930 ptr_ = new_rep( Rep( Handled_type(t1,t2,t3,t4,t5))); 931 } 932 933 //! initializes the representation after the constructor from 934 //! \c USE_WITH_INITIALIZE_WITH has been used. 935 template <class T1, class T2, class T3, class T4, class T5, class T6> 936 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 937 const T4& t4, const T5& t5, const T6& t6) { 938 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 939 "representation has already been initialized."); 940 ptr_ = new_rep( Rep( Handled_type(t1,t2,t3,t4,t5,t6))); 941 } 942 943 //! initializes the representation after the constructor from 944 //! \c USE_WITH_INITIALIZE_WITH has been used. 945 template <class T1, class T2, class T3, class T4, class T5, class T6, 946 class T7> 947 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 948 const T4& t4, const T5& t5, const T6& t6, 949 const T7& t7) { 950 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 951 "representation has already been initialized."); 952 ptr_ = new_rep( Rep( Handled_type(t1,t2,t3,t4,t5,t6,t7))); 953 } 954 955 //! initializes the representation after the constructor from 956 //! \c USE_WITH_INITIALIZE_WITH has been used. 957 template <class T1, class T2, class T3, class T4, class T5, class T6, 958 class T7, class T8> 959 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 960 const T4& t4, const T5& t5, const T6& t6, 961 const T7& t7, const T8& t8) { 962 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 963 "representation has already been initialized."); 964 ptr_ = new_rep( Rep( Handled_type(t1,t2,t3,t4,t5,t6,t7,t8))); 965 } 966 967 //! initializes the representation after the constructor from 968 //! \c USE_WITH_INITIALIZE_WITH has been used. 969 template <class T1, class T2, class T3, class T4, class T5, class T6, 970 class T7, class T8, class T9> 971 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 972 const T4& t4, const T5& t5, const T6& t6, 973 const T7& t7, const T8& t8, const T9& t9) { 974 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 975 "representation has already been initialized."); 976 ptr_ = new_rep( Rep( Handled_type(t1,t2,t3,t4,t5,t6,t7,t8,t9))); 977 } 978 979 public: 980 //! default constructor. 981 Handle_with_policy() : ptr_( new_rep( Rep())) {} 982 983 //! copy constructor, increments reference count. 984 Handle_with_policy(const Self& h) { 985 CGAL_precondition_msg( h.ptr_ != 0, "Handle_with_policy::Handle_with_policy( Self): probably " 986 "used special protected constructor and not the " 987 "'initialize_with()' function."); 988 Handle_policy::find( h); 989 ptr_ = h.ptr_; 990 ptr_->add_reference(); 991 ptr_->add_union_size( 1); 992 } 993 994 //! forwarding constructor passing its parameter to the representation 995 //! constructor. In case of the class hierarchy of representation classes, 996 //! this constructor is also chosen for pointers to newly allocated 997 //! representations that are types derived from \c T. In that case, 998 //! the pointer is just assigned to the internal pointer. 999 template <class T1> 1000 explicit Handle_with_policy( const T1& t) 1001 : ptr_( make_from_single_arg( t, Class_hierarchy())) {} 1002 1003 //! forwarding constructor passing its parameters to the representation 1004 //! constructor. 1005 template <class T1, class T2> 1006 Handle_with_policy( const T1& t1, const T2& t2) : ptr_( new_rep( Rep( Handled_type( t1, t2)))) {} 1007 1008 //! forwarding constructor passing its parameters to the representation 1009 //! constructor. 1010 template <class T1, class T2, class T3> 1011 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3) 1012 : ptr_( new_rep( Rep( Handled_type( t1, t2, t3)))) {} 1013 1014 //! forwarding constructor passing its parameters to the representation 1015 //! constructor. 1016 template <class T1, class T2, class T3, class T4> 1017 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4) 1018 : ptr_( new_rep( Rep( Handled_type( t1, t2, t3, t4)))) {} 1019 1020 //! forwarding constructor passing its parameters to the representation 1021 //! constructor. 1022 template <class T1, class T2, class T3, class T4, class T5> 1023 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1024 const T5& t5) 1025 : ptr_( new_rep( Rep( Handled_type( t1, t2, t3, t4, t5)))) {} 1026 1027 //! forwarding constructor passing its parameters to the representation 1028 //! constructor. 1029 template <class T1, class T2, class T3, class T4, class T5, class T6> 1030 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1031 const T5& t5, const T6& t6) 1032 : ptr_( new_rep( Rep( Handled_type( t1, t2, t3, t4, t5, t6)))) {} 1033 1034 //! forwarding constructor passing its parameters to the representation 1035 //! constructor. 1036 template <class T1, class T2, class T3, class T4, class T5, class T6, 1037 class T7> 1038 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1039 const T5& t5, const T6& t6, const T7& t7) 1040 : ptr_( new_rep( Rep( Handled_type( t1, t2, t3, t4, t5, t6, t7)))) {} 1041 1042 //! forwarding constructor passing its parameters to the representation 1043 //! constructor. 1044 template <class T1, class T2, class T3, class T4, class T5, class T6, 1045 class T7, class T8> 1046 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1047 const T5& t5, const T6& t6, const T7& t7, const T8& t8) 1048 : ptr_( new_rep( Rep( Handled_type( t1, t2, t3, t4, t5, t6, t7, t8)))) {} 1049 1050 //! forwarding constructor passing its parameters to the representation 1051 //! constructor. 1052 template <class T1, class T2, class T3, class T4, class T5, class T6, 1053 class T7, class T8, class T9> 1054 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1055 const T5& t5, const T6& t6, const T7& t7, const T8& t8, 1056 const T9& t9) 1057 : ptr_( new_rep( Rep( Handled_type( t1, t2, t3, t4, t5, t6, t7, t8, t9)))) {} 1058 1059 //! destructor, decrements reference count. 1060 ~Handle_with_policy() { 1061 //Bind bind_; // trigger compile-time check 1062 //(void)bind_; 1063 (void)Bind(); 1064 CGAL_precondition_msg( ptr_ != 0, "Handle_with_policy::~Handle_with_policy(): probably used " 1065 "special protected constructor and not the " 1066 "'initialize_with()' function."); 1067 remove_reference(); 1068 } 1069 1070 //! assignment, updates reference count correspondingly. 1071 Self& operator=( const Self& h) { 1072 CGAL_precondition_msg( h.ptr_ != 0, "Handle_with_policy::operator=(): probably " 1073 "used special protected constructor and not the " 1074 "'initialize_with()' function."); 1075 Handle_policy::find( h); 1076 h.ptr_->add_reference(); 1077 h.ptr_->add_union_size( 1); 1078 remove_reference(); 1079 ptr_ = h.ptr_; 1080 return *this; 1081 } 1082 1083 //! returns \c true if both share the same representation. 1084 bool is_identical( const Self& h) const { return ptr() == h.ptr(); } 1085 1086 //! returns a unique id value. Two handles share their representation 1087 //! is their id values are identical. 1088 Id_type id() const { return reinterpret_cast<Id_type>(&*ptr()); } 1089 1090 //! returns true if the representation is shared, i.e., the reference 1091 //! counter is greater than one. 1092 bool is_shared() const { return ptr_->is_shared(); } 1093 1094 //! returns \c true if the representation is actually forwarding to 1095 //! another equivalent representation (happens only with the 1096 //! union-find policies). 1097 bool is_forwarding() const { return ptr_->is_forwarding(); } 1098 1099 //! returns the size of the union set including all reference counts that 1100 //! have been accumulated so far for this representation. 1101 int union_size() const { return ptr_->union_size(); } 1102 1103 // backwards compatible 1104 bool identical( const Self& h) const { return is_identical(h); } 1105 1106 #ifdef CGAL_HANDLE_WITH_POLICY_INTERNAL_TEST 1107 // provide access to pointer for testing only!! 1108 const Rep* test_ptr() const { return ptr_; } 1109 // provide access to pointer for testing only!! 1110 bool test_identical_ptr( const Self& h) const { return ptr_ == h.ptr_; } 1111 #endif // CGAL_HANDLE_WITH_POLICY_INTERNAL_TEST 1112 }; 1113 1114 // instantiate Rep_bind to activate compile time check in there 1115 template <class T, class Policy, class Alloc> 1116 typename Handle_with_policy<T,Policy,Alloc>::Bind Handle_with_policy<T,Policy,Alloc>::bind; 1117 1118 1119 //! alternative syntax for \c h.id() to allow use with LEDA 1120 /*! This is only provided for \c Handle_policy_no_union because 1121 * ID numbers have to be fixed throughout an object's lifetime. 1122 */ 1123 template <class T, class A> 1124 typename Handle_with_policy<T, Handle_policy_no_union, A>::Id_type 1125 ID_Number(const Handle_with_policy<T, Handle_policy_no_union, A>& h) 1126 { return h.id(); } 1127 1128 template <class T, class Policy, class Alloc> 1129 typename Handle_with_policy<T, Policy, Alloc>::Rep_allocator 1130 Handle_with_policy<T, Policy, Alloc>::allocator; 1131 1132 1133 /*! \brief specialization of the base class for handles for non-reference 1134 counted representations. 1135 Uses \c LEDA_MEMORY if available. 1136 */ 1137 template <class T_, class Allocator_> 1138 class Handle_with_policy<T_, Handle_policy_in_place, Allocator_> { 1139 public: 1140 1141 //! first template paramter 1142 typedef T_ Handled_type; 1143 1144 //! the handle type itself. 1145 typedef Handle_with_policy< Handled_type, Handle_policy_in_place, Allocator_> Self; 1146 1147 //! the model of the \c HandlePolicy concept. 1148 typedef Handle_policy_in_place Handle_policy; 1149 1150 //! the allocator type. 1151 typedef Allocator_ Allocator; 1152 1153 //! identify \c T with the internal representation \c Rep. 1154 typedef Handled_type Rep; 1155 1156 //! integer type for identifying a representation. 1157 typedef std::ptrdiff_t Id_type; 1158 private: 1159 // store the rep in place 1160 Rep rep; 1161 1162 protected: 1163 //! protected access to the stored representation 1164 Handled_type* ptr() { return &rep; } 1165 //! protected access to the stored representation 1166 const Handled_type* ptr() const { return &rep; } 1167 1168 //! unify two representations, a null op here. 1169 void unify( const Self&) const {} 1170 1171 //! can be called before modifying a shared representation 1172 //! to get an own copy of the representation, a null op here. 1173 void copy_on_write() {} 1174 1175 //! used with special protected constructor 1176 enum Use_with_initialize_with { 1177 USE_WITH_INITIALIZE_WITH //!< used with special protected constructor 1178 }; 1179 1180 //! special constructor, postpones the construction of the representation 1181 //! to one of the \c initialize_with() functions. Requires default 1182 //! constructor for \c T. 1183 Handle_with_policy( Use_with_initialize_with) {} 1184 1185 //! initializes the representation after the constructor from 1186 //! \c USE_WITH_INITIALIZE_WITH has been used. 1187 template <class T1> 1188 void initialize_with( const T1& t1) { rep = Rep(t1); } 1189 1190 //! initializes the representation after the constructor from 1191 //! \c USE_WITH_INITIALIZE_WITH has been used. 1192 template <class T1, class T2> 1193 void initialize_with( const T1& t1, const T2& t2) { rep = Rep(t1,t2); } 1194 1195 //! initializes the representation after the constructor from 1196 //! \c USE_WITH_INITIALIZE_WITH has been used. 1197 template <class T1, class T2, class T3> 1198 void initialize_with( const T1& t1, const T2& t2, const T3& t3) { 1199 rep = Rep(t1,t2,t3); 1200 } 1201 1202 //! initializes the representation after the constructor from 1203 //! \c USE_WITH_INITIALIZE_WITH has been used. 1204 template <class T1, class T2, class T3, class T4> 1205 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 1206 const T4& t4) { 1207 rep = Rep(t1,t2,t3,t4); 1208 } 1209 1210 //! initializes the representation after the constructor from 1211 //! \c USE_WITH_INITIALIZE_WITH has been used. 1212 template <class T1, class T2, class T3, class T4, class T5> 1213 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 1214 const T4& t4, const T5& t5) { 1215 rep = Rep(t1,t2,t3,t4,t5); 1216 } 1217 1218 //! initializes the representation after the constructor from 1219 //! \c USE_WITH_INITIALIZE_WITH has been used. 1220 template <class T1, class T2, class T3, class T4, class T5, class T6> 1221 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 1222 const T4& t4, const T5& t5, const T6& t6) { 1223 rep = Rep(t1,t2,t3,t4,t5,t6); 1224 } 1225 1226 //! initializes the representation after the constructor from 1227 //! \c USE_WITH_INITIALIZE_WITH has been used. 1228 template <class T1, class T2, class T3, class T4, class T5, class T6, 1229 class T7> 1230 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 1231 const T4& t4, const T5& t5, const T6& t6, 1232 const T7& t7) { 1233 rep = Rep(t1,t2,t3,t4,t5,t6,t7); 1234 } 1235 1236 //! initializes the representation after the constructor from 1237 //! \c USE_WITH_INITIALIZE_WITH has been used. 1238 template <class T1, class T2, class T3, class T4, class T5, class T6, 1239 class T7, class T8> 1240 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 1241 const T4& t4, const T5& t5, const T6& t6, 1242 const T7& t7, const T8& t8) { 1243 rep = Rep(t1,t2,t3,t4,t5,t6,t7,t8); 1244 } 1245 1246 //! initializes the representation after the constructor from 1247 //! \c USE_WITH_INITIALIZE_WITH has been used. 1248 template <class T1, class T2, class T3, class T4, class T5, class T6, 1249 class T7, class T8, class T9> 1250 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 1251 const T4& t4, const T5& t5, const T6& t6, 1252 const T7& t7, const T8& t8, const T9& t9) { 1253 rep = Rep(t1,t2,t3,t4,t5,t6,t7,t8,t9); 1254 } 1255 1256 public: 1257 //! default constructor. 1258 Handle_with_policy() {} 1259 1260 //! copy constructor. 1261 Handle_with_policy(const Self& h) : rep( h.rep) {} 1262 1263 //! forwarding constructor passing its parameter to the representation 1264 //! constructor. 1265 template <class T1> 1266 explicit Handle_with_policy( const T1& t) : rep( Rep(t)) {} 1267 1268 //! forwarding constructor passing its parameters to the representation 1269 //! constructor. 1270 template <class T1, class T2> 1271 Handle_with_policy( const T1& t1, const T2& t2) : rep( Rep(t1,t2)) {} 1272 1273 //! forwarding constructor passing its parameters to the representation 1274 //! constructor. 1275 template <class T1, class T2, class T3> 1276 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3) : rep( Rep(t1,t2,t3)) {} 1277 1278 //! forwarding constructor passing its parameters to the representation 1279 //! constructor. 1280 template <class T1, class T2, class T3, class T4> 1281 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4) 1282 : rep( Rep( t1, t2, t3, t4)) {} 1283 1284 //! forwarding constructor passing its parameters to the representation 1285 //! constructor. 1286 template <class T1, class T2, class T3, class T4, class T5> 1287 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1288 const T5& t5) 1289 : rep( Rep( t1, t2, t3, t4, t5)) {} 1290 1291 //! forwarding constructor passing its parameters to the representation 1292 //! constructor. 1293 template <class T1, class T2, class T3, class T4, class T5, class T6> 1294 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1295 const T5& t5, const T6& t6) 1296 : rep( Rep( t1, t2, t3, t4, t5, t6)) {} 1297 1298 //! forwarding constructor passing its parameters to the representation 1299 //! constructor. 1300 template <class T1, class T2, class T3, class T4, class T5, class T6, 1301 class T7> 1302 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1303 const T5& t5, const T6& t6, const T7& t7) 1304 : rep( Rep( t1, t2, t3, t4, t5, t6, t7)) {} 1305 1306 //! forwarding constructor passing its parameters to the representation 1307 //! constructor. 1308 template <class T1, class T2, class T3, class T4, class T5, class T6, 1309 class T7, class T8> 1310 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1311 const T5& t5, const T6& t6, const T7& t7, const T8& t8) 1312 : rep( Rep( t1, t2, t3, t4, t5, t6, t7, t8)) {} 1313 1314 //! forwarding constructor passing its parameters to the representation 1315 //! constructor. 1316 template <class T1, class T2, class T3, class T4, class T5, class T6, 1317 class T7, class T8, class T9> 1318 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 1319 const T5& t5, const T6& t6, const T7& t7, const T8& t8, 1320 const T9& t9) 1321 : rep( Rep( t1, t2, t3, t4, t5, t6, t7, t8, t9)) {} 1322 1323 //! returns \c true if both share the same representation. 1324 bool is_identical( const Self& h) const { return this == &h; } 1325 1326 //! returns a unique id value. Two handles share their representation 1327 //! is their id values are identical. 1328 Id_type id() const { return ptr() - static_cast<Handled_type const*>(0); } 1329 1330 //! returns \c false since the representation is not shared for 1331 //! this specialization. 1332 bool is_shared() const { return false; } 1333 1334 //! returns \c false since the representation is not forwarding for 1335 //! this specialization. 1336 bool is_forwarding() const { return false; } 1337 1338 //! returns \c 1 as the union size for this specialization. 1339 int union_size() const { return 1; } 1340 1341 // backwards compatible 1342 bool identical( const Self& h) const { return is_identical(h); } 1343 1344 #ifdef CGAL_HANDLE_WITH_POLICY_INTERNAL_TEST 1345 // provide access to pointer for testing only!! 1346 const Rep* test_ptr() const { return *rep; } 1347 // provide access to pointer for testing only!! 1348 bool test_identical_ptr( const Self& h) const { return this == &h; } 1349 #endif // CGAL_HANDLE_WITH_POLICY_INTERNAL_TEST 1350 1351 #ifdef CGAL_USE_LEDA 1352 LEDA_MEMORY( Self) 1353 #endif 1354 }; 1355 1356 template <class T, class HandlePolicy, class Allocator> 1357 inline bool identical(const Handle_with_policy<T,HandlePolicy,Allocator> &h1, const Handle_with_policy<T,HandlePolicy,Allocator> &h2) { return h1.is_identical(h2); } 1358 1359 1360 /*\brief 1361 * This class' function call operator test whether one handle's \c id is 1362 * less than the \c id of the other handle. 1363 * 1364 * "Less" is defined in terms of the second template argument, 1365 * which defaults to \c std::less<Handle::Id_type> 1366 */ 1367 template <class Handle, class Less = std::less<typename Handle::Id_type> > 1368 class Handle_id_less_than { 1369 public: 1370 //! result_type 1371 typedef bool result_type; 1372 //! type of first argument 1373 typedef Handle first_argument_type; 1374 //! type of second argument 1375 typedef Handle second_argument_type; 1376 //! returns \c true iff \c h1.id() < \c h2.id() 1377 bool operator () (Handle h1, Handle h2) { 1378 Less is_less; 1379 return is_less(h1.id(), h2.id()); 1380 } 1381 //! returns \c true iff \c h1.id() < \c h2.id() 1382 bool operator () (Handle h1, Handle h2) const { 1383 Less is_less; 1384 return is_less(h1.id(), h2.id()); 1385 } 1386 }; 1387 1388 1389 //@} 1390 1391 } //namespace CGAL 1392 1393 #endif // CGAL_HANDLE_WITH_POLICY_H 1394