Inferno
0.2
|
00001 /* 00002 * containers.hpp 00003 * 00004 * Created on: 30 Aug 2009 00005 * Author: jgraley 00006 */ 00007 00008 #ifndef CONTAINERS_HPP 00009 #define CONTAINERS_HPP 00010 00011 #include "common.hpp" 00012 00013 /// OOStd namespace contains wrappers for STL and Boost features adding run-time polymorphism 00014 namespace OOStd { 00015 00016 // 00017 // Template for a base class for STL containers with forward iterators. 00018 // Supports direct calls and iterators. 00019 // 00020 // The base container will be derived from SUB_BASE. VALUE_INTERFACE should 00021 // be a base (or compatible type) for the elements of all sub-containers. 00022 // 00023 00024 template< class SUB_BASE, typename VALUE_INTERFACE > 00025 class ContainerInterface : public virtual Traceable, public virtual SUB_BASE 00026 { 00027 public: 00028 // Abstract base class for the implementation-specific iterators in containers. 00029 struct iterator_interface : public Traceable 00030 { 00031 // TODO const iterator and const versions of begin(), end() 00032 virtual shared_ptr<iterator_interface> Clone() const = 0; // Make another copy of the present iterator 00033 virtual iterator_interface &operator++() = 0; 00034 virtual iterator_interface &operator--() { ASSERTFAIL("Only on reversible iterator"); }; 00035 const virtual VALUE_INTERFACE &operator*() const = 0; 00036 const virtual VALUE_INTERFACE *operator->() const = 0; 00037 virtual bool operator==( const iterator_interface &ib ) const = 0; 00038 virtual void Overwrite( const VALUE_INTERFACE *v ) const = 0; 00039 virtual const bool IsOrdered() const = 0; 00040 virtual const int GetCount() const { ASSERTFAIL("Only on CountingIterator"); } 00041 }; 00042 00043 public: 00044 // Wrapper for iterator_interface, uses boost::shared_ptr<> and Clone() to manage the real iterator 00045 // and forwards all the operations using co-variance where possible. These can be passed around 00046 // by value, and have copy-on-write semantics, so big iterators will actually get optimised 00047 // (in your face, Stepanov!) 00048 class iterator : public Traceable 00049 { 00050 public: 00051 typedef forward_iterator_tag iterator_category; 00052 typedef VALUE_INTERFACE value_type; 00053 typedef int difference_type; 00054 typedef const value_type *pointer; 00055 typedef const value_type &reference; 00056 00057 iterator() : 00058 pib( shared_ptr<iterator_interface>() ) {} 00059 00060 iterator( const iterator_interface &ib ) : 00061 pib( ib.Clone() ) {} // Deep copy because from unmanaged source 00062 00063 iterator( const iterator &i ) : 00064 pib( i.pib ) {} // Shallow copy 00065 00066 iterator &operator=( const iterator &i ) 00067 { 00068 pib = i.pib; // Shallow copy 00069 return *this; 00070 } 00071 00072 iterator &operator++() 00073 { 00074 ASSERT(pib)("Attempt to increment uninitialised iterator"); 00075 EnsureUnique(); 00076 pib->operator++(); 00077 return *this; 00078 } 00079 00080 iterator &operator--() 00081 { 00082 ASSERT(pib)("Attempt to increment uninitialised iterator"); 00083 EnsureUnique(); 00084 pib->operator--(); 00085 return *this; 00086 } 00087 00088 const value_type &operator*() const 00089 { 00090 ASSERT(pib)("Attempt to dereference uninitialised iterator"); 00091 return pib->operator*(); 00092 } 00093 00094 const value_type *operator->() const 00095 { 00096 ASSERT(pib)("Attempt to dereference uninitialised iterator"); 00097 return pib->operator->(); 00098 } 00099 00100 bool operator==( const iterator &i ) const 00101 { 00102 ASSERT(pib)("Attempt to compare uninitialised iterator"); 00103 return pib->operator==( *(i.pib) ); 00104 } 00105 00106 bool operator!=( const iterator &i ) const 00107 { 00108 ASSERT(pib)("Attempt to compare uninitialised iterator"); 00109 return !operator==( i ); 00110 } 00111 00112 void Overwrite( const value_type *v ) const 00113 { 00114 ASSERT(pib)("Attempt to Overwrite through uninitialised iterator"); 00115 pib->Overwrite( v ); 00116 } 00117 00118 const bool IsOrdered() const 00119 { 00120 return pib->IsOrdered(); 00121 } 00122 00123 const int GetCount() const 00124 { 00125 return pib->GetCount(); 00126 } 00127 00128 iterator_interface *GetUnderlyingIterator() 00129 { 00130 if( pib ) 00131 return pib.get(); 00132 else 00133 return NULL; 00134 } 00135 00136 virtual shared_ptr<iterator_interface> Clone() // TODO does this need to be virtual? 00137 { 00138 ASSERT(pib)("Attempt to Clone() uninitialised iterator"); 00139 return pib->Clone(); 00140 } 00141 00142 operator string() 00143 { 00144 if( pib ) 00145 return (string)(Traceable::CPPFilt( typeid( *pib ).name() )); 00146 else 00147 return (string)("no-impl"); 00148 } 00149 private: 00150 void EnsureUnique() 00151 { 00152 // Call this before modifying the underlying iterator - Performs a deep copy 00153 // if required to make sure there are no other refs. 00154 if( pib && !pib.unique() ) 00155 pib = Clone(); 00156 ASSERT( !pib || pib.unique() ); 00157 } 00158 00159 shared_ptr<iterator_interface> pib; 00160 }; 00161 typedef iterator const_iterator; // TODO const iterators properly 00162 00163 // These direct calls to the container are designed to support co-variance. 00164 virtual void insert( const VALUE_INTERFACE &gx ) = 0; 00165 virtual const iterator_interface &begin() = 0; 00166 virtual const iterator_interface &end() = 0; 00167 virtual void erase( typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator it ) = 0; 00168 virtual bool empty() const { return size() == 0; } 00169 virtual int size() const 00170 { 00171 // TODO support const_interator properly and get rid of this const_cast 00172 ContainerInterface *nct = const_cast<ContainerInterface *>(this); 00173 int n=0; 00174 FOREACH( const VALUE_INTERFACE &x, *nct ) 00175 n++; 00176 return n; 00177 } 00178 virtual void clear() = 0; 00179 }; 00180 00181 00182 template< class SUB_BASE, typename VALUE_INTERFACE > 00183 struct SequenceInterface : virtual ContainerInterface<SUB_BASE, VALUE_INTERFACE> 00184 { 00185 virtual VALUE_INTERFACE &operator[]( int i ) = 0; 00186 virtual void push_back( const VALUE_INTERFACE &gx ) = 0; 00187 }; 00188 00189 00190 template< class SUB_BASE, typename VALUE_INTERFACE > 00191 struct SimpleAssociativeContainerInterface : virtual ContainerInterface<SUB_BASE, VALUE_INTERFACE> 00192 { 00193 virtual int erase( const VALUE_INTERFACE &gx ) = 0; 00194 virtual bool IsExist( const VALUE_INTERFACE &gx ) = 0; 00195 }; 00196 00197 00198 // 00199 // Abstract template for containers that will be use any STL container as 00200 // the actual implementation. 00201 // Params as for ContainerInterface except we now have to fill in CONTAINER_IMPL 00202 // as the stl container class eg std::list<blah> 00203 // 00204 template<class SUB_BASE, typename VALUE_INTERFACE, class CONTAINER_IMPL> 00205 struct ContainerCommon : virtual ContainerInterface<SUB_BASE, VALUE_INTERFACE>, CONTAINER_IMPL 00206 { 00207 struct iterator : public CONTAINER_IMPL::iterator, 00208 public ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface 00209 { 00210 virtual iterator &operator++() 00211 { 00212 CONTAINER_IMPL::iterator::operator++(); 00213 return *this; 00214 } 00215 00216 virtual iterator &operator--() 00217 { 00218 CONTAINER_IMPL::iterator::operator--(); 00219 return *this; 00220 } 00221 00222 virtual const typename CONTAINER_IMPL::value_type &operator*() const 00223 { 00224 return CONTAINER_IMPL::iterator::operator*(); 00225 } 00226 00227 virtual const typename CONTAINER_IMPL::value_type *operator->() const 00228 { 00229 return CONTAINER_IMPL::iterator::operator->(); 00230 } 00231 00232 virtual bool operator==( const typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface &ib ) const 00233 { 00234 const typename CONTAINER_IMPL::iterator *pi = dynamic_cast<const typename CONTAINER_IMPL::iterator *>(&ib); 00235 ASSERT(pi)("Comparing iterators of different type"); 00236 return *(const typename CONTAINER_IMPL::iterator *)this == *pi; 00237 } 00238 }; 00239 00240 typedef iterator const_iterator; 00241 00242 virtual void erase( typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator it ) 00243 { 00244 iterator *cit = dynamic_cast<iterator *>( it.GetUnderlyingIterator() ); 00245 ASSERT( cit ); // if this fails, you passed erase() the wrong kind of iterator 00246 CONTAINER_IMPL::erase( *(typename CONTAINER_IMPL::iterator *)cit ); 00247 } 00248 virtual bool empty() const 00249 { 00250 return CONTAINER_IMPL::empty(); 00251 } 00252 virtual int size() const 00253 { 00254 return CONTAINER_IMPL::size(); 00255 } 00256 virtual void clear() 00257 { 00258 return CONTAINER_IMPL::clear(); 00259 } 00260 virtual operator string() const 00261 { 00262 return Traceable::CPPFilt( typeid( typename CONTAINER_IMPL::value_type ).name() ); 00263 } 00264 }; 00265 00266 00267 // 00268 // Template for containers that use ordered STL containers as implementation 00269 // (basically vector, deque etc). Instantiate as per ContainerCommon. 00270 // 00271 template<class SUB_BASE, typename VALUE_INTERFACE, class CONTAINER_IMPL> 00272 struct Sequence : virtual ContainerCommon<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>, virtual SequenceInterface<SUB_BASE, VALUE_INTERFACE> 00273 { 00274 using typename CONTAINER_IMPL::insert; // due to silly C++ rule where different overloads hide each other 00275 inline Sequence<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>() {} 00276 struct iterator : public ContainerCommon<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>::iterator 00277 { 00278 inline iterator( typename CONTAINER_IMPL::iterator &i ) : CONTAINER_IMPL::iterator(i) {} 00279 inline iterator() {} 00280 virtual typename CONTAINER_IMPL::value_type &operator*() const 00281 { 00282 return CONTAINER_IMPL::iterator::operator*(); 00283 } 00284 virtual typename CONTAINER_IMPL::value_type *operator->() const 00285 { 00286 return CONTAINER_IMPL::iterator::operator->(); 00287 } 00288 virtual shared_ptr<typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface> Clone() const 00289 { 00290 shared_ptr<iterator> ni( new iterator ); 00291 *ni = *this; 00292 return ni; 00293 } 00294 virtual void Overwrite( const VALUE_INTERFACE *v ) const 00295 { 00296 // JSG Overwrite() just writes through the pointer got from dereferencing the iterator, 00297 // because in Sequences (ordererd containers) elements may be modified. 00298 typename CONTAINER_IMPL::value_type x( CONTAINER_IMPL::value_type::InferredDynamicCast(*v) ); 00299 CONTAINER_IMPL::iterator::operator*() = x; 00300 } 00301 virtual const bool IsOrdered() const 00302 { 00303 return true; // yes, Sequences are ordered 00304 } 00305 }; 00306 00307 virtual typename CONTAINER_IMPL::value_type &operator[]( int i ) 00308 { 00309 return CONTAINER_IMPL::operator[](i); 00310 } 00311 virtual void insert( const VALUE_INTERFACE &gx ) 00312 { 00313 push_back( gx ); 00314 } 00315 virtual void push_back( const VALUE_INTERFACE &gx ) 00316 { 00317 typename CONTAINER_IMPL::value_type sx( CONTAINER_IMPL::value_type::InferredDynamicCast(gx) ); 00318 CONTAINER_IMPL::push_back( sx ); 00319 } 00320 template<typename OTHER> 00321 inline void push_back( const OTHER &gx ) 00322 { 00323 typename CONTAINER_IMPL::value_type sx(gx); 00324 CONTAINER_IMPL::push_back( sx ); 00325 } 00326 00327 // Covariant style only works with refs and pointers, so force begin/end to return refs safely 00328 // This complies with STL's thread safety model. To quote SGI, 00329 // "The SGI implementation of STL is thread-safe only in the sense that simultaneous accesses 00330 // to distinct containers are safe, and simultaneous read accesses to to shared containers are 00331 // safe. If multiple threads access a single container, and at least one thread may potentially 00332 // write, then the user is responsible for ensuring mutual exclusion between the threads during 00333 // the container accesses." 00334 // So that's OK then. 00335 iterator my_begin, my_end; 00336 00337 virtual const iterator &begin() 00338 { 00339 my_begin.CONTAINER_IMPL::iterator::operator=( CONTAINER_IMPL::begin() ); 00340 return my_begin; 00341 } 00342 virtual const iterator &end() 00343 { 00344 my_end.CONTAINER_IMPL::iterator::operator=( CONTAINER_IMPL::end() ); 00345 return my_end; 00346 } 00347 Sequence( const SequenceInterface<SUB_BASE, VALUE_INTERFACE> &cns ) 00348 { 00349 // TODO support const_interator properly and get rid of this const_cast 00350 SequenceInterface<SUB_BASE, VALUE_INTERFACE> *ns = const_cast< SequenceInterface<SUB_BASE, VALUE_INTERFACE> * >( &cns ); 00351 for( typename SequenceInterface<SUB_BASE, VALUE_INTERFACE>::iterator i=ns->begin(); 00352 i != ns->end(); 00353 ++i ) 00354 { 00355 CONTAINER_IMPL::push_back( (typename CONTAINER_IMPL::value_type)*i ); 00356 } 00357 } 00358 Sequence( const VALUE_INTERFACE &nx ) 00359 { 00360 typename CONTAINER_IMPL::value_type sx( CONTAINER_IMPL::value_type::InferredDynamicCast(nx) ); 00361 CONTAINER_IMPL::push_back( sx ); 00362 } 00363 template<typename L, typename R> 00364 inline Sequence( const pair<L, R> &p ) 00365 { 00366 *this = Sequence<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>( p.first ); 00367 Sequence<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL> t( p.second ); 00368 00369 for( typename Sequence<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>::iterator i=t.begin(); 00370 i != t.end(); 00371 ++i ) 00372 { 00373 CONTAINER_IMPL::push_back( *i ); 00374 } 00375 } 00376 inline Sequence( const typename CONTAINER_IMPL::value_type &v ) 00377 { 00378 push_back( v ); 00379 } 00380 }; 00381 00382 00383 // 00384 // Template for containers that use unordered STL containers as implementation 00385 // (basically associative containers). Instantiate as per ContainerCommon. 00386 // 00387 template<class SUB_BASE, typename VALUE_INTERFACE, class CONTAINER_IMPL> 00388 struct SimpleAssociativeContainer : virtual ContainerCommon<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>, virtual SimpleAssociativeContainerInterface<SUB_BASE, VALUE_INTERFACE> 00389 { 00390 inline SimpleAssociativeContainer<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>() {} 00391 struct iterator : public ContainerCommon<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>::iterator 00392 { 00393 inline iterator( typename CONTAINER_IMPL::iterator &i ) : CONTAINER_IMPL::iterator(i) {} 00394 inline iterator() {} 00395 virtual shared_ptr<typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface> Clone() const 00396 { 00397 shared_ptr<iterator> ni( new iterator ); 00398 *ni = *this; 00399 return ni; 00400 } 00401 virtual void Overwrite( const VALUE_INTERFACE *v ) const 00402 { 00403 // SimpleAssociativeContainers (unordered containers) do not allow elements to be modified 00404 // because the internal data structure depends on element values. So we 00405 // erase the old element and insert the new one; thus, Overwrite() should not be assumed O(1) 00406 typename CONTAINER_IMPL::value_type s( CONTAINER_IMPL::value_type::InferredDynamicCast(*v) ); 00407 ((CONTAINER_IMPL *)owner)->erase( *this ); 00408 *(typename CONTAINER_IMPL::iterator *)this = ((CONTAINER_IMPL *)owner)->insert( s ); // become an iterator for the newly inserted element 00409 } 00410 virtual const bool IsOrdered() const 00411 { 00412 return false; // no, SimpleAssociativeContainers are not ordered 00413 } 00414 SimpleAssociativeContainer<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL> *owner; 00415 }; 00416 00417 virtual void insert( const VALUE_INTERFACE &gx ) 00418 { 00419 typename CONTAINER_IMPL::value_type sx( CONTAINER_IMPL::value_type::InferredDynamicCast(gx) ); 00420 CONTAINER_IMPL::insert( sx ); 00421 } 00422 template<typename OTHER> 00423 inline void insert( const OTHER &gx ) 00424 { 00425 typename CONTAINER_IMPL::value_type sx(gx); 00426 CONTAINER_IMPL::insert( sx ); 00427 } 00428 virtual int erase( const VALUE_INTERFACE &gx ) 00429 { 00430 typename CONTAINER_IMPL::value_type sx( CONTAINER_IMPL::value_type::InferredDynamicCast(gx) ); 00431 return CONTAINER_IMPL::erase( sx ); 00432 } 00433 virtual bool IsExist( const VALUE_INTERFACE &gx ) 00434 { 00435 typename CONTAINER_IMPL::value_type sx( CONTAINER_IMPL::value_type::InferredDynamicCast(gx) ); 00436 typename CONTAINER_IMPL::iterator it = CONTAINER_IMPL::find( sx ); 00437 return it != CONTAINER_IMPL::end(); 00438 } 00439 00440 iterator my_begin, my_end; 00441 virtual const iterator &begin() 00442 { 00443 my_begin.CONTAINER_IMPL::iterator::operator=( CONTAINER_IMPL::begin() ); 00444 my_begin.owner = this; 00445 return my_begin; 00446 } 00447 virtual const iterator &end() 00448 { 00449 my_end.CONTAINER_IMPL::iterator::operator=( CONTAINER_IMPL::end() ); 00450 my_end.owner = this; 00451 return my_end; 00452 } 00453 SimpleAssociativeContainer( const ContainerInterface<SUB_BASE, VALUE_INTERFACE> &cns ) 00454 { 00455 // TODO support const_interator properly and get rid of this const_cast 00456 ContainerInterface<SUB_BASE, VALUE_INTERFACE> *ns = const_cast< ContainerInterface<SUB_BASE, VALUE_INTERFACE> * >( &cns ); 00457 for( typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator i=ns->begin(); 00458 i != ns->end(); 00459 ++i ) 00460 { 00461 CONTAINER_IMPL::insert( *i ); 00462 } 00463 } 00464 SimpleAssociativeContainer( const VALUE_INTERFACE &nx ) 00465 { 00466 typename CONTAINER_IMPL::value_type sx( CONTAINER_IMPL::value_type::InferredDynamicCast(nx) ); 00467 CONTAINER_IMPL::insert( sx ); 00468 } 00469 template<typename L, typename R> 00470 inline SimpleAssociativeContainer( const pair<L, R> &p ) 00471 { 00472 *this = SimpleAssociativeContainer<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>( p.first ); 00473 SimpleAssociativeContainer<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL> t( p.second ); 00474 00475 for( typename SimpleAssociativeContainer<SUB_BASE, VALUE_INTERFACE, CONTAINER_IMPL>::iterator i=t.begin(); 00476 i != t.end(); 00477 ++i ) 00478 { 00479 CONTAINER_IMPL::insert( *i ); 00480 } 00481 } 00482 inline SimpleAssociativeContainer( const typename CONTAINER_IMPL::value_type &v ) 00483 { 00484 insert( v ); 00485 } 00486 }; 00487 00488 // 00489 // Iterator that points to a single object, no container required. 00490 // We do not support looping/incrementing or FOREACH (which requires a 00491 // container) but we do permit compare, deref and Overwrite(). This lets 00492 // ContainerInterface::iterator be used generically even when objects are 00493 // not in containers. 00494 // 00495 template<class SUB_BASE, typename VALUE_INTERFACE> 00496 struct PointIterator : public ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface 00497 { 00498 VALUE_INTERFACE * element; 00499 00500 PointIterator() : 00501 element(NULL) // means end-of-range 00502 { 00503 } 00504 00505 PointIterator( const PointIterator &other ) : 00506 element(other.element) 00507 { 00508 } 00509 00510 PointIterator( VALUE_INTERFACE *i ) : 00511 element(i) 00512 { 00513 ASSERT(i); // We don't allow NULL as input because it means end-of-range 00514 } 00515 00516 virtual shared_ptr<typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface> Clone() const 00517 { 00518 shared_ptr<PointIterator> ni( new PointIterator(*this) ); 00519 return ni; 00520 } 00521 00522 virtual PointIterator &operator++() 00523 { 00524 element = NULL; // ie if we increment, we get to the end of the range 00525 return *this; 00526 } 00527 00528 virtual VALUE_INTERFACE &operator*() const 00529 { 00530 ASSERT(element)("Tried to dereference NULL PointIterator"); 00531 return *element; 00532 } 00533 00534 virtual VALUE_INTERFACE *operator->() const 00535 { 00536 ASSERT(element)("Tried to dereference NULL PointIterator"); 00537 return element; 00538 } 00539 00540 virtual bool operator==( const typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface &ib ) const 00541 { 00542 const PointIterator *pi = dynamic_cast<const PointIterator *>(&ib); 00543 ASSERT(pi)("Comparing point iterator with something else ")(ib); 00544 return pi->element == element; 00545 } 00546 00547 virtual void Overwrite( const VALUE_INTERFACE *v ) const 00548 { 00549 *element = *v; 00550 } 00551 00552 virtual const bool IsOrdered() const 00553 { 00554 return true; // shouldn't matter what we return here 00555 } 00556 }; 00557 00558 template<class SUB_BASE, typename VALUE_INTERFACE> 00559 struct CountingIterator : public ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface 00560 { 00561 int element; 00562 00563 CountingIterator() : 00564 element(0) 00565 { 00566 } 00567 00568 CountingIterator( int i ) : 00569 element(i) 00570 { 00571 } 00572 00573 virtual shared_ptr<typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface> Clone() const 00574 { 00575 shared_ptr<CountingIterator> ni( new CountingIterator(*this) ); 00576 return ni; 00577 } 00578 00579 virtual CountingIterator &operator++() 00580 { 00581 element++; 00582 return *this; 00583 } 00584 00585 virtual CountingIterator &operator--() 00586 { 00587 element--; 00588 return *this; 00589 } 00590 00591 virtual VALUE_INTERFACE &operator*() const 00592 { 00593 ASSERTFAIL("Cannot dereference CountingIterator, use GetCount instead"); 00594 } 00595 00596 const virtual VALUE_INTERFACE *operator->() const 00597 { 00598 ASSERTFAIL("Cannot dereference CountingIterator, use GetCount instead"); 00599 } 00600 00601 virtual bool operator==( const typename ContainerInterface<SUB_BASE, VALUE_INTERFACE>::iterator_interface &ib ) const 00602 { 00603 const CountingIterator *pi = dynamic_cast<const CountingIterator *>(&ib); 00604 ASSERT(pi)("Comparing counting iterator with something else ")( ib ); 00605 return pi->element == element; 00606 } 00607 00608 virtual void Overwrite( const VALUE_INTERFACE *v ) const 00609 { 00610 ASSERTFAIL("Cannot Overwrite through CountingIterator"); 00611 } 00612 00613 virtual const bool IsOrdered() const 00614 { 00615 return true; // counting iterator counts 1, 2, 3, like that, so seems to be ordered 00616 } 00617 00618 const int GetCount() const 00619 { 00620 return element; 00621 } 00622 }; 00623 00624 // Allow operator, to be used to create pairs. Also handy for maps. 00625 template<typename L, typename R> 00626 inline pair<L,R> operator,( const L &l, const R &r ) 00627 { 00628 return pair<L,R>(l,r); 00629 } 00630 00631 }; // namespace 00632 00633 #endif /* GENERICS_HPP */