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