_PROGRAMMING WITH THE STANDARD TEMPLATE LIBRARY_ by Thomas Keffer Figure 1: (a) int* find1(int* first, int* end, const int& value) { while(first != end && *first != value) first++; return first; } (b) int a[20]; // ... fill the array "a" ... int* pos = find1(a, a+20, 5); // Searches a[0] through a[19] // Returns &a[20] on failure assert( pos==a+20 || *pos == 5 ); (c) template T* find2(T* first, T* end, const T& value) { while(first != end && *first != value) first++; return first; } (d) class Foo { ... }; bool operator!=(const Foo&, const Foo&); Foo fa[20]; // ... fill the array "fa" ... Foo f; Foo* pos = find2(fa, fa+20, f); assert( pos==fa+20 || !(*pos!=f) ); Figure 2: template InputIterator find(InputIterator first, InputIterator end, const T& value) { while(first != end && *first != value) first++; return first; } Figure 3: (a) // Forward declaration: template class ListIterator; template struct Link { Link* next_; T val_; Link(T p) : val_(p), next_(0) {;} }; template class List { Link* head_; public: typedef ListIterator iterator; List() : head_(0) {;} void addLink(Link* link) {link->next_=head_; head_=link;} ListIterator begin() const {return ListIterator(head_);} ListIterator end() const {return ListIterator(0);} friend class ListIterator; }; (b) template class ListIterator { Link* current_; public: ListIterator(Link* link) : current_(link) {;} T operator*() {return current_->val_;} void operator++(int) { current_ = current_->next_; } int operator!=(const ListIterator& it) {return current_!=it.current_;} }; Figure 4: int main() { List list; list.addLink(new Link(1)); list.addLink(new Link(2)); list.addLink(new Link(3)); list.addLink(new Link(4)); List::iterator pos = find(list.begin(), list.end(),2); assert(*pos == 2); List::iterator pos2 = find(list.begin(), list.end(),6); assert(!(pos2 != list.end())); return 0; } Figure 5: (a) vector v(10), x(10); // ... // Oops! vector::const_iterator position = find(v.begin(), x.end(), 5); assert(*position == 5); (b) void main() { list a, b; for(int i=0; i<10; i++) { a.push_front(i); b.push_front(i); } remove(a.begin(), a.end(), 5); assert(a.size()==9); // fails b.remove(5); assert(b.size()==9); // OK } Figure 6: (a) template class MyVector : public vector { public: .size_t index(const T& val) const; void sort(); .}; template size_t MyVector::index(const T& val) const { const_iterator pos = ::find(begin(), end(), val); return pos==end() ? (size_t)(-1) : pos-begin(); } template void MyVector::sort() { sort(begin(), end()); } (b) MyVector v(10); .size_t position = v.index(5); // Much simpler interface assert(v[position] == 5); Figure 7: (a) MyVector v(10); .// Sort only the first 7 elements, using the STL sort // algorithm: sort(v.begin(), v.begin()+7); (b) void foo(const vector&); void main() { MyVector v(10); foo(v); // OK } (c) template class MyVector_MT { private: Lock lock_; MyVector vec_; public: ... size_t index(const T&) const; void sort(); . }; (d) template void MyVector_MT::sort() { lock_.lock(); // Acquire lock vec_.sort(); // Call non MT-hot algorithm lock_.unlock(); // Release lock }