1 // VectorMap.h 2 // 3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de) 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a 6 // copy of this software and associated documentation files (the "Software"), 7 // to deal in the Software without restriction, including without limitation 8 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 // and/or sell copies of the Software, and to permit persons to whom the 10 // Software is furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 // DEALINGS IN THE SOFTWARE. 22 // 23 // Except as contained in this notice, the name of a copyright holder shall 24 // not be used in advertising or otherwise to promote the sale, use or other 25 // dealings in this Software without prior written authorization of the 26 // copyright holder. 27 28 #ifndef _VECTOR_MAP_H 29 #define _VECTOR_MAP_H 30 31 #include <new> 32 #include <stdlib.h> 33 #include <string.h> 34 35 #include <SupportDefs.h> 36 37 #include <KernelUtilsOrder.h> 38 #include <Vector.h> 39 40 namespace VectorMapEntryStrategy { 41 // Pair 42 template<typename Key, typename Value, 43 typename KeyOrder = KernelUtilsOrder::Ascending<Key> > class Pair; 44 // ImplicitKey 45 template<typename Key, typename Value, typename GetKey, 46 typename KeyOrder = KernelUtilsOrder::Ascending<Key> > 47 class ImplicitKey; 48 } 49 50 template<typename Entry, typename Parent, typename EntryIterator> 51 class VectorMapIterator; 52 template<typename _Key, typename _Value, typename Entry, typename Parent> 53 class VectorMapEntry; 54 55 // for convenience 56 #define _VECTOR_MAP_TEMPLATE_LIST template<typename Key, typename Value, \ 57 typename EntryStrategy> 58 #define _VECTOR_MAP_CLASS_NAME VectorMap<Key, Value, EntryStrategy> 59 60 /*! 61 \class VectorMap 62 \brief A generic vector-based map implementation. 63 64 The map entries are ordered according to the supplied 65 compare function object. Default is ascending order. 66 67 Note that VectorMap::Entry is not the same class as EntryStrategy::Entry. 68 It is light-weight class, an object of which is returned when a iterator 69 is dereferenced. It features a Key() and a Value() method returning 70 references to the entry's key/value. This allows EntryStrategy::Entry 71 to be an arbitrary class, not needing to implement a certain interface. 72 */ 73 template<typename Key, typename Value, 74 typename EntryStrategy = VectorMapEntryStrategy::Pair<Key, Value> > 75 class VectorMap { 76 private: 77 typedef _VECTOR_MAP_CLASS_NAME Class; 78 typedef typename EntryStrategy::Entry _Entry; 79 typedef typename EntryStrategy::KeyReference KeyReference; 80 typedef Vector<_Entry> ElementVector; 81 82 public: 83 typedef VectorMapEntry<KeyReference, Value, _Entry, Class> 84 Entry; 85 typedef VectorMapEntry<KeyReference, const Value, const _Entry, 86 const Class> ConstEntry; 87 typedef VectorMapIterator<Entry, Class, ElementVector::Iterator> 88 Iterator; 89 typedef VectorMapIterator<ConstEntry, const Class, 90 ElementVector::ConstIterator> ConstIterator; 91 92 private: 93 static const size_t kDefaultChunkSize = 10; 94 static const size_t kMaximalChunkSize = 1024 * 1024; 95 96 public: 97 VectorMap(size_t chunkSize = kDefaultChunkSize); 98 // TODO: Copy constructor, assignment operator. 99 ~VectorMap(); 100 101 status_t Insert(const Key &key, const Value &value); 102 status_t Put(const Key &key, const Value &value); 103 Value &Get(const Key &key); 104 const Value &Get(const Key &key) const; 105 106 int32 Remove(const Key &key); 107 Iterator Erase(const Iterator &iterator); 108 109 inline int32 Count() const; 110 inline bool IsEmpty() const; 111 void MakeEmpty(); 112 113 inline Iterator Begin(); 114 inline ConstIterator Begin() const; 115 inline Iterator End(); 116 inline ConstIterator End() const; 117 inline Iterator Null(); 118 inline ConstIterator Null() const; 119 120 Iterator Find(const Key &key); 121 ConstIterator Find(const Key &key) const; 122 Iterator FindClose(const Key &key, bool less); 123 ConstIterator FindClose(const Key &key, bool less) const; 124 125 private: 126 int32 _FindInsertionIndex(const Key &key, bool &exists) const; 127 128 private: 129 friend class Entry; 130 friend class ConstEntry; 131 132 ElementVector fElements; 133 EntryStrategy fEntryStrategy; 134 }; 135 136 137 // VectorMapEntry 138 template<typename KeyReference, typename _Value, typename Entry, 139 typename Parent> 140 class VectorMapEntry { 141 private: 142 typedef VectorMapEntry<KeyReference, _Value, Entry, Parent> Class; 143 144 public: 145 VectorMapEntry() 146 : fParent(NULL), fEntry(NULL) {} 147 148 inline KeyReference Key() const 149 { 150 return fParent->fEntryStrategy.GetKey(*fEntry); 151 } 152 153 inline _Value &Value() const 154 { 155 return fParent->fEntryStrategy.GetValue(*fEntry); 156 } 157 158 inline const Class *operator->() const 159 { 160 return this; 161 } 162 163 // private 164 public: 165 VectorMapEntry(Parent *parent, Entry *entry) 166 : fParent(parent), fEntry(entry) {} 167 168 private: 169 const Parent *fParent; 170 Entry *fEntry; 171 }; 172 173 174 // VectorMapIterator 175 template<typename Entry, typename Parent, typename EntryIterator> 176 class VectorMapIterator { 177 private: 178 typedef VectorMapIterator<Entry, Parent, EntryIterator> Iterator; 179 180 public: 181 inline VectorMapIterator() 182 : fParent(NULL), 183 fIterator() 184 { 185 } 186 187 inline VectorMapIterator( 188 const Iterator &other) 189 : fParent(other.fParent), 190 fIterator(other.fIterator) 191 { 192 } 193 194 inline Iterator &operator++() 195 { 196 ++fIterator; 197 return *this; 198 } 199 200 inline Iterator operator++(int) 201 { 202 Iterator it(*this); 203 ++*this; 204 return it; 205 } 206 207 inline Iterator &operator--() 208 { 209 --fIterator; 210 return *this; 211 } 212 213 inline Iterator operator--(int) 214 { 215 Iterator it(*this); 216 --*this; 217 return it; 218 } 219 220 inline Iterator &operator=(const Iterator &other) 221 { 222 fParent = other.fParent; 223 fIterator = other.fIterator; 224 return *this; 225 } 226 227 inline bool operator==(const Iterator &other) const 228 { 229 return (fParent == other.fParent && fIterator == other.fIterator); 230 } 231 232 inline bool operator!=(const Iterator &other) const 233 { 234 return !(*this == other); 235 } 236 237 inline Entry operator*() const 238 { 239 return Entry(fParent, &*fIterator); 240 } 241 242 inline Entry operator->() const 243 { 244 return Entry(fParent, &*fIterator); 245 } 246 247 inline operator bool() const 248 { 249 return fIterator; 250 } 251 252 // private 253 public: 254 inline VectorMapIterator(Parent *parent, const EntryIterator &iterator) 255 : fParent(parent), 256 fIterator(iterator) 257 { 258 } 259 260 inline EntryIterator &GetIterator() 261 { 262 return fIterator; 263 } 264 265 inline const EntryIterator &GetIterator() const 266 { 267 return fIterator; 268 } 269 270 protected: 271 Parent *fParent; 272 EntryIterator fIterator; 273 }; 274 275 276 // VectorMap 277 278 // constructor 279 /*! \brief Creates an empty map. 280 \param chunkSize The granularity for the underlying vector's capacity, 281 i.e. the minimal number of elements the capacity grows or shrinks 282 when necessary. 283 */ 284 _VECTOR_MAP_TEMPLATE_LIST 285 _VECTOR_MAP_CLASS_NAME::VectorMap(size_t chunkSize) 286 : fElements(chunkSize) 287 { 288 } 289 290 // destructor 291 /*! \brief Frees all resources associated with the object. 292 293 The contained keys and values are destroyed. Note, that for pointer 294 types only the pointer is destroyed, not the object it points to. 295 */ 296 _VECTOR_MAP_TEMPLATE_LIST 297 _VECTOR_MAP_CLASS_NAME::~VectorMap() 298 { 299 } 300 301 // Insert 302 /*! \brief Associates a key with a value. 303 304 If there is already a value associated with the key, the old entry 305 is replaced. 306 307 \param key The key to which a value shall be associated. 308 \param value The value to be associated with the key. 309 \return 310 - \c B_OK: Everything went fine. 311 - \c B_NO_MEMORY: Insufficient memory for this operation. 312 - \c B_BAD_VALUE: The map's EntryStrategy requires some special 313 relationship between key and value, that \a key and \a value haven't 314 (doesn't apply to the default strategy). 315 */ 316 _VECTOR_MAP_TEMPLATE_LIST 317 status_t 318 _VECTOR_MAP_CLASS_NAME::Insert(const Key &key, const Value &value) 319 { 320 if (!fEntryStrategy.AreCompatible(key, value)) 321 return B_BAD_VALUE; 322 bool exists = false; 323 int32 index = _FindInsertionIndex(key, exists); 324 if (exists) { 325 fElements[index] = fEntryStrategy.MakeEntry(key, value); 326 return B_OK; 327 } 328 return fElements.Insert(fEntryStrategy.MakeEntry(key, value), index); 329 } 330 331 // Put 332 /*! \brief Equivalent to Insert(). 333 */ 334 _VECTOR_MAP_TEMPLATE_LIST 335 inline 336 status_t 337 _VECTOR_MAP_CLASS_NAME::Put(const Key &key, const Value &value) 338 { 339 return Insert(key, value); 340 } 341 342 // Get 343 /*! \brief Returns the value associated with a given key. 344 345 \note Invoking this method for a key not know to the map is dangerous! 346 The behavior is unspecified. It may even crash. 347 348 \param key The key to be looked up. 349 \return The value associated with \a key. 350 */ 351 _VECTOR_MAP_TEMPLATE_LIST 352 Value & 353 _VECTOR_MAP_CLASS_NAME::Get(const Key &key) 354 { 355 bool exists = false; 356 int32 index = _FindInsertionIndex(key, exists); 357 if (!exists) 358 return fEntryStrategy.GetValue(fElements[0]); 359 return fEntryStrategy.GetValue(fElements[index]); 360 } 361 362 // Get 363 /*! \brief Returns the value associated with a given key. 364 365 \note Invoking this method for a key not know to the map is dangerous! 366 The behavior is unspecified. It may even crash. 367 368 \param key The key to be looked up. 369 \return The value associated with \a key. 370 */ 371 _VECTOR_MAP_TEMPLATE_LIST 372 const Value & 373 _VECTOR_MAP_CLASS_NAME::Get(const Key &key) const 374 { 375 bool exists = false; 376 int32 index = _FindInsertionIndex(key, exists); 377 if (!exists) 378 return fEntryStrategy.GetValue(fElements[0]); 379 return fEntryStrategy.GetValue(fElements[index]); 380 } 381 382 // Remove 383 /*! \brief Removes the entry with the supplied key. 384 \param key The key to be removed. 385 \return The number of removed occurrences, i.e. \c 1, if the map 386 contained an entry with that key, \c 0 otherwise. 387 */ 388 _VECTOR_MAP_TEMPLATE_LIST 389 int32 390 _VECTOR_MAP_CLASS_NAME::Remove(const Key &key) 391 { 392 bool exists = false; 393 int32 index = _FindInsertionIndex(key, exists); 394 if (!exists) 395 return 0; 396 fElements.Erase(index); 397 return 1; 398 } 399 400 // Erase 401 /*! \brief Removes the entry at the given position. 402 \param iterator An iterator referring to the entry to be removed. 403 \return An iterator referring to the entry succeeding the removed 404 one (End(), if it was the last element that has been 405 removed), or Null(), if \a iterator was an invalid iterator 406 (in this case including End()). 407 */ 408 _VECTOR_MAP_TEMPLATE_LIST 409 _VECTOR_MAP_CLASS_NAME::Iterator 410 _VECTOR_MAP_CLASS_NAME::Erase(const Iterator &iterator) 411 { 412 return Iterator(this, fElements.Erase(iterator.GetIterator())); 413 } 414 415 // Count 416 /*! \brief Returns the number of entry the map contains. 417 \return The number of entries the map contains. 418 */ 419 _VECTOR_MAP_TEMPLATE_LIST 420 inline 421 int32 422 _VECTOR_MAP_CLASS_NAME::Count() const 423 { 424 return fElements.Count(); 425 } 426 427 // IsEmpty 428 /*! \brief Returns whether the map is empty. 429 \return \c true, if the map is empty, \c false otherwise. 430 */ 431 _VECTOR_MAP_TEMPLATE_LIST 432 inline 433 bool 434 _VECTOR_MAP_CLASS_NAME::IsEmpty() const 435 { 436 return fElements.IsEmpty(); 437 } 438 439 // MakeEmpty 440 /*! \brief Removes all entries from the map. 441 */ 442 _VECTOR_MAP_TEMPLATE_LIST 443 void 444 _VECTOR_MAP_CLASS_NAME::MakeEmpty() 445 { 446 fElements.MakeEmpty(); 447 } 448 449 // Begin 450 /*! \brief Returns an iterator referring to the beginning of the map. 451 452 If the map is not empty, Begin() refers to its first entry, 453 otherwise it is equal to End() and must not be dereferenced! 454 455 \return An iterator referring to the beginning of the map. 456 */ 457 _VECTOR_MAP_TEMPLATE_LIST 458 inline 459 _VECTOR_MAP_CLASS_NAME::Iterator 460 _VECTOR_MAP_CLASS_NAME::Begin() 461 { 462 return Iterator(this, fElements.Begin()); 463 } 464 465 // Begin 466 /*! \brief Returns an iterator referring to the beginning of the map. 467 468 If the map is not empty, Begin() refers to its first entry, 469 otherwise it is equal to End() and must not be dereferenced! 470 471 \return An iterator referring to the beginning of the map. 472 */ 473 _VECTOR_MAP_TEMPLATE_LIST 474 inline 475 _VECTOR_MAP_CLASS_NAME::ConstIterator 476 _VECTOR_MAP_CLASS_NAME::Begin() const 477 { 478 return ConstIterator(this, fElements.Begin()); 479 } 480 481 // End 482 /*! \brief Returns an iterator referring to the end of the map. 483 484 The position identified by End() is the one succeeding the last 485 entry, i.e. it must not be dereferenced! 486 487 \return An iterator referring to the end of the map. 488 */ 489 _VECTOR_MAP_TEMPLATE_LIST 490 inline 491 _VECTOR_MAP_CLASS_NAME::Iterator 492 _VECTOR_MAP_CLASS_NAME::End() 493 { 494 return Iterator(this, fElements.End()); 495 } 496 497 // End 498 /*! \brief Returns an iterator referring to the end of the map. 499 500 The position identified by End() is the one succeeding the last 501 entry, i.e. it must not be dereferenced! 502 503 \return An iterator referring to the end of the map. 504 */ 505 _VECTOR_MAP_TEMPLATE_LIST 506 inline 507 _VECTOR_MAP_CLASS_NAME::ConstIterator 508 _VECTOR_MAP_CLASS_NAME::End() const 509 { 510 return ConstIterator(this, fElements.End()); 511 } 512 513 // Null 514 /*! \brief Returns an invalid iterator. 515 516 Null() is used as a return value, if something went wrong. It must 517 neither be incremented or decremented nor dereferenced! 518 519 \return An invalid iterator. 520 */ 521 _VECTOR_MAP_TEMPLATE_LIST 522 inline 523 _VECTOR_MAP_CLASS_NAME::Iterator 524 _VECTOR_MAP_CLASS_NAME::Null() 525 { 526 return Iterator(this, fElements.Null()); 527 } 528 529 // Null 530 /*! \brief Returns an invalid iterator. 531 532 Null() is used as a return value, if something went wrong. It must 533 neither be incremented or decremented nor dereferenced! 534 535 \return An invalid iterator. 536 */ 537 _VECTOR_MAP_TEMPLATE_LIST 538 inline 539 _VECTOR_MAP_CLASS_NAME::ConstIterator 540 _VECTOR_MAP_CLASS_NAME::Null() const 541 { 542 return ConstIterator(this, fElements.Null()); 543 } 544 545 // Find 546 /*! \brief Returns an iterator referring to the entry with the 547 specified key. 548 \param key The key of the entry to be found. 549 \return An iterator referring to the found entry, or End(), if the 550 map doesn't contain any entry with the given value. 551 */ 552 _VECTOR_MAP_TEMPLATE_LIST 553 _VECTOR_MAP_CLASS_NAME::Iterator 554 _VECTOR_MAP_CLASS_NAME::Find(const Key &key) 555 { 556 bool exists = false; 557 int32 index = _FindInsertionIndex(key, exists); 558 if (!exists) 559 return End(); 560 return Iterator(this, fElements.IteratorForIndex(index)); 561 } 562 563 // Find 564 /*! \brief Returns an iterator referring to the entry with the 565 specified key. 566 \param key The key of the entry to be found. 567 \return An iterator referring to the found entry, or End(), if the 568 map doesn't contain any entry with the given value. 569 */ 570 _VECTOR_MAP_TEMPLATE_LIST 571 _VECTOR_MAP_CLASS_NAME::ConstIterator 572 _VECTOR_MAP_CLASS_NAME::Find(const Key &key) const 573 { 574 bool exists = false; 575 int32 index = _FindInsertionIndex(key, exists); 576 if (!exists) 577 return End(); 578 return ConstIterator(this, fElements.IteratorForIndex(index)); 579 } 580 581 // FindClose 582 /*! \brief Returns an iterator referring to the entry with a key closest 583 to the specified one. 584 585 If the map contains an entry with the specified key, an iterator 586 to it is returned. Otherwise \a less indicates whether an iterator to 587 the entry with an directly smaller or greater key shall be returned. 588 589 If \a less is \c true and the first entry in the map has a greater 590 key than the specified one, End() is returned. Similarly, when \a less 591 is \c false and the last entry's key is smaller. Find() invoked on an 592 empty map always returns End(). 593 594 Note, that the key order used for the set is specified as template 595 argument to the class. Default is ascending order. Descending order 596 inverts the meaning of \a less, i.e. if \c true, greater values will 597 be returned, since they are smaller ones according to the order. 598 599 \param value The key of the entry to be found. 600 \return An iterator referring to the found entry, or End(), if the 601 map doesn't contain any entry with the given key or a close 602 one according to \a less. 603 */ 604 _VECTOR_MAP_TEMPLATE_LIST 605 _VECTOR_MAP_CLASS_NAME::Iterator 606 _VECTOR_MAP_CLASS_NAME::FindClose(const Key &key, bool less) 607 { 608 bool exists = false; 609 int32 index = _FindInsertionIndex(key, exists); 610 // If not found, the index _FindInsertionIndex() returns will point to 611 // an element with a greater value or to End(). So, no special handling 612 // is needed for !less. 613 if (exists || !less) 614 return Iterator(this, fElements.IteratorForIndex(index)); 615 // An element with a smaller value is desired. The previous one (if any) 616 // will do. 617 if (index > 0) 618 return Iterator(this, fElements.IteratorForIndex(index - 1)); 619 return End(); 620 } 621 622 // FindClose 623 /*! \brief Returns an iterator referring to the entry with a key closest 624 to the specified one. 625 626 If the map contains an entry with the specified key, an iterator 627 to it is returned. Otherwise \a less indicates whether an iterator to 628 the entry with an directly smaller or greater key shall be returned. 629 630 If \a less is \c true and the first entry in the map has a greater 631 key than the specified one, End() is returned. Similarly, when \a less 632 is \c false and the last entry's key is smaller. Find() invoked on an 633 empty map always returns End(). 634 635 Note, that the key order used for the set is specified as template 636 argument to the class. Default is ascending order. Descending order 637 inverts the meaning of \a less, i.e. if \c true, greater values will 638 be returned, since they are smaller ones according to the order. 639 640 \param value The key of the entry to be found. 641 \return An iterator referring to the found entry, or End(), if the 642 map doesn't contain any entry with the given key or a close 643 one according to \a less. 644 */ 645 _VECTOR_MAP_TEMPLATE_LIST 646 _VECTOR_MAP_CLASS_NAME::ConstIterator 647 _VECTOR_MAP_CLASS_NAME::FindClose(const Key &key, bool less) const 648 { 649 bool exists = false; 650 int32 index = _FindInsertionIndex(key, exists); 651 // If not found, the index _FindInsertionIndex() returns will point to 652 // an element with a greater value or to End(). So, no special handling 653 // is needed for !less. 654 if (exists || !less) 655 return ConstIterator(this, fElements.IteratorForIndex(index)); 656 // An element with a smaller value is desired. The previous one (if any) 657 // will do. 658 if (index > 0) 659 return ConstIterator(this, fElements.IteratorForIndex(index - 1)); 660 return End(); 661 } 662 663 // _FindInsertionIndex 664 /*! \brief Finds the index at which the entry with the supplied key is 665 located or at which it would need to be inserted. 666 \param key The key. 667 \param exists Is set to \c true, if the map does already contain an 668 entry with that key, to \c false otherwise. 669 \return The index at which the entry with the supplied key is 670 located or at which it would need to be inserted. 671 */ 672 _VECTOR_MAP_TEMPLATE_LIST 673 int32 674 _VECTOR_MAP_CLASS_NAME::_FindInsertionIndex(const Key &key, 675 bool &exists) const 676 { 677 // binary search 678 int32 lower = 0; 679 int32 upper = Count(); 680 while (lower < upper) { 681 int32 mid = (lower + upper) / 2; 682 int cmp = fEntryStrategy.Compare(fEntryStrategy.GetKey(fElements[mid]), 683 key); 684 if (cmp < 0) 685 lower = mid + 1; 686 else 687 upper = mid; 688 } 689 exists = (lower < Count() && fEntryStrategy.Compare(key, 690 fEntryStrategy.GetKey(fElements[lower])) == 0); 691 return lower; 692 } 693 694 695 // entry strategies 696 697 namespace VectorMapEntryStrategy { 698 699 // Pair 700 template<typename Key, typename Value, typename KeyOrder> 701 class Pair { 702 public: 703 typedef const Key &KeyReference; 704 705 class Entry { 706 public: 707 Entry(const Key &key, const Value &value) 708 : key(key), value(value) {} 709 710 Key key; 711 Value value; 712 }; 713 714 inline KeyReference GetKey(const Entry &entry) const 715 { 716 return entry.key; 717 } 718 719 inline const Value &GetValue(const Entry &entry) const 720 { 721 return entry.value; 722 } 723 724 inline Value &GetValue(Entry &entry) const 725 { 726 return entry.value; 727 } 728 729 inline Entry MakeEntry(const Key &key, const Value &value) const 730 { 731 return Entry(key, value); 732 } 733 734 inline bool AreCompatible(const Key &, const Value &) const 735 { 736 return true; 737 } 738 739 inline int Compare(const Key &a, const Key &b) const 740 { 741 return fCompare(a, b); 742 } 743 744 private: 745 KeyOrder fCompare; 746 }; 747 748 // ImplicitKey 749 template<typename Key, typename Value, typename _GetKey, typename KeyOrder> 750 class ImplicitKey { 751 public: 752 typedef Key KeyReference; 753 typedef Value Entry; 754 755 inline KeyReference GetKey(const Entry &entry) const 756 { 757 return fGetKey(entry); 758 } 759 760 inline const Value &GetValue(const Entry &entry) const 761 { 762 return entry; 763 } 764 765 inline Value &GetValue(Entry &entry) const 766 { 767 return entry; 768 } 769 770 inline Entry MakeEntry(const Key &, const Value &value) const 771 { 772 return value; 773 } 774 775 inline bool AreCompatible(const Key &key, const Value &value) const 776 { 777 return (fGetKey(value) == key); 778 } 779 780 inline int Compare(const Key &a, const Key &b) const 781 { 782 return fCompare(a, b); 783 } 784 785 private: 786 KeyOrder fCompare; 787 _GetKey fGetKey; 788 }; 789 790 } // VectorMapEntryStrategy 791 792 #endif // _VECTOR_MAP_H 793