Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooLinkedListIter.h
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * File: $Id: RooLinkedListIter.h,v 1.11 2007/05/11 09:11:30 verkerke Exp $
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16#ifndef ROO_LINKED_LIST_ITER
17#define ROO_LINKED_LIST_ITER
18
19#include "TIterator.h"
20#include "RooLinkedList.h"
21
22#include <memory>
23#include <stdexcept>
24#include <assert.h>
25
26/// Interface for RooFIter-compatible iterators
28{
29 public:
30 /// Return next element or nullptr if at end.
31 virtual RooAbsArg * next() = 0;
32 virtual ~GenericRooFIter() {}
33};
34
35////////////////////////////////////////////////////////////////////////////////////////////
36/// A one-time forward iterator working on RooLinkedList or RooAbsCollection.
37/// This wrapper separates the interface visible to the outside from the actual
38/// implementation of the iterator.
39class RooFIter final
40{
41 public:
42 RooFIter(std::unique_ptr<GenericRooFIter> && itImpl) : fIterImpl{std::move(itImpl)} {}
43 RooFIter(const RooFIter &) = delete;
44 RooFIter(RooFIter &&) = default;
45 RooFIter & operator=(const RooFIter &) = delete;
46 RooFIter & operator=(RooFIter &&) = default;
47
48 /// Return next element or nullptr if at end.
50 return fIterImpl->next();
51 }
52
53 private:
54 std::unique_ptr<GenericRooFIter> fIterImpl;
55};
56
57////////////////////////////////////////////////////////////////////////////////////////////
58/// Implementation of the GenericRooFIter interface for the RooLinkedList
60{
61 public:
63 RooFIterForLinkedList(const RooLinkedList* list) : fPtr (list->_first) {}
64
65 /// Return next element in collection
66 RooAbsArg *next() override {
67 if (!fPtr) return nullptr ;
68 TObject* arg = fPtr->_arg ;
69 fPtr = fPtr->_next;
70 return (RooAbsArg*) arg ;
71 }
72
73 private:
74 const RooLinkedListElem * fPtr{nullptr}; //! Next link element
75};
76
77
78
79
80////////////////////////////////////////////////////////////////////////////////////////////
81/// TIterator and GenericRooFIter front end with STL back end.
82///
83/// By default, this iterators counts, at which position the current element should be.
84/// On request, it does an index access to the underlying collection, and returns the element.
85/// This happens because the RooLinkedList, which used to be the default collection in RooFit,
86/// will not invalidate iterators when inserting elements. Since the default is now an STL collection,
87/// reallocations might invalidate the iterator.
88///
89/// With an iterator that counts, only inserting before or at the iterator position will create problems.
90/// deal with reallocations while iterating. Therefore, this iterator will also check that the last element
91/// it was pointing to is the the current element when it is invoked again. This ensures that
92/// inserting or removing before this iterator does not happen, which was possible with
93/// the linked list iterators of RooFit.
94/// When NDEBUG is defined, these checks will disappear.
95/// \note This is a legacy iterator that only exists to not break old code. Use begin(), end() and
96/// range-based for loops with RooArgList and RooArgSet.
97template<class STLContainer>
98class TIteratorToSTLInterface final : public TIterator , public GenericRooFIter {
99public:
100
101 TIteratorToSTLInterface(const STLContainer & container) :
102 TIterator(),
104 fSTLContainer(container),
105 fIndex(0)
106#ifdef NDEBUG
107 ,fCurrentElem{nullptr}
108#else
109 ,fCurrentElem{fSTLContainer.empty() ? nullptr : fSTLContainer.front()}
110#endif
111 {
112
113 }
114
115 TIterator & operator=(const TIterator &) override {
116 throw;
117 }
118
119 const TCollection *GetCollection() const override {
120 return nullptr;
121 }
122
123 RooAbsArg * next() override {
124 if (atEnd())
125 return nullptr;
126#ifdef NDEBUG
127 return fSTLContainer[fIndex++];
128#else
129 return nextChecked();
130#endif
131 }
132
133
134 TObject * Next() override {
135 return static_cast<TObject*>(next());
136 }
137
138 void Reset() override {
139 fIndex = 0;
140#ifndef NDEBUG
141 fCurrentElem = fSTLContainer.empty() ? nullptr : fSTLContainer.front();
142#endif
143
144 }
145
146 bool operator!=(const TIterator & other) const override {
147 const auto * castedOther =
148 dynamic_cast<const TIteratorToSTLInterface<STLContainer>*>(&other);
149 return !castedOther || &fSTLContainer != &(castedOther->fSTLContainer)
150 || fIndex == castedOther->fIndex;
151 }
152
153 TObject * operator*() const override {
154 if (atEnd())
155 return nullptr;
156
157 #ifndef NDEBUG
159 #endif
160
161 return static_cast<TObject*>(fSTLContainer[fIndex]);
162 }
163
164
165private:
166 bool atEnd() const {
167 return fSTLContainer.empty()
168 || fIndex >= fSTLContainer.size();
169 }
170
171
173 RooAbsArg * ret = fSTLContainer.at(fIndex);
174 if (fCurrentElem != nullptr && ret != fCurrentElem) {
175 throw std::logic_error("A RooCollection should not be modified while iterating. "
176 "Only inserting at end is acceptable.");
177 }
178 fCurrentElem = ++fIndex < fSTLContainer.size() ? fSTLContainer[fIndex] : nullptr;
179
180 return ret;
181 }
182
183
184 const STLContainer & fSTLContainer; //!
185 std::size_t fIndex; //!
187};
188
189
190
191
192////////////////////////////////////////////////////////////////////////////////////////////
193/// A wrapper around TIterator derivatives.
194///
195/// It is called RooLinkedListIter because all classes assume that the RooAbsCollections use
196/// a RooLinkedList, which is not true, any more.
197/// The purpose of this wrapper is to act on the outside like a RooLinkedListIter, even though
198/// the underlying implementation may work an a different container, like e.g.
199/// an STL container. This is needed to not break user code that is using a RooLinkedList or
200/// a RooAbsCollection.
201///
202/// \note All code using this iterator as an iterator over a RooAbsCollection should move
203/// to begin() and end() or range-based for loops. These are faster.
204class RooLinkedListIter final : public TIterator {
205
206 public:
207 RooLinkedListIter(std::shared_ptr<TIterator> iterImpl) :
208 fIterImpl{std::move(iterImpl)} {
209
210 }
211
214
215 // Setting the move constructor and assignment operator to = default might
216 // seem to work, but it causes linker errors when using it because
217 // TIterator::operator= is not implemented.
219 : fIterImpl{std::move(other.fIterImpl)}
220 {}
222 fIterImpl = std::move(other.fIterImpl);
223 return *this;
224 }
225
226 TIterator &operator=(const TIterator & other) override {fIterImpl->operator=(other); return *this;}
227 const TCollection *GetCollection() const override {return nullptr;}
228
229 TObject * Next() override {return fIterImpl->Next();}
230 void Reset() override {fIterImpl->Reset();}
231 bool operator!=(const TIterator & other) const override {return fIterImpl->operator!=(other);}
232 TObject * operator*() const override {return fIterImpl->operator*();}
233
234 private:
235 std::shared_ptr<TIterator> fIterImpl; //!
236};
237
238
239////////////////////////////////////////////////////////////////////////////////////////////
240/// Implementation of the actual iterator on RooLinkedLists.
241///
242class RooLinkedListIterImpl final : public TIterator {
243public:
244
245 RooLinkedListIterImpl(const RooLinkedList* list, const RooLinkedListElem* ptr, bool forward) :
246 _list(list), _ptr(ptr), _forward(forward) {}
247
248 RooLinkedListIterImpl(const RooLinkedList* list, bool forward) :
249 RooLinkedListIterImpl(list, forward ? list->_first : list->_last, forward) {}
250
252
253 // Iterator assignment operator
254
255 if (&other==this) return *this ;
256 const RooLinkedListIterImpl* iter = dynamic_cast<const RooLinkedListIterImpl*>(&other) ;
257 if (iter) {
258 _list = iter->_list ;
259 _ptr = iter->_ptr ;
260 _forward = iter->_forward ;
261 }
262 return *this ;
263 }
264
265 virtual const TCollection *GetCollection() const {
266 // Dummy
267 return 0 ;
268 }
269
270 virtual TObject *Next() {
271 // Return next element in collection
272 return NextNV();
273 }
274
276 // Return next element in collection
277 if (!_ptr) return nullptr ;
278 TObject* arg = _ptr->_arg ;
279 _ptr = _forward ? _ptr->_next : _ptr->_prev ;
280 return arg ;
281 }
282
283 virtual void Reset() {
284 // Return iterator to first element in collection
286 }
287
288 bool operator!=(const TIterator &aIter) const {
289 const RooLinkedListIterImpl *iter(dynamic_cast<const RooLinkedListIterImpl*>(&aIter));
290 if (iter) return (_ptr != iter->_ptr);
291 return false; // for base class we don't implement a comparison
292 }
293
294 bool operator!=(const RooLinkedListIterImpl &aIter) const {
295 return _ptr != aIter._ptr;
296 }
297
298 virtual TObject *operator*() const {
299 // Return element iterator points to
300 return _ptr ? _ptr->_arg : nullptr;
301 }
302
304 if(_ptr) _ptr = _forward ? _ptr->_next : _ptr->_prev ;
305 return *this;
306 }
307
309 RooLinkedListIterImpl tmp(*this);
310 operator++();
311 return tmp;
312 }
313
314protected:
315 const RooLinkedList* _list ; //! Collection iterated over
316 const RooLinkedListElem* _ptr ; //! Next link element
317 bool _forward ; //! Iterator direction
318};
319
320
321
322
323#endif
Interface for RooFIter-compatible iterators.
virtual ~GenericRooFIter()
virtual RooAbsArg * next()=0
Return next element or nullptr if at end.
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:69
Implementation of the GenericRooFIter interface for the RooLinkedList.
RooAbsArg * next() override
Return next element in collection.
RooFIterForLinkedList(const RooLinkedList *list)
const RooLinkedListElem * fPtr
A one-time forward iterator working on RooLinkedList or RooAbsCollection.
RooFIter(RooFIter &&)=default
RooFIter(const RooFIter &)=delete
RooAbsArg * next()
Return next element or nullptr if at end.
RooFIter & operator=(const RooFIter &)=delete
std::unique_ptr< GenericRooFIter > fIterImpl
RooFIter(std::unique_ptr< GenericRooFIter > &&itImpl)
RooFIter & operator=(RooFIter &&)=default
RooLinkedListElem is an link element for the RooLinkedList class.
RooLinkedListElem * _prev
RooLinkedListElem * _next
Implementation of the actual iterator on RooLinkedLists.
RooLinkedListIterImpl & operator++()
virtual TObject * operator*() const
Return current object or nullptr.
TIterator & operator=(const TIterator &other)
bool operator!=(const RooLinkedListIterImpl &aIter) const
RooLinkedListIterImpl(const RooLinkedList *list, bool forward)
bool _forward
Next link element.
const RooLinkedList * _list
virtual const TCollection * GetCollection() const
RooLinkedListIterImpl operator++(int)
bool operator!=(const TIterator &aIter) const
Compare two iterator objects.
virtual TObject * Next()
RooLinkedListIterImpl(const RooLinkedList *list, const RooLinkedListElem *ptr, bool forward)
const RooLinkedListElem * _ptr
Collection iterated over.
A wrapper around TIterator derivatives.
RooLinkedListIter(std::shared_ptr< TIterator > iterImpl)
bool operator!=(const TIterator &other) const override
Compare two iterator objects.
const TCollection * GetCollection() const override
RooLinkedListIter(const RooLinkedListIter &)=delete
void Reset() override
TObject * Next() override
TObject * operator*() const override
Return current object or nullptr.
RooLinkedListIter & operator=(const RooLinkedListIter &)=delete
RooLinkedListIter(RooLinkedListIter &&other)
TIterator & operator=(const TIterator &other) override
std::shared_ptr< TIterator > fIterImpl
RooLinkedListIter & operator=(RooLinkedListIter &&other)
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
RooLinkedListElem * _last
Link to first element of list.
RooLinkedListElem * _first
Collection abstract base class.
Definition TCollection.h:65
TIterator and GenericRooFIter front end with STL back end.
TObject * Next() override
bool operator!=(const TIterator &other) const override
Compare two iterator objects.
RooAbsArg * next() override
Return next element or nullptr if at end.
const RooAbsArg * fCurrentElem
TIterator & operator=(const TIterator &) override
TIteratorToSTLInterface(const STLContainer &container)
TObject * operator*() const override
Return current object or nullptr.
const TCollection * GetCollection() const override
const STLContainer & fSTLContainer
Iterator abstract base class.
Definition TIterator.h:30
Mother of all ROOT objects.
Definition TObject.h:41
#define NDEBUG