1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2020 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 
35 /**
36  * Original Authors: Corwin Joy          * Michael Gradman
37  *                   cjoy@houston.rr.com * Michael.Gradman@caminus.com
38  * Caminus, Suite 1150, Two Allen Center, 1200 Smith Street, Houston, TX 77002
39  * This class is an extension of variant_bidirectional_iterator to a
40  * filter_iterator similar to boost's.  The filter iterator is modeled
41  * after a forward_iterator since to go backward and forward requires
42  * the storage of both a "begin" and "end" iterator to avoid stepping
43  * off the end or the beginning.  To reduce complexity, we only allow
44  * traversal in one direction.
45  *
46  * \author John W. Peterson
47  * \date 2004
48  */
49 template<class Predicate, class Type, class ReferenceType = Type &, class PointerType = Type *>
50 class variant_filter_iterator :
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:
58   /**
59    * Shortcut name for the fully-qualified typename.
60    */
61   typedef variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> Iterator;
62 
63 
64 
65 public:
66   /**
67    * Abstract base class for the iterator type.  Ideally these mixin classes would be protected,
68    * but due to the fact that different templated versions of the same class (which are not related
69    * by inheritance) need to be able to see each other's IterBase and PredBase members.  Thus, the
70    * mixin classes are in the public interface.
71    */
72   struct IterBase
73   {
~IterBaseIterBase74     virtual ~IterBase() {}
75     virtual  IterBase * clone() const = 0;
76 
77     /**
78      * Dereferences the iterator.
79      */
80     virtual ReferenceType operator*() const = 0;
81 
82     /**
83      * Pre-increments the iterator.
84      */
85     virtual IterBase & operator++() = 0;
86 
87     virtual bool equal(const IterBase * other) const = 0;
88 
89     // typedef typename variant_filter_iterator<Predicate, Type, const Type &, const Type *>::IterBase const_IterBase;
90     typedef typename variant_filter_iterator<Predicate, Type const, Type const & , Type const *>::IterBase const_IterBase;
91 
92     /**
93      * Similar to the \p clone() function.
94      *
95      * \returns A pointer to a copy of a different type.
96      */
97     virtual const_IterBase * const_clone() const = 0;
98   };
99 
100 
101 
102 
103 
104 
105 
106   /**
107    * Abstract base class for the predicate.
108    */
109   struct PredBase
110   {
~PredBasePredBase111     virtual ~PredBase() {}
112     virtual PredBase * clone() const = 0;
113     virtual bool operator()(const IterBase * in) const = 0;
114 
115     // typedef typename variant_filter_iterator<Predicate, Type, const Type &, const Type *>::PredBase const_PredBase;
116     typedef typename variant_filter_iterator<Predicate, Type const, Type const &, Type const *>::PredBase const_PredBase;
117 
118     /**
119      * Similar to the \p clone() function.
120      *
121      * \returns A pointer to a copy of a different type.
122      */
123     virtual const_PredBase * const_clone() const = 0;
124   };
125 
126 
127 
128 
129 
130 
131 
132   /**
133    * The actual iterator object is held as a template parameter here.
134    */
135   template<typename IterType>
136   struct Iter : IterBase
137   {
138 
139     /**
140      * Constructor
141      */
IterIter142     Iter (const IterType & v) :
143       iter_data (v)
144     {
145       // libMesh::out << "In Iter<IterType>::Iter(const IterType & v)" << std::endl;
146     }
147 
148 
149     /**
150      * Copy Constructor.
151      */
IterIter152     Iter (const Iter & other) :
153       iter_data(other.iter_data)
154     {}
155 
156 
157     /**
158      * Destructor
159      */
~IterIter160     virtual ~Iter () {}
161 
162     /**
163      * \returns A copy of this object as a pointer to
164      * the base (non-templated) class.
165      */
cloneIter166     virtual IterBase * clone() const override
167     {
168 #ifdef __SUNPRO_CC
169       variant_filter_iterator::Iter<IterType> * copy =
170         new variant_filter_iterator::Iter<IterType>(iter_data);
171 #else
172       Iter<IterType> * copy =
173         new Iter<IterType>(iter_data);
174 #endif
175 
176       return copy;
177     }
178 
179     /**
180      * \returns A copy of this object as a pointer to a
181      * different type of object.
182      */
const_cloneIter183     virtual typename IterBase::const_IterBase * const_clone() const override
184     {
185       /**
186        * Important typedef for const_iterators.  Notice the weird syntax!  Does it compile everywhere?
187        */
188       // typedef typename variant_filter_iterator<Predicate, Type, const Type &, const Type *>::template Iter<IterType> const_Iter;
189       typedef typename variant_filter_iterator<Predicate, Type const, Type const &,  Type const *>::template Iter<IterType> const_Iter;
190 
191       typename IterBase::const_IterBase * copy =
192         new const_Iter(iter_data);
193 
194       return copy;
195     }
196 
197     /**
198      * Dereferences the iterator.
199      */
200     virtual ReferenceType operator*() const override
201     {
202       return * iter_data;
203     }
204 
205     /**
206      * Pre-increments the iterator.
207      */
208     virtual Iter & operator++() override
209     {
210       ++iter_data;
211       return *this;
212     }
213 
214     /**
215      * Use a dynamic cast to convert the base pointer
216      * passed in to the derived type.  If the cast
217      * fails it means you compared two different derived
218      * classes.
219      */
equalIter220     virtual bool equal(const IterBase * other) const override
221     {
222 #if defined(__SUNPRO_CC) || (defined(__GNUC__) && (__GNUC__ < 3)  && !defined(__INTEL_COMPILER))
223       const variant_filter_iterator::Iter<IterType> * p =
224         libMesh::cast_ptr<const variant_filter_iterator::Iter<IterType> *>(other);
225 #else
226       const Iter<IterType> * p =
227         libMesh::cast_ptr<const Iter<IterType> *>(other);
228 #endif
229 
230       return (iter_data == p->iter_data);
231     }
232 
233     /**
234      * This is the iterator passed by the user.
235      */
236     IterType iter_data;
237   };
238 
239 
240 
241 
242   /**
243    * The actual predicate is held as a template parameter here.
244    * There are two template arguments here, one for the actual type
245    * of the predicate and one for the iterator type.
246    */
247   template <typename IterType, typename PredType>
248   struct Pred : PredBase
249   {
250     /**
251      * Constructor
252      */
PredPred253     Pred (const PredType & v) :
254       pred_data (v) {}
255 
256     /**
257      * Destructor
258      */
~PredPred259     virtual ~Pred () {}
260 
261     /**
262      * \returns A copy of this object as a pointer to the base class.
263      */
clonePred264     virtual PredBase * clone() const override
265     {
266 #ifdef __SUNPRO_CC
267       variant_filter_iterator::Pred<IterType,PredType> * copy =
268         new variant_filter_iterator::Pred<IterType,PredType>(pred_data);
269 #else
270       Pred<IterType,PredType> * copy =
271         new Pred<IterType,PredType>(pred_data);
272 #endif
273 
274       return copy;
275     }
276 
277 
278     /**
279      * The redefinition of the const_clone function for the Pred class.
280      */
const_clonePred281     virtual typename PredBase::const_PredBase * const_clone() const override
282     {
283       /**
284        * Important typedef for const_iterators.
285        */
286       //      typedef typename variant_filter_iterator<Predicate, Type, const Type &, const Type *>::template Pred<IterType, PredType> const_Pred;
287       typedef typename variant_filter_iterator<Predicate, Type const, Type const &,  Type const *>::template Pred<IterType, PredType> const_Pred;
288 
289 
290       typename PredBase::const_PredBase * copy =
291         new const_Pred(pred_data);
292 
293       return copy;
294     }
295 
296 
297 
298 
299     /**
300      * Re-implementation of op()
301      */
operatorPred302     virtual bool operator() (const IterBase * in) const override
303     {
304       libmesh_assert(in);
305 
306       // Attempt downcast
307 #if defined(__SUNPRO_CC) || (defined(__GNUC__) && (__GNUC__ < 3)  && !defined(__INTEL_COMPILER))
308       const variant_filter_iterator::Iter<IterType> * p =
309         libMesh::cast_ptr<const variant_filter_iterator::Iter<IterType> * >(in);
310 #else
311       const Iter<IterType> * p =
312         libMesh::cast_ptr<const Iter<IterType> *>(in);
313 #endif
314 
315       // Return result of op() for the user's predicate.
316       return pred_data(p->iter_data);
317     }
318 
319     /**
320      * This is the predicate passed in by the user.
321      */
322     PredType pred_data;
323   };
324 
325 
326 
327 public:
328   /**
329    * Ideally this private member data should have protected access.  However, if we want
330    * a const_iterator to be constructable from an non-const one, templated versions of the
331    * same class (not related by inheritance) will need to know about these private members.
332    * Thus, they have public access.
333    *
334    * Polymorphic pointer to the object.  Don't confuse
335    * with the data pointer located in the \p Iter!
336    */
337   IterBase * data;
338 
339   /**
340    * Also have a polymorphic pointer to the end object,
341    * this prevents iterating past the end.
342    */
343   IterBase * end;
344 
345   /**
346    * The predicate object.  Must have op() capable of
347    * operating on IterBase * pointers.  Therefore it has
348    * to follow the same paradigm as \p IterBase.
349    */
350   PredBase * pred;
351 
352 
353 
354 public:
355   /**
356    * Templated Constructor.  Allows you to construct the iterator
357    * and predicate from any types.  Also advances the data pointer
358    * to the first entry which satisfies the predicate.
359    *
360    * \note The initialization list uses the default IterBase copy
361    * constructor.
362    */
363   template<typename PredType, typename IterType>
variant_filter_iterator(const IterType & d,const IterType & e,const PredType & p)364   variant_filter_iterator (const IterType & d,
365                            const IterType & e,
366                            const PredType & p ):
367     data ( new Iter<IterType>(d) ),
368     end  ( new Iter<IterType>(e) ),
369     pred ( new Pred<IterType,PredType>(p) )
370   {
371     this->satisfy_predicate();
372   }
373 
374   /**
375    * Default Constructor.
376    */
variant_filter_iterator()377   variant_filter_iterator () :
378     data(nullptr),
379     end(nullptr),
380     pred(nullptr) {}
381 
382   /**
383    * Copy Constructor.
384    * Copy the internal data instead of sharing it.
385    */
variant_filter_iterator(const Iterator & rhs)386   variant_filter_iterator (const Iterator & rhs) :
387     data (rhs.data != nullptr ? rhs.data->clone() : nullptr),
388     end  (rhs.end  != nullptr ? rhs.end->clone()  : nullptr),
389     pred (rhs.pred != nullptr ? rhs.pred->clone() : nullptr) {}
390 
391 
392 
393   /**
394    * Copy construct from another (similar) variant_filter_iterator.
395    * The Predicate is the same, but the Type, ReferenceType and
396    * PointerType are different.  Example:
397    * You are iterating over a std::vector<int *> with std::vector<int *>::iterator
398    * Then, you have:
399    * Type=int * ,  ReferenceType=int *& , PointerType=int **
400    * On the other hand, when you iterate using std::vector<int *>::const_iterator
401    * you have:
402    * Type=int * const, ReferenceType=int * const & , PointerType=int * const *
403    */
404   template <class OtherType, class OtherReferenceType, class OtherPointerType>
variant_filter_iterator(const variant_filter_iterator<Predicate,OtherType,OtherReferenceType,OtherPointerType> & rhs)405   variant_filter_iterator (const variant_filter_iterator<Predicate, OtherType, OtherReferenceType, OtherPointerType> & rhs)
406     : data (rhs.data != nullptr ? rhs.data->const_clone() : nullptr),
407       end  (rhs.end  != nullptr ? rhs.end->const_clone()  : nullptr),
408       pred (rhs.pred != nullptr ? rhs.pred->const_clone() : nullptr)
409   {
410     // libMesh::out << "Called templated copy constructor for variant_filter_iterator" << std::endl;
411   }
412 
413 
414 
415 
416 
417 
418   /**
419    * Destructor
420    */
~variant_filter_iterator()421   virtual ~variant_filter_iterator()
422   {
423     delete data; data = nullptr;
424     delete end;  end  = nullptr;
425     delete pred; pred = nullptr;
426   }
427 
428   /**
429    * unary op*() forwards on to \p Iter::op*()
430    */
431   ReferenceType operator*() const
432   {
433     return **data;
434   }
435 
436 
437   /**
438    * op->()
439    */
440   PointerType operator->() const
441   {
442     return (&**this);
443   }
444 
445   /**
446    * op++() forwards on to \p Iter::op++()
447    */
448   Iterator & operator++()
449   {
450     ++*data;
451     this->satisfy_predicate();
452     return (*this);
453   }
454 
455   /**
456    * postfix op++(), creates a temporary!
457    */
458   const Iterator operator++(int) // const here to prevent iterator++++ type operations
459   {
460     Iterator oldValue(*this); // standard is to return old value
461     ++*data;
462     this->satisfy_predicate();
463     return oldValue;
464   }
465 
466   /**
467    * Forwards to the \p equal() function defined for the
468    * IterBase pointer.
469    */
equal(const variant_filter_iterator & other)470   bool equal(const variant_filter_iterator & other) const
471   {
472     return data->equal(other.data);
473   }
474 
475   /**
476    * swap, used to implement op=
477    */
swap(Iterator & lhs,Iterator & rhs)478   void swap(Iterator & lhs, Iterator & rhs)
479   {
480     // Swap the data pointers
481     std::swap (lhs.data, rhs.data);
482 
483     // Swap the end pointers
484     std::swap (lhs.end, rhs.end);
485 
486     // Also swap the predicate objects.
487     std::swap (lhs.pred, rhs.pred);
488   }
489 
490   /**
491    * Assignment operator.
492    */
493   Iterator & operator=(const Iterator & rhs)
494   {
495     Iterator temp(rhs);
496     swap(temp, *this);
497     return *this;
498   }
499 
500 
501 
502 private:
503 
504   /**
505    * Advances the data pointer until it reaches
506    * the end or the predicate is satisfied.
507    */
satisfy_predicate()508   void satisfy_predicate()
509   {
510     while ( !data->equal(end) && !(*pred)(data) )
511       ++(*data);
512   }
513 };
514 
515 
516 
517 
518 
519 
520 // op==
521 template<class Predicate, class Type, class ReferenceType, class PointerType>
522 inline
523 bool operator==(const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> & x,
524                 const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> & y)
525 {
526   return x.equal(y);
527 }
528 
529 
530 
531 // op!=
532 template<class Predicate, class Type, class ReferenceType, class PointerType>
533 inline
534 bool operator!=(const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> & x,
535                 const variant_filter_iterator<Predicate, Type, ReferenceType, PointerType> & y)
536 {
537   return !(x == y);
538 }
539 
540 
541 
542 #endif // LIBMESH_VARIANT_FILTER_ITERATOR_H
543