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
277
278
279
|
#ifndef DataFormats_Common_FwdRef_h
#define DataFormats_Common_FwdRef_h
/*----------------------------------------------------------------------
FwdRef: A template for a interproduct reference to a member of a product.
----------------------------------------------------------------------*/
/**
\b Summary
The edm::FwdRef<> is a storable reference to an item in a stored
"forward" container, which also contains a reference to an item in a
"backward" container that the "forward" container is derived from.
For example, you could use one to hold a reference back
to one particular track within a derived std::vector<> of tracks,
but you want to keep the original Ref's to the original
std::vector<> of tracks (for instance, if you've made a selection
on the tracks in the list and want to remove the unnecessary ones
from the event).
\b Usage
The edm::FwdRef<> works just like a pointer
\code
edm::FwdRef<Foo> fooPtr = ... //set the value
functionTakingConstFoo(*fooPtr); //get the Foo object
fooPtr->bar(); //call a method of the held Foo object
\endcode
The main purpose of an edm::FwdRef<> is it can be used as a member
datum for a class that is to be stored in the edm::Event where the
user can simultaneously check the "backwards" ref as well as the
default "forward" ref.
\b Customization
The edm::FwdRef<> takes three template parameters, and both
"forward" and "backward" refs must be the same types:
1) \b C: The type of the container which is holding the item
2) \b T: The type of the item. This defaults to C::value_type
3) \b F: A helper class (a functor) which knows how to find a
particular 'T' within the container given an appropriate key. The
type of the key is deduced from F::second_argument. The default
for F is refhelper::FindTrait<C,T>::value. If no specialization
of FindTrait<> is available for the combination (C,T) then it
defaults to getting the iterator to be beginning of the container
and using std::advance() to move to the appropriate key in the
container.
It is possible to customize the 'lookup' algorithm used.
1) The helper class F must provide `value_type`,
`first_argument_type` and `second_argument_type` typedefs.
2) The helper class F must define the function call operator in
such a way that the following call is well-formed:
// f is an instance of type F
// coll is an instance of type C
// k is an instance of type F::key_type
result_type r = f(coll,k);
If one wishes to make a specialized lookup the default lookup for
the container/type pair then one needs to partially specialize
the templated class edm::refhelper::FindTrait<C,T> such that it
has a typedef named 'value' which refers to the specialized
helper class (i.e., F)
The class template FwdRef<C,T,F> supports 'null' references.
-- a default-constructed FwdRef is 'null'; furthermore, it also
has an invalid (or 'null') ProductID.
-- a FwdRef constructed through the single-arguement constructor
that takes a ProductID is also null.
*/
/*----------------------------------------------------------------------
// This defines the public interface to the class FwdRef<C, T, F>.
// C is the collection type.
// T (default C::value_type) is the type of an element in the collection.
//
// ProductID productID is the product ID of the collection.
// key_type itemKey is the key of the element in the collection.
// C::value_type *itemPtr is a C++ pointer to the element
// FwdRef<C, T, F> const& ref is another FwdRef<C, T, F>
// Constructors
FwdRef(); // Default constructor
FwdRef(FwdRef<C, T> const& ref); // Copy constructor (default, not explicitly specified)
FwdRef(Ref<C,T,F> const & fwdRef, Ref<C,T,F> const & backRef);
// Destructor
virtual ~FwdRef() {}
// Operators and methods
FwdRef<C, T>& operator=(FwdRef<C, T> const&); // assignment (default, not explicitly specified)
T const& operator*() const; // dereference
T const* const operator->() const; // member dereference
bool operator==(FwdRef<C, T> const& ref) const; // equality
bool operator!=(FwdRef<C, T> const& ref) const; // inequality
bool operator<(FwdRef<C, T> const& ref) const; // ordering
bool isNonnull() const; // true if an object is referenced
bool isNull() const; // equivalent to !isNonnull()
bool operator!() const; // equivalent to !isNonnull()
----------------------------------------------------------------------*/
#include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
#include "DataFormats/Common/interface/Ref.h"
#include <boost/functional.hpp>
namespace edm {
template <typename C,
typename T = typename refhelper::ValueTrait<C>::value,
typename F = typename refhelper::FindTrait<C, T>::value>
class FwdRef {
public:
/// for export
typedef C product_type;
typedef T value_type;
typedef T const element_type; //used for generic programming
typedef F finder_type;
typedef typename boost::binary_traits<F>::second_argument_type argument_type;
typedef typename std::remove_cv<typename std::remove_reference<argument_type>::type>::type key_type;
/// C is the type of the collection
/// T is the type of a member the collection
/// Default constructor needed for reading from persistent store. Not for direct use.
FwdRef() : ref_(), backRef_() {}
/// General purpose constructor from 2 refs (forward and backward.
FwdRef(Ref<C, T, F> const& ref, Ref<C, T, F> const& backRef) : ref_(ref), backRef_(backRef) {
assert(ref.isNull() == backRef.isNull());
}
/// Destructor
~FwdRef() {}
/// Dereference operator
T const& operator*() const;
/// Member dereference operator
T const* operator->() const;
/// Returns C++ pointer to the item
T const* get() const {
if (ref_.isAvailable()) {
return ref_.get();
} else {
return backRef_.get();
}
}
/// Checks for null
bool isNull() const { return !isNonnull(); }
/// Checks for non-null
//bool isNonnull() const {return id().isValid(); }
bool isNonnull() const { return ref_.isNonnull() || backRef_.isNonnull(); }
/// Checks for null
bool operator!() const { return isNull(); }
Ref<C, T, F> const& ref() const { return ref_; }
Ref<C, T, F> const& backRef() const { return backRef_; }
/// Accessor for product getter.
EDProductGetter const* productGetter() const {
//another thread might cause productGetter() to change its value
EDProductGetter const* getter = ref_.productGetter();
if (getter)
return getter;
else
return backRef_.productGetter();
}
/// Accessor for product ID.
ProductID id() const { return ref_.isNonnull() ? ref_.id() : backRef_.id(); }
/// Accessor for product key.
key_type key() const { return ref_.isNonnull() ? ref_.key() : backRef_.key(); }
bool hasProductCache() const { return ref_.hasProductCache() || backRef_.hasProductCache(); }
/// Checks if collection is in memory or available
/// in the Event. No type checking is done.
bool isAvailable() const { return ref_.isAvailable() || backRef_.isAvailable(); }
/// Checks if this ref is transient (i.e. not persistable).
bool isTransient() const { return ref_.isTransient(); }
//Used by ROOT storage
CMS_CLASS_VERSION(10)
private:
Ref<C, T, F> ref_;
Ref<C, T, F> backRef_;
};
} // namespace edm
#include "DataFormats/Common/interface/RefProd.h"
namespace edm {
/// Dereference operator
template <typename C, typename T, typename F>
inline T const& FwdRef<C, T, F>::operator*() const {
return ref_.isNonnull() && ref_.isAvailable() ? ref_.operator*() : backRef_.operator*();
}
/// Member dereference operator
template <typename C, typename T, typename F>
inline T const* FwdRef<C, T, F>::operator->() const {
return ref_.isNonnull() && ref_.isAvailable() ? ref_.operator->() : backRef_.operator->();
}
/// for two FwdRefs to be equal, both the
/// "forward" and the "backward" Refs must be the same
template <typename C, typename T, typename F>
inline bool operator==(FwdRef<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
return (lhs.ref() == rhs.ref()) && (lhs.backRef() == rhs.backRef());
}
/// for a FwdRef to equal a Ref, EITHER the
/// "forward" or the "backward" Refs must equal to the test ref
template <typename C, typename T, typename F>
inline bool operator==(Ref<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
return (lhs == rhs.ref()) || (lhs == rhs.backRef());
}
/// for a FwdRef to equal a Ref, EITHER the
/// "forward" or the "backward" Refs must equal to the test ref
template <typename C, typename T, typename F>
inline bool operator==(FwdRef<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
return (lhs.ref() == rhs) || (lhs.backRef() == rhs);
}
template <typename C, typename T, typename F>
inline bool operator!=(FwdRef<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
return !(lhs == rhs);
}
template <typename C, typename T, typename F>
inline bool operator!=(Ref<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
return !(lhs == rhs);
}
template <typename C, typename T, typename F>
inline bool operator!=(FwdRef<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
return !(lhs == rhs);
}
/// for inequality operators, ONLY test the forward ref.
/// the ordering of the backward ref is not relevant.
template <typename C, typename T, typename F>
inline bool operator<(FwdRef<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
return (lhs.ref() < rhs.ref());
}
template <typename C, typename T, typename F>
inline bool operator<(Ref<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
return (lhs < rhs.ref());
}
template <typename C, typename T, typename F>
inline bool operator<(FwdRef<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
return (lhs.ref() < rhs);
}
} // namespace edm
#endif
|