$extrastylesheet
variant_filter_iterator.h
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 #ifndef LIBMESH_VARIANT_FILTER_ITERATOR_H
00019 #define LIBMESH_VARIANT_FILTER_ITERATOR_H
00020 
00021 
00022 // C++ includes
00023 #include <algorithm> // for std::swap
00024 #include <cstddef>
00025 #include <cstdlib>   // for std::abort()
00026 #include <iterator>
00027 
00028 #if defined(__GNUC__) && (__GNUC__ < 3)  && !defined(__INTEL_COMPILER)
00029 #include <typeinfo>
00030 #endif
00031 
00032 // Local includes
00033 #include "libmesh/libmesh_common.h" // for cast_ptr()
00034 
00048 template<class Predicate, class Type, class ReferenceType = Type&, class PointerType = Type*>
00049 class variant_filter_iterator :
00050 #if defined(__GNUC__) && (__GNUC__ < 3)  && !defined(__INTEL_COMPILER)
00051   public std::forward_iterator<std::forward_iterator_tag, Type>
00052 #else
00053   public std::iterator<std::forward_iterator_tag,  Type>
00054 #endif
00055 {
00056 public:
00060   typedef variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> Iterator;
00061 
00062 
00063 
00064 public:
00071   struct IterBase
00072   {
00073     virtual ~IterBase() {}
00074     virtual  IterBase* clone() const = 0 ;
00075     virtual ReferenceType operator*() const = 0;    // <-- CUSTOM INTERFACE METHOD
00076     virtual IterBase& operator++() = 0;          // <-- CUSTOM INTERFACE METHOD
00077     virtual bool equal(const IterBase *other) const = 0;
00078 
00079     // Similar to clone function above, but returns a pointer to a copy of a different type.
00080     // typedef typename variant_filter_iterator<Predicate, Type, const Type&, const Type*>::IterBase const_IterBase;
00081     typedef typename variant_filter_iterator<Predicate, Type const, Type const & , Type const*>::IterBase const_IterBase;
00082     virtual const_IterBase* const_clone() const = 0;
00083   };
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00094   struct PredBase
00095   {
00096     virtual ~PredBase() {}
00097     virtual PredBase* clone() const = 0 ;
00098     virtual bool operator()(const IterBase* in) const = 0;
00099 
00100     // Similar to clone function above, but returns a pointer to a copy of a different type.
00101     // typedef typename variant_filter_iterator<Predicate, Type, const Type&, const Type*>::PredBase const_PredBase;
00102     typedef typename variant_filter_iterator<Predicate, Type const,  Type const &,  Type const *>::PredBase const_PredBase;
00103     virtual const_PredBase* const_clone() const = 0;
00104   };
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00115   template<typename IterType>
00116   struct Iter : IterBase
00117   {
00118 
00122     Iter (const IterType& v) :
00123       iter_data (v)
00124     {
00125       // libMesh::out << "In Iter<IterType>::Iter(const IterType& v)" << std::endl;
00126     }
00127 
00128 
00132     Iter (const Iter& other) :
00133       iter_data(other.iter_data)
00134     {}
00135 
00136 
00140     virtual ~Iter () {}
00141 
00146     virtual IterBase* clone() const
00147     {
00148 #ifdef __SUNPRO_CC
00149       variant_filter_iterator::Iter<IterType> *copy =
00150         new variant_filter_iterator::Iter<IterType>(iter_data);
00151 #else
00152       Iter<IterType> *copy =
00153         new Iter<IterType>(iter_data);
00154 #endif
00155 
00156       return copy;
00157     }
00158 
00163     virtual typename IterBase::const_IterBase* const_clone() const
00164     {
00168       // typedef typename variant_filter_iterator<Predicate, Type, const Type&, const Type*>::template Iter<IterType> const_Iter;
00169       typedef typename variant_filter_iterator<Predicate, Type const, Type const &,  Type const *>::template Iter<IterType> const_Iter;
00170 
00171       typename IterBase::const_IterBase* copy =
00172         new const_Iter(iter_data);
00173 
00174       return copy;
00175     }
00176 
00180     virtual ReferenceType operator*() const   // <-- CUSTOM INTERFACE METHOD
00181     {
00182       return *iter_data;
00183     }
00184 
00188     virtual Iter& operator++()         // <-- CUSTOM INTERFACE METHOD
00189     {
00190       ++iter_data;
00191       return *this;
00192     }
00193 
00200     virtual bool equal(const IterBase *other) const
00201     {
00202 #if defined(__SUNPRO_CC) || (defined(__GNUC__) && (__GNUC__ < 3)  && !defined(__INTEL_COMPILER))
00203       const variant_filter_iterator::Iter<IterType>* p =
00204         libMesh::cast_ptr<const variant_filter_iterator::Iter<IterType>*>(other);
00205 #else
00206       const Iter<IterType>* p =
00207         libMesh::cast_ptr<const Iter<IterType>*>(other);
00208 #endif
00209 
00210       return (iter_data == p->iter_data);
00211     }
00212 
00216     IterType iter_data;
00217   };
00218 
00219 
00220 
00221 
00227   template <typename IterType, typename PredType>
00228   struct Pred : PredBase
00229   {
00233     Pred (const PredType& v) :
00234       pred_data (v) {}
00235 
00239     virtual ~Pred () {}
00240 
00244     virtual PredBase* clone() const
00245     {
00246 #ifdef __SUNPRO_CC
00247       variant_filter_iterator::Pred<IterType,PredType> *copy =
00248         new variant_filter_iterator::Pred<IterType,PredType>(pred_data);
00249 #else
00250       Pred<IterType,PredType> *copy =
00251         new Pred<IterType,PredType>(pred_data);
00252 #endif
00253 
00254       return copy;
00255     }
00256 
00257 
00262     virtual typename PredBase::const_PredBase* const_clone() const
00263     {
00267       //      typedef typename variant_filter_iterator<Predicate, Type, const Type&, const Type*>::template Pred<IterType, PredType> const_Pred;
00268       typedef typename variant_filter_iterator<Predicate, Type const, Type const &,  Type const *>::template Pred<IterType, PredType> const_Pred;
00269 
00270 
00271       typename PredBase::const_PredBase* copy =
00272         new const_Pred(pred_data);
00273 
00274       return copy;
00275     }
00276 
00277 
00278 
00279 
00283     virtual bool operator() (const IterBase* in) const
00284     {
00285       libmesh_assert(in);
00286 
00287       // Attempt downcast
00288 #if defined(__SUNPRO_CC) || (defined(__GNUC__) && (__GNUC__ < 3)  && !defined(__INTEL_COMPILER))
00289       const variant_filter_iterator::Iter<IterType>* p =
00290         libMesh::cast_ptr<const variant_filter_iterator::Iter<IterType>* >(in);
00291 #else
00292       const Iter<IterType>* p =
00293         libMesh::cast_ptr<const Iter<IterType>* >(in);
00294 #endif
00295 
00296       // Return result of op() for the user's predicate.
00297       return pred_data(p->iter_data);
00298     }
00299 
00303     PredType pred_data;
00304   };
00305 
00306 
00307 
00308 public:
00318   IterBase* data;
00319 
00324   IterBase* end;
00325 
00331   PredBase* pred;
00332 
00333 
00334 
00335 public:
00341   template<typename PredType, typename IterType>
00342   variant_filter_iterator (const IterType& d,
00343                            const IterType& e,
00344                            const PredType& p ):
00345     data ( new Iter<IterType>(d) ), // note: uses default IterBase copy constructor
00346     end  ( new Iter<IterType>(e) ),
00347     pred ( new Pred<IterType,PredType>(p) )
00348   {
00349     this->satisfy_predicate();
00350   }
00351 
00355   variant_filter_iterator () :
00356     data(NULL),
00357     end(NULL),
00358     pred(NULL) {}
00359 
00364   variant_filter_iterator (const Iterator& rhs) :
00365     data (rhs.data != NULL ? rhs.data->clone() : NULL),
00366     end  (rhs.end  != NULL ? rhs.end->clone()  : NULL),
00367     pred (rhs.pred != NULL ? rhs.pred->clone() : NULL) {}
00368 
00369 
00370 
00382   template <class OtherType, class OtherReferenceType, class OtherPointerType>
00383   variant_filter_iterator (const variant_filter_iterator<Predicate, OtherType, OtherReferenceType, OtherPointerType>& rhs)
00384     : data (rhs.data != NULL ? rhs.data->const_clone() : NULL),
00385       end  (rhs.end  != NULL ? rhs.end->const_clone()  : NULL),
00386       pred (rhs.pred != NULL ? rhs.pred->const_clone() : NULL)
00387   {
00388     // libMesh::out << "Called templated copy constructor for variant_filter_iterator" << std::endl;
00389   }
00390 
00391 
00392 
00393 
00394 
00395 
00399   virtual ~variant_filter_iterator()
00400   {
00401     delete data; data = NULL;
00402     delete end;  end  = NULL;
00403     delete pred; pred = NULL;
00404   }
00405 
00409   ReferenceType operator*() const
00410   {
00411     return **data;
00412   }
00413 
00414 
00418   PointerType operator->() const
00419   {
00420     return (&**this);
00421   }
00422 
00426   Iterator& operator++()
00427   {
00428     ++*data;
00429     this->satisfy_predicate();
00430     return (*this);
00431   }
00432 
00436   const Iterator operator++(int) // const here to prevent iterator++++ type operations
00437   {
00438     Iterator oldValue(*this); // standard is to return old value
00439     ++*data;
00440     this->satisfy_predicate();
00441     return oldValue;
00442   }
00443 
00450   bool equal(const variant_filter_iterator& other) const
00451   {
00452     return data->equal(other.data);
00453   }
00454 
00458   void swap(Iterator& lhs, Iterator& rhs)
00459   {
00460     // Swap the data pointers
00461     std::swap (lhs.data, rhs.data);
00462 
00463     // Swap the end pointers
00464     std::swap (lhs.end, rhs.end);
00465 
00466     // Also swap the predicate objects.
00467     std::swap (lhs.pred, rhs.pred);
00468   }
00469 
00473   Iterator& operator=(const Iterator& rhs)
00474   {
00475     Iterator temp(rhs);
00476     swap(temp, *this);
00477     return *this;
00478   }
00479 
00480 
00481 
00482 private:
00483 
00488   void satisfy_predicate()
00489   {
00490     while ( !data->equal(end) && !(*pred)(data) )
00491       ++(*data);
00492   }
00493 };
00494 
00495 
00496 
00497 
00498 
00499 
00500 //---------------------------------------------------------------------------
00501 // op==
00502 template<class Predicate, class Type, class ReferenceType, class PointerType>
00503 inline
00504 bool operator==(const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType>& x,
00505                 const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType>& y)
00506 {
00507   return x.equal(y);
00508 }
00509 
00510 
00511 
00512 // op!=
00513 template<class Predicate, class Type, class ReferenceType, class PointerType>
00514 inline
00515 bool operator!=(const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType>& x,
00516                 const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType>& y)
00517 {
00518   return !(x == y);
00519 }
00520 
00521 
00522 
00523 #endif // LIBMESH_VARIANT_FILTER_ITERATOR_H