variant_filter_iterator.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 #ifndef LIBMESH_VARIANT_FILTER_ITERATOR_H
19 #define LIBMESH_VARIANT_FILTER_ITERATOR_H
20 
21 
22 // C++ includes
23 #include <algorithm> // for std::swap
24 #include <cstddef>
25 #include <cstdlib> // for std::abort()
26 #include <iterator>
27 
28 #if defined(__GNUC__) && (__GNUC__ < 3) && !defined(__INTEL_COMPILER)
29 #include <typeinfo>
30 #endif
31 
32 // Local includes
33 #include "libmesh/libmesh_common.h" // for cast_ptr()
34 
49 template<class Predicate, class Type, class ReferenceType = Type &, class PointerType = Type *>
51 #if defined(__GNUC__) && (__GNUC__ < 3) && !defined(__INTEL_COMPILER)
52  public std::forward_iterator<std::forward_iterator_tag, Type>
53 #else
54  public std::iterator<std::forward_iterator_tag, Type>
55 #endif
56 {
57 public:
61  typedef variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> Iterator;
62 
63 
64 
65 public:
72  struct IterBase
73  {
74  virtual ~IterBase() {}
75  virtual IterBase * clone() const = 0;
76 
80  virtual ReferenceType operator*() const = 0;
81 
85  virtual IterBase & operator++() = 0;
86 
87  virtual bool equal(const IterBase * other) const = 0;
88 
89  // Similar to clone function above, but returns a pointer to a copy of a different type.
90  // typedef typename variant_filter_iterator<Predicate, Type, const Type &, const Type *>::IterBase const_IterBase;
91  typedef typename variant_filter_iterator<Predicate, Type const, Type const & , Type const *>::IterBase const_IterBase;
92  virtual const_IterBase * const_clone() const = 0;
93  };
94 
95 
96 
97 
98 
99 
100 
104  struct PredBase
105  {
106  virtual ~PredBase() {}
107  virtual PredBase * clone() const = 0;
108  virtual bool operator()(const IterBase * in) const = 0;
109 
110  // Similar to clone function above, but returns a pointer to a copy of a different type.
111  // typedef typename variant_filter_iterator<Predicate, Type, const Type &, const Type *>::PredBase const_PredBase;
112  typedef typename variant_filter_iterator<Predicate, Type const, Type const &, Type const *>::PredBase const_PredBase;
113  virtual const_PredBase * const_clone() const = 0;
114  };
115 
116 
117 
118 
119 
120 
121 
125  template<typename IterType>
126  struct Iter : IterBase
127  {
128 
132  Iter (const IterType & v) :
133  iter_data (v)
134  {
135  // libMesh::out << "In Iter<IterType>::Iter(const IterType & v)" << std::endl;
136  }
137 
138 
142  Iter (const Iter & other) :
143  iter_data(other.iter_data)
144  {}
145 
146 
150  virtual ~Iter () {}
151 
156  virtual IterBase * clone() const libmesh_override
157  {
158 #ifdef __SUNPRO_CC
159  variant_filter_iterator::Iter<IterType> * copy =
160  new variant_filter_iterator::Iter<IterType>(iter_data);
161 #else
162  Iter<IterType> * copy =
163  new Iter<IterType>(iter_data);
164 #endif
165 
166  return copy;
167  }
168 
173  virtual typename IterBase::const_IterBase * const_clone() const libmesh_override
174  {
178  // typedef typename variant_filter_iterator<Predicate, Type, const Type &, const Type *>::template Iter<IterType> const_Iter;
179  typedef typename variant_filter_iterator<Predicate, Type const, Type const &, Type const *>::template Iter<IterType> const_Iter;
180 
181  typename IterBase::const_IterBase * copy =
182  new const_Iter(iter_data);
183 
184  return copy;
185  }
186 
190  virtual ReferenceType operator*() const libmesh_override
191  {
192  return * iter_data;
193  }
194 
198  virtual Iter & operator++() libmesh_override
199  {
200  ++iter_data;
201  return *this;
202  }
203 
210  virtual bool equal(const IterBase * other) const libmesh_override
211  {
212 #if defined(__SUNPRO_CC) || (defined(__GNUC__) && (__GNUC__ < 3) && !defined(__INTEL_COMPILER))
213  const variant_filter_iterator::Iter<IterType> * p =
214  libMesh::cast_ptr<const variant_filter_iterator::Iter<IterType> *>(other);
215 #else
216  const Iter<IterType> * p =
217  libMesh::cast_ptr<const Iter<IterType> *>(other);
218 #endif
219 
220  return (iter_data == p->iter_data);
221  }
222 
226  IterType iter_data;
227  };
228 
229 
230 
231 
237  template <typename IterType, typename PredType>
238  struct Pred : PredBase
239  {
243  Pred (const PredType & v) :
244  pred_data (v) {}
245 
249  virtual ~Pred () {}
250 
254  virtual PredBase * clone() const libmesh_override
255  {
256 #ifdef __SUNPRO_CC
257  variant_filter_iterator::Pred<IterType,PredType> * copy =
258  new variant_filter_iterator::Pred<IterType,PredType>(pred_data);
259 #else
260  Pred<IterType,PredType> * copy =
261  new Pred<IterType,PredType>(pred_data);
262 #endif
263 
264  return copy;
265  }
266 
267 
272  virtual typename PredBase::const_PredBase * const_clone() const libmesh_override
273  {
277  // typedef typename variant_filter_iterator<Predicate, Type, const Type &, const Type *>::template Pred<IterType, PredType> const_Pred;
278  typedef typename variant_filter_iterator<Predicate, Type const, Type const &, Type const *>::template Pred<IterType, PredType> const_Pred;
279 
280 
281  typename PredBase::const_PredBase * copy =
282  new const_Pred(pred_data);
283 
284  return copy;
285  }
286 
287 
288 
289 
293  virtual bool operator() (const IterBase * in) const libmesh_override
294  {
295  libmesh_assert(in);
296 
297  // Attempt downcast
298 #if defined(__SUNPRO_CC) || (defined(__GNUC__) && (__GNUC__ < 3) && !defined(__INTEL_COMPILER))
299  const variant_filter_iterator::Iter<IterType> * p =
300  libMesh::cast_ptr<const variant_filter_iterator::Iter<IterType> * >(in);
301 #else
302  const Iter<IterType> * p =
303  libMesh::cast_ptr<const Iter<IterType> *>(in);
304 #endif
305 
306  // Return result of op() for the user's predicate.
307  return pred_data(p->iter_data);
308  }
309 
313  PredType pred_data;
314  };
315 
316 
317 
318 public:
328  IterBase * data;
329 
334  IterBase * end;
335 
341  PredBase * pred;
342 
343 
344 
345 public:
351  template<typename PredType, typename IterType>
352  variant_filter_iterator (const IterType & d,
353  const IterType & e,
354  const PredType & p ):
355  data ( new Iter<IterType>(d) ), // note: uses default IterBase copy constructor
356  end ( new Iter<IterType>(e) ),
357  pred ( new Pred<IterType,PredType>(p) )
358  {
359  this->satisfy_predicate();
360  }
361 
366  data(libmesh_nullptr),
367  end(libmesh_nullptr),
368  pred(libmesh_nullptr) {}
369 
374  variant_filter_iterator (const Iterator & rhs) :
375  data (rhs.data != libmesh_nullptr ? rhs.data->clone() : libmesh_nullptr),
376  end (rhs.end != libmesh_nullptr ? rhs.end->clone() : libmesh_nullptr),
377  pred (rhs.pred != libmesh_nullptr ? rhs.pred->clone() : libmesh_nullptr) {}
378 
379 
380 
392  template <class OtherType, class OtherReferenceType, class OtherPointerType>
393  variant_filter_iterator (const variant_filter_iterator<Predicate, OtherType, OtherReferenceType, OtherPointerType> & rhs)
394  : data (rhs.data != libmesh_nullptr ? rhs.data->const_clone() : libmesh_nullptr),
395  end (rhs.end != libmesh_nullptr ? rhs.end->const_clone() : libmesh_nullptr),
396  pred (rhs.pred != libmesh_nullptr ? rhs.pred->const_clone() : libmesh_nullptr)
397  {
398  // libMesh::out << "Called templated copy constructor for variant_filter_iterator" << std::endl;
399  }
400 
401 
402 
403 
404 
405 
410  {
411  delete data; data = libmesh_nullptr;
412  delete end; end = libmesh_nullptr;
413  delete pred; pred = libmesh_nullptr;
414  }
415 
419  ReferenceType operator*() const
420  {
421  return **data;
422  }
423 
424 
428  PointerType operator->() const
429  {
430  return (&**this);
431  }
432 
436  Iterator & operator++()
437  {
438  ++*data;
439  this->satisfy_predicate();
440  return (*this);
441  }
442 
446  const Iterator operator++(int) // const here to prevent iterator++++ type operations
447  {
448  Iterator oldValue(*this); // standard is to return old value
449  ++*data;
450  this->satisfy_predicate();
451  return oldValue;
452  }
453 
460  bool equal(const variant_filter_iterator & other) const
461  {
462  return data->equal(other.data);
463  }
464 
468  void swap(Iterator & lhs, Iterator & rhs)
469  {
470  // Swap the data pointers
471  std::swap (lhs.data, rhs.data);
472 
473  // Swap the end pointers
474  std::swap (lhs.end, rhs.end);
475 
476  // Also swap the predicate objects.
477  std::swap (lhs.pred, rhs.pred);
478  }
479 
483  Iterator & operator=(const Iterator & rhs)
484  {
485  Iterator temp(rhs);
486  swap(temp, *this);
487  return *this;
488  }
489 
490 
491 
492 private:
493 
499  {
500  while ( !data->equal(end) && !(*pred)(data) )
501  ++(*data);
502  }
503 };
504 
505 
506 
507 
508 
509 
510 //---------------------------------------------------------------------------
511 // op==
512 template<class Predicate, class Type, class ReferenceType, class PointerType>
513 inline
514 bool operator==(const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> & x,
515  const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> & y)
516 {
517  return x.equal(y);
518 }
519 
520 
521 
522 // op!=
523 template<class Predicate, class Type, class ReferenceType, class PointerType>
524 inline
525 bool operator!=(const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> & x,
526  const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> & y)
527 {
528  return !(x == y);
529 }
530 
531 
532 
533 #endif // LIBMESH_VARIANT_FILTER_ITERATOR_H
variant_filter_iterator(const IterType &d, const IterType &e, const PredType &p)
PredType pred_data
virtual PredBase * clone() const libmesh_override
const class libmesh_nullptr_t libmesh_nullptr
IterBase * end
virtual PredBase::const_PredBase * const_clone() const libmesh_override
libmesh_assert(j)
virtual ~Pred()
IterType iter_data
bool operator!=(const variant_filter_iterator< Predicate, Type, ReferenceType, PointerType > &x, const variant_filter_iterator< Predicate, Type, ReferenceType, PointerType > &y)
ReferenceType operator*() const
PetscErrorCode Vec x
void satisfy_predicate()
PointerType operator->() const
PredBase * pred
virtual ~variant_filter_iterator()
Iterator & operator++()
void swap(Iterator &lhs, Iterator &rhs)
bool operator==(const variant_filter_iterator< Predicate, Type, ReferenceType, PointerType > &x, const variant_filter_iterator< Predicate, Type, ReferenceType, PointerType > &y)
Iterator & operator=(const Iterator &rhs)
Pred(const PredType &v)
IterBase * data
bool equal(const variant_filter_iterator &other) const