Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/root/RooLinkedListIter.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*****************************************************************************
0002  * Project: RooFit                                                           *
0003  * Package: RooFitCore                                                       *
0004  *    File: $Id: RooLinkedListIter.h,v 1.11 2007/05/11 09:11:30 verkerke Exp $
0005  * Authors:                                                                  *
0006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
0007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
0008  *                                                                           *
0009  * Copyright (c) 2000-2005, Regents of the University of California          *
0010  *                          and Stanford University. All rights reserved.    *
0011  *                                                                           *
0012  * Redistribution and use in source and binary forms,                        *
0013  * with or without modification, are permitted according to the terms        *
0014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
0015  *****************************************************************************/
0016 #ifndef ROO_LINKED_LIST_ITER
0017 #define ROO_LINKED_LIST_ITER
0018 
0019 #include "TIterator.h"
0020 #include "RooLinkedList.h"
0021 
0022 #include <memory>
0023 #include <stdexcept>
0024 #include <cassert>
0025 
0026 /// Interface for RooFIter-compatible iterators
0027 class GenericRooFIter
0028 {
0029   public:
0030   /// Return next element or nullptr if at end.
0031   virtual RooAbsArg * next() = 0;
0032   virtual ~GenericRooFIter() {}
0033 };
0034 
0035 ////////////////////////////////////////////////////////////////////////////////////////////
0036 /// A one-time forward iterator working on RooLinkedList or RooAbsCollection.
0037 /// This wrapper separates the interface visible to the outside from the actual
0038 /// implementation of the iterator.
0039 class RooFIter final
0040 {
0041   public:
0042   RooFIter(std::unique_ptr<GenericRooFIter> && itImpl) : fIterImpl{std::move(itImpl)} {}
0043   RooFIter(const RooFIter &) = delete;
0044   RooFIter(RooFIter &&) = default;
0045   RooFIter & operator=(const RooFIter &) = delete;
0046   RooFIter & operator=(RooFIter &&) = default;
0047 
0048   /// Return next element or nullptr if at end.
0049   RooAbsArg *next() {
0050     return fIterImpl->next();
0051   }
0052 
0053   private:
0054   std::unique_ptr<GenericRooFIter> fIterImpl;
0055 };
0056 
0057 ////////////////////////////////////////////////////////////////////////////////////////////
0058 /// Implementation of the GenericRooFIter interface for the RooLinkedList
0059 class RooFIterForLinkedList final : public GenericRooFIter
0060 {
0061   public:
0062   RooFIterForLinkedList() {}
0063   RooFIterForLinkedList(const RooLinkedList* list) : fPtr (list->_first) {}
0064 
0065   /// Return next element in collection
0066   RooAbsArg *next() override {
0067     if (!fPtr) return nullptr ;
0068     TObject* arg = fPtr->_arg ;
0069     fPtr = fPtr->_next;
0070     return (RooAbsArg*) arg ;
0071   }
0072 
0073  private:
0074     const RooLinkedListElem * fPtr{nullptr};  ///<! Next link element
0075 };
0076 
0077 
0078 
0079 
0080 ////////////////////////////////////////////////////////////////////////////////////////////
0081 /// TIterator and GenericRooFIter front end with STL back end.
0082 ///
0083 /// By default, this iterators counts, at which position the current element should be.
0084 /// On request, it does an index access to the underlying collection, and returns the element.
0085 /// This happens because the RooLinkedList, which used to be the default collection in RooFit,
0086 /// will not invalidate iterators when inserting elements. Since the default is now an STL collection,
0087 /// reallocations might invalidate the iterator.
0088 ///
0089 /// With an iterator that counts, only inserting before or at the iterator position will create problems.
0090 /// deal with reallocations while iterating. Therefore, this iterator will also check that the last element
0091 /// it was pointing to is the current element when it is invoked again. This ensures that
0092 /// inserting or removing before this iterator does not happen, which was possible with
0093 /// the linked list iterators of RooFit.
0094 /// When NDEBUG is defined, these checks will disappear.
0095 /// \note This is a legacy iterator that only exists to not break old code. Use begin(), end() and
0096 /// range-based for loops with RooArgList and RooArgSet.
0097 template<class STLContainer>
0098 class TIteratorToSTLInterface final : public TIterator , public GenericRooFIter {
0099 public:
0100 
0101   TIteratorToSTLInterface(const STLContainer & container) :
0102     TIterator(),
0103     GenericRooFIter(),
0104     fSTLContainer(container),
0105     fIndex(0)
0106 #ifdef NDEBUG
0107     ,fCurrentElem{nullptr}
0108 #else
0109     ,fCurrentElem{fSTLContainer.empty() ? nullptr : fSTLContainer.front()}
0110 #endif
0111   {
0112 
0113   }
0114 
0115   TIterator & operator=(const TIterator &) override {
0116     throw;
0117   }
0118 
0119   const TCollection *GetCollection() const override {
0120     return nullptr;
0121   }
0122 
0123   RooAbsArg * next() override {
0124     if (atEnd())
0125       return nullptr;
0126 #ifdef NDEBUG
0127     return fSTLContainer[fIndex++];
0128 #else
0129     return nextChecked();
0130 #endif
0131   }
0132 
0133 
0134   TObject * Next() override {
0135     return static_cast<TObject*>(next());
0136   }
0137 
0138   void Reset() override {
0139     fIndex = 0;
0140 #ifndef NDEBUG
0141     fCurrentElem = fSTLContainer.empty() ? nullptr : fSTLContainer.front();
0142 #endif
0143 
0144   }
0145 
0146   bool operator!=(const TIterator & other) const override {
0147     const auto * castedOther =
0148         dynamic_cast<const TIteratorToSTLInterface<STLContainer>*>(&other);
0149     return !castedOther || &fSTLContainer != &(castedOther->fSTLContainer)
0150         || fIndex == castedOther->fIndex;
0151   }
0152 
0153   TObject * operator*() const override {
0154       if (atEnd())
0155         return nullptr;
0156 
0157     #ifndef NDEBUG
0158       assert(fCurrentElem == fSTLContainer[fIndex]);
0159     #endif
0160 
0161       return static_cast<TObject*>(fSTLContainer[fIndex]);
0162     }
0163 
0164 
0165 private:
0166   bool atEnd() const {
0167     return fSTLContainer.empty()
0168         || fIndex >= fSTLContainer.size();
0169   }
0170 
0171 
0172   RooAbsArg * nextChecked() {
0173     RooAbsArg * ret = fSTLContainer.at(fIndex);
0174     if (fCurrentElem != nullptr && ret != fCurrentElem) {
0175       throw std::logic_error("A RooCollection should not be modified while iterating. "
0176           "Only inserting at end is acceptable.");
0177     }
0178     fCurrentElem = ++fIndex < fSTLContainer.size() ? fSTLContainer[fIndex] : nullptr;
0179 
0180     return ret;
0181   }
0182 
0183 
0184   const STLContainer & fSTLContainer; ///<!
0185   std::size_t fIndex; ///<!
0186   const RooAbsArg * fCurrentElem; ///<!
0187 };
0188 
0189 
0190 
0191 
0192 ////////////////////////////////////////////////////////////////////////////////////////////
0193 /// A wrapper around TIterator derivatives.
0194 ///
0195 /// It is called RooLinkedListIter because all classes assume that the RooAbsCollections use
0196 /// a RooLinkedList, which is not true, any more.
0197 /// The purpose of this wrapper is to act on the outside like a RooLinkedListIter, even though
0198 /// the underlying implementation may work an a different container, like e.g.
0199 /// an STL container. This is needed to not break user code that is using a RooLinkedList or
0200 /// a RooAbsCollection.
0201 ///
0202 /// \note All code using this iterator as an iterator over a RooAbsCollection should move
0203 /// to begin() and end() or range-based for loops. These are faster.
0204 class RooLinkedListIter final : public TIterator {
0205 
0206   public:
0207   RooLinkedListIter(std::shared_ptr<TIterator> iterImpl) :
0208     fIterImpl{std::move(iterImpl)} {
0209 
0210   }
0211 
0212   RooLinkedListIter(const RooLinkedListIter &) = delete;
0213   RooLinkedListIter & operator=(const RooLinkedListIter &) = delete;
0214 
0215   // Setting the move constructor and assignment operator to = default might
0216   // seem to work, but it causes linker errors when using it because
0217   // TIterator::operator= is not implemented.
0218   RooLinkedListIter(RooLinkedListIter && other)
0219     : fIterImpl{std::move(other.fIterImpl)}
0220   {}
0221   RooLinkedListIter & operator=(RooLinkedListIter && other) {
0222     fIterImpl = std::move(other.fIterImpl);
0223     return *this;
0224   }
0225 
0226   TIterator &operator=(const TIterator & other) override {fIterImpl->operator=(other); return *this;}
0227   const TCollection *GetCollection() const override {return nullptr;}
0228 
0229   TObject * Next() override {return fIterImpl->Next();}
0230   void Reset() override {fIterImpl->Reset();}
0231   bool operator!=(const TIterator & other) const override {return fIterImpl->operator!=(other);}
0232   TObject * operator*() const override {return fIterImpl->operator*();}
0233 
0234   private:
0235   std::shared_ptr<TIterator> fIterImpl; //!
0236 };
0237 
0238 
0239 ////////////////////////////////////////////////////////////////////////////////////////////
0240 /// Implementation of the actual iterator on RooLinkedLists.
0241 ///
0242 class RooLinkedListIterImpl final : public TIterator {
0243 public:
0244 
0245   RooLinkedListIterImpl(const RooLinkedList* list, const RooLinkedListElem* ptr, bool forward) :
0246     _list(list), _ptr(ptr), _forward(forward) {}
0247 
0248   RooLinkedListIterImpl(const RooLinkedList* list, bool forward) :
0249     RooLinkedListIterImpl(list, forward ? list->_first : list->_last, forward) {}
0250 
0251   TIterator& operator=(const TIterator& other) override {
0252 
0253     // Iterator assignment operator
0254 
0255     if (&other==this) return *this ;
0256     const RooLinkedListIterImpl* iter = dynamic_cast<const RooLinkedListIterImpl*>(&other) ;
0257     if (iter) {
0258       _list = iter->_list ;
0259       _ptr = iter->_ptr ;
0260       _forward = iter->_forward ;
0261     }
0262     return *this ;
0263   }
0264 
0265   const TCollection *GetCollection() const override {
0266     // Dummy
0267     return nullptr ;
0268   }
0269 
0270   TObject *Next() override {
0271     // Return next element in collection
0272     return NextNV();
0273   }
0274 
0275   TObject *NextNV() {
0276     // Return next element in collection
0277     if (!_ptr) return nullptr ;
0278     TObject* arg = _ptr->_arg ;
0279     _ptr = _forward ? _ptr->_next : _ptr->_prev ;
0280     return arg ;
0281   }
0282 
0283   void Reset() override {
0284     // Return iterator to first element in collection
0285     _ptr = _forward ? _list->_first : _list->_last ;
0286   }
0287 
0288   bool operator!=(const TIterator &aIter) const override {
0289     const RooLinkedListIterImpl *iter(dynamic_cast<const RooLinkedListIterImpl*>(&aIter));
0290     if (iter) return (_ptr != iter->_ptr);
0291     return false; // for base class we don't implement a comparison
0292   }
0293 
0294   bool operator!=(const RooLinkedListIterImpl &aIter) const {
0295     return _ptr != aIter._ptr;
0296   }
0297 
0298   TObject *operator*() const override {
0299     // Return element iterator points to
0300     return _ptr ? _ptr->_arg : nullptr;
0301   }
0302 
0303   RooLinkedListIterImpl &operator++() {
0304      if(_ptr) _ptr = _forward ? _ptr->_next : _ptr->_prev ;
0305      return *this;
0306   }
0307 
0308   RooLinkedListIterImpl operator++(int) {
0309      RooLinkedListIterImpl tmp(*this);
0310      operator++();
0311      return tmp;
0312   }
0313 
0314 protected:
0315   const RooLinkedList* _list ;     ///<! Collection iterated over
0316   const RooLinkedListElem* _ptr ;  ///<! Next link element
0317   bool _forward ;                  ///<!  Iterator direction
0318 };
0319 
0320 
0321 
0322 
0323 #endif