BOSS 8.0.0
BESIII Offline Software System
Loading...
Searching...
No Matches
Event/GeneratorObject/include/DataModel/DataVector.h
Go to the documentation of this file.
1#ifndef DATAMODEL_DATAVECTOR_H
2#define DATAMODEL_DATAVECTOR_H
3
4#ifndef _CPP_VECTOR
5# include <vector>
6#endif
7#ifndef _CPP_ITERATOR
8# include <iterator>
9#endif
10#ifndef _CPP_ALGORITHM
11# include <algorithm> /* std::swap, advance */
12#endif
13#ifndef _CPP_IOSTREAM
14# include <iostream>
15#endif
16
17#include <typeinfo>
18
19#ifndef DATAMODEL_OWNERSHIPPOLICY_H
20# include "DataModel/OwnershipPolicy.h"
21#endif
22
23#ifndef BOOST_CONCEPT_CHECKS_HPP
24# include <boost/concept_check.hpp>
25#endif
26
27#ifndef GAUDIKERNEL_SYSTEM_H
28# include "GaudiKernel/System.h"
29#endif
30
31namespace detail {
32
34 public:
35 CompareAndPrint( bool quiet ) : m_quiet( quiet ) {}
36 template <typename Element> bool operator()( Element* f, Element* s ) const {
37 bool areEq( f == s );
38 if ( !m_quiet && areEq && f != 0 )
39 {
40 std::cout << "WARNING: duplicated pointer found in a DataVector of "
41 << System::typeinfoName( typeid( *f ) ) << " owning its elements! "
42 << std::hex << f << std::dec << std::endl;
43 }
44 return areEq;
45 }
46
47 private:
48 bool m_quiet;
49 };
50
51#ifndef NDEBUG
52# define DEFQUIET false
53#else
54# define DEFQUIET true
55#endif
56 template <class ForwIter>
57 ForwIter remove_duplicates( ForwIter b, ForwIter e, bool quiet = DEFQUIET ) {
58 std::sort( b, e );
59 return std::unique( b, e, CompareAndPrint( quiet ) );
60 }
61#undef DEFQUIET
62} // namespace detail
63
64/** @class DataVector
65 * @brief an STL vector of pointers that by default owns
66 * its pointed elements.
67 *
68 * Beware of ownership issues when you modify a DataVector.
69 * Obviously you should not delete explicitly a DataVector element.
70 * A DataVector should never have two elements pointing to the same object.
71 * This may seem obvious but certain std algorithms (e.g. remove_if) may
72 * leave a DataVector with two copies of the same element in the
73 * "left-over" range. To avoid a crash when clearing the vector (e.g. in the
74 * destructor we have introduced a n-log(n) helper function that searches
75 * and removes duplicates in the DataVector. This is used by the destructor
76 * by clear() and by erase(first, last). As this may change in the future
77 * to improve performance, do not rely on this functionality and do avoid
78 * introducing duplicated elements in a DataVector.
79 *
80 * All these cautions do not apply when a DataVector it is created with
81 * the flag SG::VIEW_ELEMENTS (see enum OwnershipPolicy) and hence does
82 * not own its elements. This is typically used to have DataVector
83 * elements allocated by DataPool. Othewise consider the cleaner
84 * alternative of using a vector<T*>
85 *
86 * Notice the use of value_type instead of const_reference:
87 * this is justified by the fact that the elem are always ptrs.
88 * @author ATLAS Collaboration
89 *$Id: DataVector.h,v 1.17 2003/10/14 18:56:42 calaf Exp $
90 */
91template <typename T> class DataVector {
92private:
93#ifndef __ATLAS_SEAL_DICT__
94 SG::OwnershipPolicy m_ownPolicy;
95#else
96 int m_ownPolicy;
97#endif
98 typedef std::vector<T*> PtrVector;
99
100 PtrVector m_pCont;
101
102public:
103 /// access the underlying std vector;
104 const PtrVector& stdcont() const { return m_pCont; }
105
106 ///\name vector typedefs: it behaves like a vector<T*>
107 //@{
108 typedef T*& reference;
109 typedef const T*& const_reference;
110 typedef typename PtrVector::iterator iterator;
111 typedef typename PtrVector::const_iterator const_iterator;
112 typedef typename PtrVector::size_type size_type;
113 typedef typename PtrVector::difference_type difference_type;
114 typedef T* value_type;
115 typedef typename PtrVector::allocator_type allocator_type;
116 typedef T** pointer;
117 typedef const T** const_pointer;
118 typedef typename PtrVector::reverse_iterator reverse_iterator;
119 typedef typename PtrVector::const_reverse_iterator const_reverse_iterator;
120 //@}
121
122public:
123 /// \name vector structors (no Allocators). Own elements by default
124 //@{
126 : m_ownPolicy( ownPolicy ), m_pCont() {}
127
128 /// Non standard: always set elements to 0
129 explicit DataVector( size_type n, /* value_type pElem = 0,*/
131 : m_ownPolicy( ownPolicy ) {
132 // FIXME what is the right thing to do?
133 // boost::function_requires< boost::DefaultConstructibleConcept<T> >();
134 // if (m_ownPolicy == SG::OWN_ELEMENTS && 0 == pElem) pElem = new T();
135 insert( begin(), n, 0 );
136 }
137
138 /// copy constructor: since it is a shallow copy
139 /// the copy DataVector does not own the elements
140 explicit DataVector( const DataVector<T>& rhs )
141 : m_ownPolicy( SG::VIEW_ELEMENTS ), m_pCont( rhs.stdcont() ) {
142 // cout << "copy const called" << this << " <- " << &rhs << endl;
143 }
144
145 /// copy via iterators: since it is a shallow copy
146 /// the copy DataVector does not own the elements
147 template <class InputIterator>
148 DataVector( InputIterator first, InputIterator last,
150 : m_ownPolicy( ownPolicy ), m_pCont( first, last ) {}
151
152 /// op =: since it is a shallow copy
153 /// the copy DataList does not own the elements
155 m_ownPolicy = SG::VIEW_ELEMENTS;
156 m_pCont = rhs.stdcont();
157 // cout << "op = called" << this << " = " << &rhs << endl;
158 return *this;
159 }
160
161 /// the ownership policy will determine who owns the assigned elements
162 template <class InputIterator> void assign( InputIterator first, InputIterator last ) {
163 clear();
164 insert( begin(), first, last );
165 }
166
167 /// Deletes the pointed-at elements when m_ownPolicy == SG::OWN_ELEMENTS
168 /// (i.e. by default).
169 virtual ~DataVector<T>() {
170 if ( m_ownPolicy == SG::OWN_ELEMENTS )
171 {
172 iterator new_end( detail::remove_duplicates( begin(), end() ) );
173 iterator iter( begin() );
174 while ( iter != new_end ) delete *( iter++ );
175 }
176 }
177 //@}
178
179 /// \name vector iterators
180 //@{
181#define FUNFWD( func ) \
182 func() { return m_pCont.func(); }
183#define CONSTFUNFWD( func ) \
184 func() const { return m_pCont.func(); }
185#define FUNFWDN( func ) \
186 func( size_type n ) { return m_pCont.func( n ); }
187#define CONSTFUNFWDN( func ) \
188 func( size_type n ) const { return m_pCont.func( n ); }
189
190 iterator FUNFWD( begin );
194 iterator FUNFWD( rbegin );
198 //@}
199
200 /// \name vector capacity
201 //@{
204
205 /// Non standard. When increasing size always set the new elements to 0
206 void resize( size_type sz /*, value_type pElem = 0*/ ) {
207 if ( sz < size() ) { erase( begin() + sz, end() ); }
208 else
209 {
210 // FIXME what is the right thing to do?
211 // boost::function_requires< boost::DefaultConstructibleConcept<T> >();
212 // if (m_ownPolicy == SG::OWN_ELEMENTS && 0 == pElem) pElem = new T();
213 insert( end(), sz - size(), 0 );
214 }
215 }
217 bool CONSTFUNFWD( empty );
218 void FUNFWDN( reserve );
219 //@}
220
221 /// Allows us to distinguish among read/write access to a returned reference.
222 /// Manages memory correctly for lvalue references
224 public:
225 ElementProxy( PtrVector& cont, size_type index ) : m_proxied( cont.begin() ) {
226 std::advance( m_proxied, index );
227 }
228 ElementProxy( iterator iter ) : m_proxied( iter ) {}
229 /// lvalue uses assignment
231 delete *m_proxied;
232 *m_proxied = *( rhs.m_proxied );
233 return *this;
234 }
235 /// lvalue uses assignment
237 delete *m_proxied;
238 *m_proxied = rhs;
239 return *this;
240 }
241 /// rvalue uses conversion
242 operator T* const() const { return *m_proxied; }
243
244 private:
245 iterator m_proxied;
246 };
247
248 /// \name vector accessors. Non standard return values!
249 //@{
250
251 /// standard return value is reference!
252 ElementProxy operator[]( size_type n ) { return ElementProxy( m_pCont, n ); }
253 ElementProxy at( size_type n ) { return ElementProxy( m_pCont, n ); }
254 ElementProxy front() { return ElementProxy( m_pCont.begin() ); }
255 ElementProxy back() { return ElementProxy( m_pCont.end() - 1 ); }
256
257 /// standard return value is const_reference i.e. const T*&!
258 const T* CONSTFUNFWDN( operator[] );
259 const T* CONSTFUNFWDN( at );
260 const T* CONSTFUNFWD( front );
261 const T* CONSTFUNFWD( back );
262
263 //@}
264
265 /// \name vector modifiers
266 //@{
267 // std void push_back(const_reference pElem)
268 void push_back( value_type pElem ) { m_pCont.push_back( pElem ); }
269 void FUNFWD( pop_back );
270 /// the ownership policy will determine who owns the inserted elements
271 iterator insert( iterator position, value_type pElem ) { // std const_ref
272 return m_pCont.insert( position, pElem );
273 }
274
275 /// the ownership policy will determine who owns the inserted elements
276 template <class InputIterator>
277 void insert( iterator position, InputIterator first, InputIterator last ) {
278 m_pCont.insert( position, first, last );
279 }
280 /// the ownership policy will determine whether to erase the pointee
281 iterator erase( iterator position ) {
282 if ( m_ownPolicy == SG::OWN_ELEMENTS && position != end() ) delete position;
283 return m_pCont.erase( position );
284 }
285 /// the ownership policy will determine whether to erase the pointee
287 if ( first == last ) return first;
288 if ( m_ownPolicy == SG::OWN_ELEMENTS )
289 {
290 iterator new_end( detail::remove_duplicates( first, last ) );
291 iterator iter( first );
292 while ( iter != new_end ) delete *( iter++ );
293 }
294 return m_pCont.erase( first, last );
295 }
296 void swap( DataVector<T>& rhs ) {
297 std::swap( m_ownPolicy, rhs.m_ownPolicy );
298 m_pCont.swap( rhs.m_pCont );
299 }
300 void clear() { erase( begin(), end() ); }
301 //@}
302
303private:
304 /// \name Non standard: clieant not allowed to call as they produce
305 /// unpredictable results (multiple elements pointing to the same obj)
306 void assign( size_type n, value_type pElem ) {
307 clear();
308 insert( begin(), n, pElem );
309 }
310 void insert( iterator position, size_type n, value_type pElem ) { // std const_ref
311 // if (m_ownPolicy == SG::OWN_ELEMENTS) {
312 // PtrVector buf;
313 // buf.reserve(n);
314 // buf.push_back(pElem); //take ownership of the original ptr
315 // boost::function_requires< boost::CopyConstructibleConcept<T> >();
316 // for (size_type i(1); i<n; ++i) buf.push_back(pElem ? new T(*pElem) : 0);
317 // insert(position, buf.begin(), buf.end());
318 // } else {
319 m_pCont.insert( position, n, pElem );
320 // }
321 }
322
323#undef FUNFWD
324#undef CONSTFUNFWD
325#undef FUNFWDN
326#undef CONSTFUNFWDN
327};
328
329/// \name vector comparison operators
330//@{
331#define COMPOP( oper ) \
332 template <class T> bool operator oper( const DataVector<T> lhs, const DataVector<T> rhs ) { \
333 return lhs.stdcont() oper rhs.stdcont(); \
334 }
335
336COMPOP( == )
337COMPOP( < )
338COMPOP( != )
339COMPOP( > )
340COMPOP( >= )
341COMPOP( <= )
342
343#undef COMPOP
344
345template <class T> void swap( DataVector<T> lhs, DataVector<T> rhs ) { lhs.swap( rhs ); }
346//@}
347
348#endif
TFile f("ana_bhabha660a_dqa_mcPat_zy_old.root")
const Int_t n
void swap(DataVector< T > lhs, DataVector< T > rhs)
EvtStreamInputIterator< typename Generator::result_type > iter(Generator gen, int N=0)
EvtComplex cont(const EvtTensor4C &t1, const EvtTensor4C &t2)
XmlRpcServer s
ElementProxy & operator=(value_type rhs)
lvalue uses assignment
ElementProxy & operator=(const ElementProxy &rhs)
lvalue uses assignment
an STL vector of pointers that by default owns its pointed elements.
iterator erase(iterator position)
the ownership policy will determine whether to erase the pointee
const T * CONSTFUNFWDN(operator[])
standard return value is const_reference i.e. const T*&!
ElementProxy operator[](size_type n)
standard return value is reference!
void insert(iterator position, InputIterator first, InputIterator last)
the ownership policy will determine who owns the inserted elements
DataVector(InputIterator first, InputIterator last, SG::OwnershipPolicy ownPolicy=SG::VIEW_ELEMENTS)
size_type CONSTFUNFWD(size)
iterator FUNFWD(rend)
void assign(InputIterator first, InputIterator last)
the ownership policy will determine who owns the assigned elements
size_type CONSTFUNFWD(max_size)
void resize(size_type sz)
Non standard. When increasing size always set the new elements to 0.
const_iterator CONSTFUNFWD(rend)
iterator erase(iterator first, iterator last)
the ownership policy will determine whether to erase the pointee
DataVector(size_type n, SG::OwnershipPolicy ownPolicy=SG::OWN_ELEMENTS)
Non standard: always set elements to 0.
iterator FUNFWD(rbegin)
const_iterator CONSTFUNFWD(end)
PtrVector::const_reverse_iterator const_reverse_iterator
void FUNFWD(pop_back)
bool CONSTFUNFWD(empty)
iterator FUNFWD(end)
const PtrVector & stdcont() const
access the underlying std vector;
iterator FUNFWD(begin)
const T * CONSTFUNFWD(front)
const_iterator CONSTFUNFWD(begin)
const T * CONSTFUNFWDN(at)
size_type CONSTFUNFWD(capacity)
iterator insert(iterator position, value_type pElem)
the ownership policy will determine who owns the inserted elements
const_iterator CONSTFUNFWD(rbegin)
DataVector< T > & operator=(const DataVector< T > &rhs)
DataVector(SG::OwnershipPolicy ownPolicy=SG::OWN_ELEMENTS)
const T * CONSTFUNFWD(back)
void FUNFWDN(reserve)
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
@ OWN_ELEMENTS
this data object owns its elements
ForwIter remove_duplicates(ForwIter b, ForwIter e, bool quiet=DEFQUIET)