PandaTree
RefVector.h
1 #ifndef PandaTree_Framework_RefVector_h
2 #define PandaTree_Framework_RefVector_h
3 
4 #include "ContainerBase.h"
5 #include "Ref.h"
6 
7 #include <stdexcept>
8 #include <vector>
9 
10 namespace panda {
11 
13 
17  template<class E>
18  class RefVector {
19  public:
20  typedef RefVector<E> self_type;
21  typedef E element_type;
24  typedef std::vector<Short_t> Indices;
25 
27  RefVector() {}
29 
33  RefVector(ContainerBase const*& c, Indices& indices) : container_(&c), indices_(&indices) {}
35  RefVector(self_type const& orig) : container_(orig.container_), indices_(orig.indices_) {}
37  void setIndices(Indices& indices) { indices_ = &indices; }
39 
43  void setContainer(ContainerBase const*& c) { container_ = &c; }
45  UShort_t size() const;
47  ref_type at(UShort_t);
49  const_ref_type at(UShort_t) const;
51  element_type const& objAt(UShort_t) const;
53  self_type& operator=(self_type const&);
55 
59  void addRef(element_type const*);
61 
64  void push_back(ref_type const&);
66  void clear() { if (indices_) indices_->clear(); }
68 
71  void init() { clear(); }
73  Bool_t isValid() const { return container_ && *container_ && indices_; }
75 
78  Indices*& indices();
80 
83  ContainerBase const* container() const;
85 
88  void sort(ContainerBase::Comparison const&);
89 
91  template<Bool_t is_const>
92  class RefHolder {
93  public:
94  typedef typename std::conditional<is_const, Short_t const, Short_t>::type index_type;
95  typedef typename std::conditional<is_const, const_ref_type, ref_type>::type value_type;
96 
97  RefHolder(ContainerBase const*& c, index_type& idx) : ref_(c, idx) {}
98  value_type const& operator*() const { return ref_; }
99  value_type const* operator->() const { return &ref_; }
100  private:
101  value_type ref_;
102  };
103 
105  template<Bool_t is_const>
107  friend class RefVector<element_type>;
108  public:
110  typedef RefVectorIterator<is_const> self_type;
111  typedef typename std::conditional<is_const, const_ref_type, ref_type>::type value_type;
113  typedef typename std::conditional<is_const, Indices::const_iterator, Indices::iterator>::type internal_type;
114  typedef int difference_type;
115 
116  RefVectorIterator() {}
117  RefVectorIterator(self_type const& it) : container_(it.container_), itr_(it.itr_) {}
118 
119  bool operator==(self_type const& rhs) const { return itr_ == rhs.itr_; }
120  bool operator!=(self_type const& rhs) const { return itr_ != rhs.itr_; }
121 
122  value_type operator*() const { return value_type(*container_, *itr_); }
123  ptr_type operator->() const { return ptr_type(*container_, *itr_); }
124 
125  self_type& operator++() { ++itr_; return *this; }
126  self_type operator++(int) { auto copy(*this); ++itr_; return copy; }
127  self_type& operator--() { --itr_; return *this; }
128  self_type operator--(int) { auto copy(*this); --itr_; return copy; }
129 
130  self_type& operator+=(int n) { itr_ += n; return *this; }
131  self_type& operator-=(int n) { itr_ -= n; return *this; }
132 
133  self_type operator+(int n) const { auto copy(*this); return (copy += n); }
134  self_type operator-(int n) const { auto copy(*this); return (copy -= n); }
135 
136  int operator-(self_type const& rhs) const {
137  return this->operator*().operator->() - (*rhs).operator->();
138  }
139 
140  self_type& operator[](int n) { auto copy(*this); return (copy += n); }
141  bool operator<(self_type const& rhs) const { return this->operator-(rhs) < 0; }
142  bool operator>(self_type const& rhs) const { return this->operator-(rhs) > 0; }
143  bool operator<=(self_type const& rhs) const { return !(this->operator>(rhs)); }
144  bool operator>=(self_type const& rhs) const { return !(this->operator<(rhs)); }
145 
146  private:
147  RefVectorIterator(ContainerBase const*& v, internal_type const& i) : container_(&v), itr_(i) {}
148 
149  ContainerBase const** container_{0};
150  internal_type itr_{};
151  };
152 
155 
156  const_iterator begin() const { return const_iterator(*container_, indices_->begin()); }
157  iterator begin() { return iterator(*container_, indices_->begin()); }
158  const_iterator end() const { return const_iterator(*container_, indices_->end()); }
159  iterator end() { return iterator(*container_, indices_->end()); }
160 
161  private:
162  ContainerBase const** container_{0};
163  Indices* indices_{0};
164  };
165 
166  template<class E>
167  void
168  RefVector<E>::sort(ContainerBase::Comparison const& _c)
169  {
170  // define an index comparison using the element comparison
171  auto indexComp([this, &_c](short i1, short i2)->Bool_t {
172  return _c(static_cast<Element const&>((*container_)->elemAt(i1)),
173  static_cast<Element const&>((*container_)->elemAt(i2)));
174  });
175 
176  std::sort(indices_->begin(), indices_->end(), indexComp);
177  }
178 
179  template<class E>
180  UShort_t
182  {
183  if (!indices_)
184  return 0;
185  return indices_->size();
186  }
187 
188  template<class E>
189  Ref<E>
190  RefVector<E>::at(UShort_t _i)
191  {
192  if (!container_ || !indices_)
193  throw std::runtime_error("at() called on an invalid RefVector");
194 
195  return Ref<element_type>(*container_, indices_->at(_i));
196  }
197 
198  template<class E>
200  RefVector<E>::at(UShort_t _i) const
201  {
202  if (!container_ || !indices_)
203  throw std::runtime_error("at() called on an invalid RefVector");
204 
205  return ConstRef<element_type>(*container_, indices_->at(_i));
206  }
207 
208  template<class E>
209  E const&
210  RefVector<E>::objAt(UShort_t _i) const
211  {
212  if (!container_ || !(*container_) || !indices_)
213  throw std::runtime_error("at() called on an invalid RefVector");
214 
215  return static_cast<element_type const&>((*container_)->elemAt(indices_->at(_i)));
216  }
217 
218  template<class E>
219  RefVector<E>&
221  {
222  container_ = _rhs.container_;
223  if (indices_) {
224  if (_rhs.indices_)
225  indices_->assign(_rhs.indices_->begin(), _rhs.indices_->end());
226  else
227  indices_ = 0;
228  }
229  else if (_rhs.indices_)
230  throw std::runtime_error("Cannot copy a valid RefVector to an invalid RefVector");
231 
232  return *this;
233  }
234 
235  template<class E>
236  void
238  {
239  if (!_obj)
240  return;
241 
242  if (!container_ || !(*container_) || !indices_)
243  throw std::runtime_error("Cannot push to an invalid RefVector");
244 
245  for (UShort_t idx(0); idx != (*container_)->size(); ++idx) {
246  if (&(*container_)->elemAt(idx) == _obj) {
247  indices_->push_back(Short_t(idx));
248  return;
249  }
250  }
251 
252  throw std::runtime_error("Pushing an object not in referenced collection");
253  }
254 
255  template<class E>
256  void
258  {
259  if (!container_ || !indices_)
260  throw std::runtime_error("Cannot push to an invalid RefVector");
261 
262  if (_ref.container() != *container_)
263  throw std::runtime_error("Pushing a ref of a wrong object");
264 
265  indices_->push_back(_ref.idx());
266  }
267 
268  template<class E>
269  std::vector<Short_t>*&
271  {
272  if (!indices_)
273  throw std::runtime_error("Invalid indices ref");
274 
275  return indices_;
276  }
277 
278  template<class E>
279  ContainerBase const*
281  {
282  if (!container_)
283  throw std::runtime_error("Invalid container ref");
284 
285  return *container_;
286  }
287 
288 }
289 
290 template<class E>
291 std::ostream& operator<<(std::ostream& _out, panda::RefVector<E> const& _ref)
292 {
293  _out << "RefVector<" << E::typeName() << ">";
294  if (_ref.isValid())
295  _out << " " << _ref.container()->getName();
296  else
297  _out << " <null>";
298 
299  return _out;
300 }
301 
302 #endif
void init()
Initializer.
Definition: RefVector.h:71
RefVector()
Default constructor.
Definition: RefVector.h:27
A reference to an element in a container.
Definition: Ref.h:20
void push_back(ref_type const &)
Setter function.
Definition: RefVector.h:257
void setContainer(ContainerBase const *&c)
Set the container (an Array or a Collection).
Definition: RefVector.h:43
ContainerBase const * container() const
Accessor to container.
Definition: RefVector.h:280
element_type const & objAt(UShort_t) const
Object accessor.
Definition: RefVector.h:210
void addRef(element_type const *)
Setter function.
Definition: RefVector.h:237
"pointer" wrapper for Ref
Definition: RefVector.h:92
self_type & operator=(self_type const &)
Assignment operator.
Definition: RefVector.h:220
Indices *& indices()
Accessor to indices.
Definition: RefVector.h:270
RefVector(self_type const &orig)
Copy constructor.
Definition: RefVector.h:35
const iterator
Definition: RefVector.h:106
ContainerBase const * container() const
Accessor to container.
Definition: Ref.h:142
void sort(ContainerBase::Comparison const &)
Sort the ref vector.
Definition: RefVector.h:168
index_type & idx()
Accessor to idx.
Definition: Ref.h:120
UShort_t size() const
Size of the vector.
Definition: RefVector.h:181
void clear()
Clear operation.
Definition: RefVector.h:66
void setIndices(Indices &indices)
Set the index.
Definition: RefVector.h:37
Base class for all containers.
Definition: ContainerBase.h:18
Bool_t isValid() const
Validity check. Both container and idx must be valid, and idx must not be 0xffffffff.
Definition: RefVector.h:73
A const version of Ref.
Definition: Ref.h:164
RefVector(ContainerBase const *&c, Indices &indices)
Standard constructor.
Definition: RefVector.h:33
Definition: MicroJet.h:12
Definition: Array.h:11
A vector of references to elements in a container.
Definition: RefVector.h:18
ref_type at(UShort_t)
Element (ref) accessor.
Definition: RefVector.h:190