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