1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
|
#ifndef DataFormats_Common_RefVector_h
#define DataFormats_Common_RefVector_h
/*----------------------------------------------------------------------
RefVector: A template for a vector of interproduct references.
Each vector element is a reference to a member of the same product.
----------------------------------------------------------------------*/
#include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
#include "DataFormats/Common/interface/EDProductfwd.h"
#include "DataFormats/Common/interface/FillView.h"
#include "DataFormats/Common/interface/Ref.h"
#include "DataFormats/Common/interface/RefHolderBase.h"
#include "DataFormats/Common/interface/RefTraits.h"
#include "DataFormats/Common/interface/RefVectorBase.h"
#include "DataFormats/Common/interface/RefVectorIterator.h"
#include "DataFormats/Common/interface/RefVectorTraits.h"
#include "DataFormats/Common/interface/traits.h"
#include "DataFormats/Provenance/interface/ProductID.h"
#include <algorithm>
#include <stdexcept>
#include <vector>
namespace edm {
template <typename C,
typename T = typename refhelper::ValueTrait<C>::value,
typename F = typename refhelper::FindTrait<C, T>::value>
class RefVector {
public:
typedef C collection_type;
typedef T member_type;
typedef F finder_type;
typedef typename refhelper::RefVectorTrait<C, T, F>::iterator_type iterator;
typedef iterator const_iterator;
typedef typename refhelper::RefVectorTrait<C, T, F>::ref_type value_type;
typedef value_type const const_reference; // better this than the default 'const value_type &'
typedef const_reference reference; // as operator[] returns 'const R' and not 'R &'
// key_type is the type of the key into the collection
typedef typename value_type::key_type key_type;
typedef std::vector<key_type> KeyVec;
// size_type is the type of the index into the RefVector
typedef typename KeyVec::size_type size_type;
typedef RefVectorBase<key_type> contents_type;
/// Default constructor needed for reading from persistent
/// store. Not for direct use.
RefVector() : refVector_() {}
~RefVector() = default;
RefVector(RefVector const& rh) : refVector_(rh.refVector_) {}
RefVector(RefVector&& rh) noexcept : refVector_(std::move(rh.refVector_)) {}
RefVector& operator=(RefVector const& rhs);
RefVector& operator=(RefVector&& rhs) noexcept {
refVector_ = std::move(rhs.refVector_);
return *this;
}
RefVector(ProductID const& iId) : refVector_(iId) {}
/// Add a Ref<C, T> to the RefVector
void push_back(value_type const& ref) { refVector_.pushBack(ref.refCore(), ref.key()); }
/// Retrieve an element of the RefVector
value_type const operator[](size_type idx) const {
RefCore const& core = refVector_.refCore();
key_type const& key = refVector_.keys()[idx];
void const* memberPointer = refVector_.cachedMemberPointer(idx);
if (memberPointer) {
RefCore newCore(core); // NOLINT
newCore.setProductPtr(memberPointer);
return value_type(newCore, key);
}
return value_type(core, key);
}
/// Retrieve an element of the RefVector
value_type const at(size_type idx) const {
RefCore const& core = refVector_.refCore();
key_type const& key = refVector_.keys().at(idx);
void const* memberPointer = refVector_.cachedMemberPointer(idx);
if (memberPointer) {
RefCore newCore(core); // NOLINT
newCore.setProductPtr(memberPointer);
return value_type(newCore, key);
}
return value_type(core, key);
}
/// Accessor for all data
contents_type const& refVector() const { return refVector_; }
/// Is the RefVector empty
bool empty() const { return refVector_.empty(); }
/// Size of the RefVector
size_type size() const { return refVector_.size(); }
/// Capacity of the RefVector
size_type capacity() const { return refVector_.capacity(); }
/// Reserve space for RefVector
void reserve(size_type n) { refVector_.reserve(n); }
/// Initialize an iterator over the RefVector
const_iterator begin() const;
/// Termination of iteration
const_iterator end() const;
/// Accessor for product ID.
ProductID id() const { return refVector_.refCore().id(); }
/// Accessor for product getter
EDProductGetter const* productGetter() const { return refVector_.refCore().productGetter(); }
/// Checks for null
bool isNull() const { return !id().isValid(); }
/// Checks for non-null
bool isNonnull() const { return !isNull(); }
/// Checks for null
bool operator!() const { return isNull(); }
/// Checks if product collection is in memory or available
/// in the Event. No type checking is done.
bool isAvailable() const;
/// Checks if product collection is tansient (i.e. non persistable)
bool isTransient() const { return refVector_.refCore().isTransient(); }
/// Erase an element from the vector.
iterator erase(iterator const& pos);
/// Clear the vector.
void clear() { refVector_.clear(); }
/// Swap two vectors.
void swap(RefVector<C, T, F>& other) noexcept;
/// Checks if product is in memory.
bool hasProductCache() const { return refVector_.refCore().productPtr() != 0; }
void fillView(ProductID const& id, std::vector<void const*>& pointers, FillViewHelperVector& helpers) const;
//Needed for ROOT storage
CMS_CLASS_VERSION(13)
private:
contents_type refVector_;
};
template <typename C, typename T, typename F>
inline void RefVector<C, T, F>::swap(RefVector<C, T, F>& other) noexcept {
refVector_.swap(other.refVector_);
}
template <typename C, typename T, typename F>
inline RefVector<C, T, F>& RefVector<C, T, F>::operator=(RefVector<C, T, F> const& rhs) {
RefVector<C, T, F> temp(rhs);
this->swap(temp);
return *this;
}
template <typename C, typename T, typename F>
inline void swap(RefVector<C, T, F>& a, RefVector<C, T, F>& b) noexcept {
a.swap(b);
}
template <typename C, typename T, typename F>
void RefVector<C, T, F>::fillView(ProductID const&,
std::vector<void const*>& pointers,
FillViewHelperVector& helpers) const {
pointers.reserve(this->size());
helpers.reserve(this->size());
size_type key = 0;
for (const_iterator i = begin(), e = end(); i != e; ++i, ++key) {
member_type const* address = i->isNull() ? nullptr : &**i;
pointers.push_back(address);
helpers.emplace_back(i->id(), i->key());
}
}
template <typename C, typename T, typename F>
inline void fillView(RefVector<C, T, F> const& obj,
ProductID const& id,
std::vector<void const*>& pointers,
FillViewHelperVector& helpers) {
obj.fillView(id, pointers, helpers);
}
template <typename C, typename T, typename F>
struct has_fillView<RefVector<C, T, F> > {
static bool const value = true;
};
template <typename C, typename T, typename F>
inline bool operator==(RefVector<C, T, F> const& lhs, RefVector<C, T, F> const& rhs) {
return lhs.refVector() == rhs.refVector();
}
template <typename C, typename T, typename F>
inline bool operator!=(RefVector<C, T, F> const& lhs, RefVector<C, T, F> const& rhs) {
return !(lhs == rhs);
}
template <typename C, typename T, typename F>
inline typename RefVector<C, T, F>::iterator RefVector<C, T, F>::erase(iterator const& pos) {
typename contents_type::keys_type::size_type index = pos - begin();
typename contents_type::keys_type::iterator newPos = refVector_.eraseAtIndex(index);
typename contents_type::keys_type::size_type newIndex = newPos - refVector_.keys().begin();
return iterator(this, newIndex);
}
template <typename C, typename T, typename F>
typename RefVector<C, T, F>::const_iterator RefVector<C, T, F>::begin() const {
return iterator(this, 0);
}
template <typename C, typename T, typename F>
typename RefVector<C, T, F>::const_iterator RefVector<C, T, F>::end() const {
return iterator(this, size());
}
template <typename C, typename T, typename F>
bool RefVector<C, T, F>::isAvailable() const {
if (refVector_.refCore().isAvailable()) {
return true;
} else if (empty()) {
return false;
}
// The following is the simplest implementation, but
// this is woefully inefficient and could be optimized
// to run much faster with some nontrivial effort. There
// is only 1 place in the code base where this function
// is used at all and I'm not sure whether it will ever
// be used with thinned collections, so for the moment I
// am not spending the time to optimize this.
for (size_type i = 0; i < size(); ++i) {
if (!(*this)[i].isAvailable()) {
return false;
}
}
return true;
}
template <typename C, typename T, typename F>
std::ostream& operator<<(std::ostream& os, RefVector<C, T, F> const& r) {
for (typename RefVector<C, T, F>::const_iterator i = r.begin(), e = r.end(); i != e; ++i) {
os << *i << '\n';
}
return os;
}
} // namespace edm
#include "DataFormats/Common/interface/GetProduct.h"
namespace edm {
namespace detail {
template <typename C, typename T, typename F>
struct GetProduct<RefVector<C, T, F> > {
typedef T element_type;
typedef typename RefVector<C, T, F>::const_iterator iter;
static element_type const* address(iter const& i) { return &**i; }
};
} // namespace detail
} // namespace edm
#endif
|