/* * pointainer - auto-cleaning container of pointers * * Example usage: * { * pointainer< std::vector > v; * // v can be manipulated like any std::vector. * * v.push_back(new int(42)); * v.push_back(new int(17)); * // v now owns the allocated int-s * * v.erase(v.begin()); * // frees the memory allocated for the int 42, and then removes the * // first element of v. * } * // v's destructor is called, and it frees the memory allocated for * // the int 17. * * Notes: * 1. Assumes all elements are unique (you don't have two elements * pointing to the same object, otherwise you might delete it twice). * 2. Not usable with pair associative containers (map and multimap). * 3. For ANSI-challenged compilers, you may want to #define * NO_MEMBER_TEMPLATES. * * Written 10-Jan-1999 by Yonat Sharon * Last updated 07-Feb-1999 */ #ifndef POINTAINER_H #define POINTAINER_H #ifdef NO_MEMBER_TEMPLATES #include // for binder2nd #endif template class pointainer : public Cnt { public: using typename Cnt::size_type; using typename Cnt::difference_type; using typename Cnt::reference; using typename Cnt::const_reference; using typename Cnt::value_type; using typename Cnt::iterator; using typename Cnt::const_iterator; using typename Cnt::reverse_iterator; using typename Cnt::const_reverse_iterator; typedef pointainer its_type; pointainer() {} pointainer(const Cnt& c) : Cnt(c) {} its_type& operator=(const Cnt& c) {Cnt::operator=(c); return *this;} ~pointainer() {clean_all();} void clear() {clean_all(); Cnt::clear();} iterator erase(iterator i) {clean(i); return Cnt::erase(i);} iterator erase(iterator f, iterator l) {clean(f,l); return Cnt::erase(f,l);} // for associative containers: erase() a value size_type erase(const value_type& v) { iterator i = find(v); size_type found(i != end()); // can't have more than 1 if (found) erase(i); return found; } // for sequence containers: pop_front(), pop_back(), resize() and assign() void pop_front() {clean(begin()); Cnt::pop_front();} void pop_back() {iterator i(end()); clean(--i); Cnt::pop_back();} void resize(size_type s, value_type c = value_type()) { if (s < size()) clean(begin()+s, end()); Cnt::resize(s, c); } #ifndef NO_MEMBER_TEMPLATES template void assign(InIter f, InIter l) #else void assign(iterator f, iterator l) #endif { clean_all(); Cnt::assign(f,l); } #ifndef NO_MEMBER_TEMPLATES template void assign(Size n, const T& t = T()) #else void assign(size_t n, const value_type& t = value_type()) #endif { clean_all(); Cnt::assign(n,t); } // for std::list: remove() and remove_if() void remove(const value_type& v) { clean( std::find(begin(), end(), v) ); Cnt::remove(v); } #ifndef NO_MEMBER_TEMPLATES template #else typedef std::binder2nd > Pred; #endif void remove_if(Pred pr) { for (iterator i = begin(); i != end(); ++i) if (pr(*i)) clean(i); Cnt::remove_if(pr); } private: void clean(iterator i) {delete *i;} void clean(iterator f, iterator l) {while (f != l) clean(f++);} void clean_all() {clean( begin(), end() );} // we can't have two pointainers own the same objects: pointainer(const its_type&) {} its_type& operator=(const its_type&) {} }; #endif // POINTAINER_H