PandaTree
Ref.h
1 #ifndef PandaTree_Framework_Ref_h
2 #define PandaTree_Framework_Ref_h
3 
4 #include "ContainerBase.h"
5 
6 #include <stdexcept>
7 
8 namespace panda {
9 
11 
19  template<class E>
20  class Ref {
21  public:
22  typedef Ref<E> self_type;
23  typedef E value_type;
24  typedef Short_t index_type;
25 
27  Ref() {}
29 
33  Ref(ContainerBase const*& c, index_type& idx) : container_(&c), idx_(&idx) {}
35  Ref(self_type const& orig) : container_(orig.container_), idx_(orig.idx_) {}
37  void setIndex(index_type& idx) { idx_ = &idx; }
39 
43  void setContainer(ContainerBase const*& c) { container_ = &c; }
45 
48  value_type const* operator->() const
49  {
50  if (!container_ || !(*container_) || !idx_ || (*idx_) < 0)
51  return 0;
52 
53  return &static_cast<E const&>((*container_)->elemAt(*idx_));
54  }
56 
59  value_type const& operator*() const
60  {
61  if (!container_ || !(*container_) || !idx_ || (*idx_) < 0)
62  throw std::runtime_error("Dereferencing an invalid Ref");
63 
64  return static_cast<E const&>((*container_)->elemAt(*idx_));
65  }
67 
71  self_type& operator=(self_type const& rhs)
72  {
73  container_ = rhs.container_;
74  if (idx_) {
75  if (rhs.idx_)
76  (*idx_) = (*rhs.idx_);
77  else
78  (*idx_) = -1;
79  }
80  return *this;
81  }
83 
88  Bool_t setRef(value_type const* rhs)
89  {
90  if (!rhs) {
91  container_ = 0;
92  idx_ = 0;
93  }
94 
95  if (!container_ || !(*container_) || !idx_)
96  return false;
97 
98  // loop through the container and return when a match is found
99  for ((*idx_) = 0; (*idx_) != Short_t((*container_)->size()); ++(*idx_)) {
100  if (&(*container_)->elemAt(*idx_) == rhs)
101  return true;
102  }
103 
104  // otherwise set to -1 and return false
105 
106  (*idx_) = -1;
107  return true;
108  }
110  Bool_t isValid() const { return container_ && *container_ && idx_ && unsigned(*idx_) < (*container_)->size(); }
112 
115  void init() { if (idx_) (*idx_) = -1; }
117 
120  index_type& idx()
121  {
122  if (!idx_)
123  throw std::runtime_error("Invalid index ref");
124 
125  return *idx_;
126  }
128 
131  index_type idx() const
132  {
133  if (!idx_)
134  throw std::runtime_error("Invalid index ref");
135 
136  return *idx_;
137  }
139 
142  ContainerBase const* container() const
143  {
144  if (!container_)
145  throw std::runtime_error("Invalid container ref");
146 
147  return *container_;
148  }
150  value_type const* get() const { return operator->(); }
151 
152  private:
153  ContainerBase const** container_{0};
154  index_type* idx_{0};
155  };
156 
157 
159 
163  template<class E>
164  class ConstRef {
165  public:
166  typedef ConstRef<E> self_type;
167  typedef E value_type;
168  typedef Short_t index_type;
169 
171  ConstRef() {}
173 
177  ConstRef(ContainerBase const*& c, index_type const& idx) : container_(&c), idx_(&idx) {}
179  ConstRef(self_type const& orig) : container_(orig.container_), idx_(orig.idx_) {}
180 
181  self_type& operator=(self_type const&) = delete;
182 
184  void setIndex(index_type const& idx) { idx_ = &idx; }
186 
190  void setContainer(ContainerBase const*& c) { container_ = &c; }
192 
195  value_type const* operator->() const
196  {
197  if (!container_ || !(*container_) || !idx_ || (*idx_) < 0)
198  return 0;
199 
200  return &static_cast<E const&>((*container_)->elemAt(*idx_));
201  }
203 
206  value_type const& operator*() const
207  {
208  if (!container_ || !(*container_) || !idx_ || (*idx_) < 0)
209  throw std::runtime_error("Dereferencing an invalid ConstRef");
210 
211  return static_cast<E const&>((*container_)->elemAt(*idx_));
212  }
214  Bool_t isValid() const { return container_ && *container_ && idx_ && unsigned(*idx_) < (*container_)->size(); }
216 
219  index_type const& idx() const
220  {
221  if (!idx_)
222  throw std::runtime_error("Invalid index ref");
223 
224  return *idx_;
225  }
227 
230  ContainerBase const* container() const
231  {
232  if (!container_)
233  throw std::runtime_error("Invalid container ref");
234 
235  return *container_;
236  }
238  value_type const* get() const { return operator->(); }
239 
240  private:
241  ContainerBase const** container_{0};
242  index_type const* idx_{0};
243  };
244 
245 }
246 
247 template<class E>
248 std::ostream& operator<<(std::ostream& _out, panda::Ref<E> const& _ref)
249 {
250  _out << "Ref<" << E::typeName() << ">";
251  if (_ref.isValid())
252  _out << " " << _ref.container()->getName() << "(" << _ref.idx() << ")";
253  else
254  _out << " (null)";
255 
256  return _out;
257 }
258 
259 template<class E>
260 std::ostream& operator<<(std::ostream& _out, panda::ConstRef<E> const& _ref)
261 {
262  _out << "Ref<" << E::typeName() << ">";
263  if (_ref.isValid())
264  _out << " " << _ref.container()->getName() << "(" << _ref.idx() << ")";
265  else
266  _out << " (null)";
267 
268  return _out;
269 }
270 
271 #endif
ConstRef()
Default constructor.
Definition: Ref.h:171
A reference to an element in a container.
Definition: Ref.h:20
self_type & operator=(self_type const &rhs)
Copy assignment.
Definition: Ref.h:71
index_type const & idx() const
Accessor to idx.
Definition: Ref.h:219
value_type const & operator*() const
The dereference operator.
Definition: Ref.h:206
void setIndex(index_type &idx)
Set the index.
Definition: Ref.h:37
ContainerBase const * container() const
Accessor to container.
Definition: Ref.h:142
Ref(self_type const &orig)
Copy constructor.
Definition: Ref.h:35
Ref()
Default constructor.
Definition: Ref.h:27
ConstRef(ContainerBase const *&c, index_type const &idx)
Standard constructor.
Definition: Ref.h:177
value_type const * operator->() const
The arrow operator.
Definition: Ref.h:48
Bool_t isValid() const
Validity check. Both container and idx must be valid, and idx must not be 0xffffffff.
Definition: Ref.h:110
index_type & idx()
Accessor to idx.
Definition: Ref.h:120
index_type idx() const
Accessor to idx.
Definition: Ref.h:131
void setIndex(index_type const &idx)
Set the index.
Definition: Ref.h:184
Bool_t setRef(value_type const *rhs)
Setter function.
Definition: Ref.h:88
ConstRef(self_type const &orig)
Copy constructor.
Definition: Ref.h:179
void setContainer(ContainerBase const *&c)
Set the container.
Definition: Ref.h:190
char const * getName() const final
Name of this object.
Definition: ContainerBase.h:25
Base class for all containers.
Definition: ContainerBase.h:18
void init()
Initializer.
Definition: Ref.h:115
void setContainer(ContainerBase const *&c)
Set the container.
Definition: Ref.h:43
value_type const * operator->() const
The arrow operator.
Definition: Ref.h:195
Bool_t isValid() const
Validity check. Both container and idx must be valid, and idx must not be 0xffffffff.
Definition: Ref.h:214
A const version of Ref.
Definition: Ref.h:164
Definition: Array.h:11
ContainerBase const * container() const
Accessor to container.
Definition: Ref.h:230
value_type const & operator*() const
The dereference operator.
Definition: Ref.h:59
Ref(ContainerBase const *&c, index_type &idx)
Standard constructor.
Definition: Ref.h:33