$extrastylesheet
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