a Code for the Combination of Indirect and Direct Constraints on High Energy Physics Models Logo
VectorlikeArray.hpp
Go to the documentation of this file.
1/*
2 * VectorlikeArray.hpp
3 *
4 * Created on: Jan 4, 2012
5 * Author: Ben O'Leary (benjamin.oleary@gmail.com)
6 *
7 * This file is part of BOLlib, released under the
8 * GNU General Public License. Please see the accompanying
9 * README.BOLlib.txt file for a full list of files, brief documentation
10 * on how to use these classes, and further details on the license.
11 */
12
13#ifndef VECTORLIKEARRAY_HPP_
14#define VECTORLIKEARRAY_HPP_
15
16#include <cstdlib>
17#include <stdexcept>
18#include <vector>
19#include <list>
20
21namespace BOL
22{
23 /* this is a template class to do the job of a container similar to a
24 * std::vector, but by acting like an array with a number of elements
25 * attached, which can be re-sized. a std::vector is usually going to be a
26 * better choice, but there might be circumstances where a VectorlikeArray is
27 * preferable.
28 */
29 template< typename StoredClass >
31 {
32 public:
33 VectorlikeArray( int const initialSize = 0 );
35 StoredClass* (*storedClassCopyFunction)( StoredClass const& ) = NULL );
36 /* the copy constructor requires a function that returns a pointer to a
37 * StoredClass instance that was made with new, since the VectorlikeArray
38 * instance will be responsible for freeing its memory with delete. (the
39 * function should of course make the new StoredClass instance as a copy
40 * of the StoredClass instance that is passed as its argument.) if the
41 * function pointer for copying given is NULL, the StoredClass copies are
42 * attempted to be initialized with the default StoredClass copy
43 * constructor (i.e. with new StoredClass( StoredClass const& ) with the
44 * appropriate argument).
45 */
47
48 StoredClass&
49 operator[]( int const soughtIndex );
50 // this returns a reference to the requested element. it does not check
51 // that the element is in the range!
52 StoredClass const&
53 operator[]( int const soughtIndex ) const;
54 // this returns a reference to the requested element. it does not check
55 // that the element is in the range!
56 bool
57 isEmpty() const;
58 // this returns false if the number of elements which are deemed current is
59 // greater than zero, true otherwise.
60 int
61 getSize() const;
62 // this returns the number of elements which are deemed current.
63 int
64 getLastIndex() const;
65 // this returns the number for accessing the last of elements which are
66 // deemed current.
68 setSize( int const newSize );
69 // this sets the size of the currently-available container, ensuring that
70 // enough elements exist.
72 increaseSize( int const numberToAdd = 1 );
73 // this increases the size of the currently-available container, ensuring
74 // that enough elements exist.
75 StoredClass&
76 newEnd();
77 // this increases the size of the currently-available container by 1,
78 // ensuring that enough elements exist, & returns the last element.
81 // this is just setSize( 0 ).
82 StoredClass*
83 getPointer( int const soughtIndex );
84 // if an element out of range is asked for, this returns NULL.
85 StoredClass const*
86 getPointer( int const soughtIndex ) const;
87 // if an element out of range is asked for, this returns NULL.
88 StoredClass&
89 safeAt( int const soughtIndex );
90 // if an element out of range is asked for, this throws an exception.
91 StoredClass const&
92 safeAt( int const soughtIndex ) const;
93 // if an element out of range is asked for, this throws an exception.
94 StoredClass&
95 getFront();
96 // this returns the 1st element deemed current, throwing an out_of_range
97 // exception if the container is empty.
98 StoredClass const&
99 getFront() const;
100 // this returns the 1st element deemed current, throwing an out_of_range
101 // exception if the container is empty.
102 StoredClass&
103 getBack();
104 // this returns the last element deemed current, throwing an out_of_range
105 // exception if the container is empty.
106 StoredClass const&
107 getBack() const;
108 // this returns the last element deemed current, throwing an out_of_range
109 // exception if the container is empty.
110 std::vector< StoredClass* >&
111 getAsVector( std::vector< StoredClass* >& vectorToFill ) const;
112 // this fills the given vector with pointers to the current elements,
113 // returning a reference to the vector.
114 std::list< StoredClass* >&
115 getAsList( std::list< StoredClass* >& listToFill ) const;
116 // this fills the given list with pointers to the current elements,
117 // returning a reference to the list.
119 memoryFreeingResize( int const newSize = 0 );
120 // this frees up as much memory as possible held in this VectorlikeArray by
121 // leaving it as big as specified by newSize.
124 void (*firstArgumentBecomesCopyOfSecond)( StoredClass&,
125 StoredClass const& ) = NULL );
126 /* this sets this instance of VectorlikeArray to be a copy of copySource.
127 * if the function pointer that is meant to point to a function that sets a
128 * StoredClass instance to be a copy of another is given as NULL, the
129 * StoredClass copies are attempted to be copied with the default
130 * StoredClass operator= (i.e. with newCopy = copiedInstance
131 * appropriately). it returns a reference to this instance.
132 */
133
134
135 protected:
136 StoredClass** pointerArray;
137 // this is the pointer to the array of pointers to the held StoredClass
138 // instances.
140 // this is the number of pointers in the array in memory.
142 // this is the index of the last pointer in the array which points to a
143 // constructed StoredClass instance.
145 // this is the number of pointers as the user should see it.
147 // this is the index of the last pointer in the array as the user should
148 // see it.
149
150 StoredClass*
151 unsafeGetPointer( int const soughtIndex );
152 // this does not check bounds!
153 StoredClass const*
154 unsafeGetPointer( int const soughtIndex )
155 const;
156 // this does not check bounds!
157 StoredClass*
158 safeGetPointer( int const soughtIndex );
159 // if an element out of range is asked for, this returns NULL.
160 StoredClass const*
161 safeGetPointer( int const soughtIndex ) const;
162 // if an element out of range is asked for, this returns NULL.
163 StoredClass&
164 getReference( int const soughtIndex );
165 // if an element out of range is asked for, this throws an exception.
166 StoredClass const&
167 getReference( int const soughtIndex )
168 const;
169 // if an element out of range is asked for, this throws an exception.
170 };
171
172
173
174 template< typename StoredClass >
175 inline
177 pointerArray( new StoredClass*[ initialSize ] ),
178 allocatedSizeOfArray( initialSize ),
179 indexOfEndConstructed( -1 ),
180 currentSizeOfArray( initialSize ),
181 currentEndIndex( initialSize - 1 )
182 {
184 {
186 pointerArray[ indexOfEndConstructed ] = new StoredClass;
187 }
188 }
189
190 /* the copy constructor requires a function that returns a pointer to a
191 * StoredClass instance that was made with new, since the VectorlikeArray
192 * instance will be responsible for freeing its memory with delete. (the
193 * function should of course make the new StoredClass instance as a copy
194 * of the StoredClass instance that is passed as its argument.) if the
195 * function pointer for copying given is NULL, the StoredClass copies are
196 * attempted to be initialized with the default StoredClass copy
197 * constructor (i.e. with new StoredClass( StoredClass const& ) with the
198 * appropriate argument).
199 */
200 template< typename StoredClass >
201 inline
203 VectorlikeArray< StoredClass > const& copySource,
204 StoredClass* (*storedClassCopyFunction)( StoredClass const& ) ) :
205 pointerArray( new StoredClass*[ copySource.currentSizeOfArray ] ),
206 allocatedSizeOfArray( copySource.currentSizeOfArray ),
207 indexOfEndConstructed( -1 ),
208 currentSizeOfArray( copySource.currentSizeOfArray ),
209 currentEndIndex( copySource.currentEndIndex )
210 {
211 if( NULL == storedClassCopyFunction )
212 {
214 {
217 = new StoredClass( copySource[ indexOfEndConstructed ] );
218 }
219 }
220 else
221 {
223 {
226 = (*storedClassCopyFunction)( copySource[ indexOfEndConstructed ] );
227 }
228 }
229 }
230
231 template< typename StoredClass >
232 inline
234 {
235 while( 0 <= indexOfEndConstructed )
236 {
237 delete pointerArray[ indexOfEndConstructed ];
238 --indexOfEndConstructed;
239 }
240 delete[] pointerArray;
241 }
242
243
244 template< typename StoredClass >
245 inline StoredClass&
247 // this returns a reference to the requested element. it does not check that
248 // the element is in the range!
249 {
250 return *(unsafeGetPointer( soughtIndex ));
251 }
252
253 template< typename StoredClass >
254 inline StoredClass const&
255 VectorlikeArray< StoredClass >::operator[]( int const soughtIndex ) const
256 // this returns a reference to the requested element. it does not check that
257 // the element is in the range!
258 {
259 return *(unsafeGetPointer( soughtIndex ));
260 }
261
262 template< typename StoredClass >
263 inline bool
265 // this returns false if the number of elements which are deemed current is
266 // greater than zero, true otherwise.
267 {
268 if( 0 < currentSizeOfArray )
269 {
270 return false;
271 }
272 else
273 {
274 return true;
275 }
276 }
277
278 template< typename StoredClass >
279 inline int
281 const
282 // this returns the number of elements which are deemed current.
283 {
284 return currentSizeOfArray;
285 }
286
287 template< typename StoredClass >
288 inline int
290 // this returns the number for getPointer to access the last of elements
291 // which are deemed current.
292 {
293 return currentEndIndex;
294 }
295
296 template< typename StoredClass >
299 // this sets the size of the currently-available container, ensuring that
300 // enough elements exist.
301 {
302 // first the conceptual end of the array is moved:
303 currentSizeOfArray = newSize;
304 currentEndIndex = ( newSize - 1 );
305
306 // then the array of pointers is ensured to be large enough:
307 if( currentSizeOfArray > allocatedSizeOfArray )
308 {
309 if( !(0 < allocatedSizeOfArray ) )
310 {
311 allocatedSizeOfArray = currentSizeOfArray;
312 }
313 else
314 {
315 while( currentSizeOfArray > allocatedSizeOfArray )
316 {
317 allocatedSizeOfArray += allocatedSizeOfArray;
318 // the array size is doubled if it gets increased, following the
319 // logic of the std::vector class.
320 }
321 }
322 // now allocatedSizeOfArray is large enough.
323
324 StoredClass**
325 newPointerArray = new StoredClass*[ allocatedSizeOfArray ];
326 // now newCurrentPointersArray is a new, larger array where the pointers
327 // can be put.
328
329 for( int copyIndex( indexOfEndConstructed );
330 0 <= copyIndex;
331 --copyIndex )
332 {
333 newPointerArray[ copyIndex ] = pointerArray[ copyIndex ];
334 }
335 // now newCurrentPointersArray has copied all the contents of
336 // pointerArray, so it is OK to delete[] pointerArray:
337 delete[] pointerArray;
338 pointerArray = newPointerArray;
339 }
340
341 // next it is ensured that enough pointers point to constructed instances:
342 while( currentEndIndex > indexOfEndConstructed )
343 {
344 ++indexOfEndConstructed;
345 pointerArray[ indexOfEndConstructed ] = new StoredClass;
346 }
347
348 return *this;
349 }
350
351 template< typename StoredClass >
354 // this increases the size of the currently-available container, ensuring
355 // that enough elements exist.
356 {
357 return setSize( numberToAdd + currentSizeOfArray );
358 }
359
360 template< typename StoredClass >
361 inline StoredClass&
363 // this increases the size of the currently-available container by 1,
364 // ensuring that enough elements exist, & returns the last element.
365 {
366 increaseSize( 1 );
367 return *(unsafeGetPointer( currentEndIndex ));
368 }
369
370 template< typename StoredClass >
373 // this is just setSize( 0 ).
374 {
375 return setSize( 0 );
376 }
377
378 template< typename StoredClass >
379 inline StoredClass*
381 // if an element out of range is asked for, this returns NULL.
382 {
383 return safeGetPointer( soughtIndex );
384 }
385
386 template< typename StoredClass >
387 inline StoredClass const*
388 VectorlikeArray< StoredClass >::getPointer( int const soughtIndex ) const
389 // if an element out of range is asked for, this returns NULL.
390 {
391 return safeGetPointer( soughtIndex );
392 }
393
394 template< typename StoredClass >
395 inline StoredClass&
397 // if an element out of range is asked for, this throws an exception.
398 {
399 return getReference( soughtIndex );
400 }
401
402 template< typename StoredClass >
403 inline StoredClass const&
404 VectorlikeArray< StoredClass >::safeAt( int const soughtIndex ) const
405 // if an element out of range is asked for, this throws an exception.
406 {
407 return getReference( soughtIndex );
408 }
409
410 template< typename StoredClass >
411 inline StoredClass&
413 // if an element out of range is asked for, this throws an exception.
414 {
415 StoredClass* soughtPointer( safeGetPointer( soughtIndex ) );
416 if( NULL == soughtPointer )
417 {
418 throw std::out_of_range(
419 "VectorlikeArray::getReference(...) out of range" );
420 }
421 return *soughtPointer;
422 }
423
424 template< typename StoredClass >
425 inline StoredClass const&
426 VectorlikeArray< StoredClass >::getReference( int const soughtIndex ) const
427 // if an element out of range is asked for, this throws an exception.
428 {
429 StoredClass* soughtPointer( safeGetPointer( soughtIndex ) );
430 if( NULL == soughtPointer )
431 {
432 throw std::out_of_range(
433 "VectorlikeArray::getReference(...) out of range" );
434 }
435 return *soughtPointer;
436 }
437
438 template< typename StoredClass >
439 inline StoredClass&
441 // this returns the 1st element deemed current, throwing an out_of_range
442 // exception if the container is empty.
443 {
444 return *(safeGetPointer( 0 ));
445 }
446
447 template< typename StoredClass >
448 inline StoredClass const&
450 // this returns the 1st element deemed current, throwing an out_of_range
451 // exception if the container is empty.
452 {
453 return *(safeGetPointer( 0 ));
454 }
455
456 template< typename StoredClass >
457 inline StoredClass&
459 // this returns the last element deemed current, throwing an out_of_range
460 // exception if the container is empty.
461 {
462 return *(safeGetPointer( currentEndIndex ));
463 }
464
465 template< typename StoredClass >
466 inline StoredClass const&
468 // this returns the last element deemed current, throwing an out_of_range
469 // exception if the container is empty.
470 {
471 return *(safeGetPointer( currentEndIndex ));
472 }
473
474 template< typename StoredClass >
475 inline std::vector< StoredClass* >&
477 std::vector< StoredClass* >& vectorToFill ) const
478 // this fills the given vector with pointers to the current elements,
479 // returning a reference to the vector.
480 {
481 vectorToFill.assign( pointerArray,
482 ( pointerArray + currentSizeOfArray ) );
483 return vectorToFill;
484 }
485
486 template< typename StoredClass >
487 inline std::list< StoredClass* >&
489 std::list< StoredClass* >& listToFill ) const
490 // this fills the given list with pointers to the current elements,
491 // returning a reference to the list.
492 {
493 listToFill.assign( pointerArray,
494 ( pointerArray + currentSizeOfArray ) );
495 return listToFill;
496 }
497
498 template< typename StoredClass >
501 // this frees up as much memory as possible held in this VectorlikeArray by
502 // leaving it as big as specified by newSize.
503 {
504 currentSizeOfArray = newSize;
505 currentEndIndex = ( newSize - 1 );
506 while( indexOfEndConstructed >= newSize )
507 {
508 delete pointerArray[ indexOfEndConstructed ];
509 --indexOfEndConstructed;
510 }
511 if( newSize != allocatedSizeOfArray )
512 {
513 allocatedSizeOfArray = newSize;
514 StoredClass**
515 newPointerArray = new StoredClass*[ allocatedSizeOfArray ];
516 // now newCurrentPointersArray is a new array where the pointers
517 // can be put.
518
519 for( int copyIndex( indexOfEndConstructed );
520 0 <= copyIndex;
521 --copyIndex )
522 {
523 newPointerArray[ copyIndex ] = pointerArray[ copyIndex ];
524 }
525 // now newCurrentPointersArray has copied all the contents of
526 // pointerArray, so it is OK to delete[] pointerArray:
527 delete[] pointerArray;
528 pointerArray = newPointerArray;
529 }
530
531 // next it is ensured that enough pointers point to constructed instances:
532 while( currentEndIndex > indexOfEndConstructed )
533 {
534 pointerArray[ ++indexOfEndConstructed ] = new StoredClass;
535 // the index is increased then the pointer at the incremented index is
536 // set to point at a new StoredClass instance.
537 }
538
539 return *this;
540 }
541
542 template< typename StoredClass >
543 inline StoredClass*
545 // this does not check bounds!
546 {
547 return pointerArray[ soughtIndex ];
548 }
549
550 template< typename StoredClass >
551 inline StoredClass const*
553 int const soughtIndex ) const
554 // this does not check bounds!
555 {
556 return pointerArray[ soughtIndex ];
557 }
558
559 template< typename StoredClass >
560 inline StoredClass*
562 // if an element out of range is asked for, this returns NULL.
563 {
564 if( ( 0 <= soughtIndex )
565 &&
566 ( currentEndIndex >= soughtIndex ) )
567 {
568 return unsafeGetPointer( soughtIndex );
569 }
570 else
571 {
572 return NULL;
573 }
574 }
575
576 template< typename StoredClass >
577 inline StoredClass const*
579 // if an element out of range is asked for, this returns NULL.
580 {
581 if( ( 0 <= soughtIndex )
582 &&
583 ( currentEndIndex >= soughtIndex ) )
584 {
585 return unsafeGetPointer( soughtIndex );
586 }
587 else
588 {
589 return NULL;
590 }
591 }
592
593 template< typename StoredClass >
596 VectorlikeArray< StoredClass > const& copySource,
597 void (*firstArgumentBecomesCopyOfSecond)( StoredClass&,
598 StoredClass const& ) )
599 /* this sets this instance of VectorlikeArray to be a copy of copySource. if
600 * the function pointer that is meant to point to a function that sets a
601 * StoredClass instance to be a copy of another is given as NULL, the
602 * StoredClass copies are attempted to be copied with the default StoredClass
603 * operator= (i.e. with newCopy = copiedInstance appropriately). it returns
604 * a reference to this instance.
605 */
606 {
607 setSize( copySource.getSize() );
608 if( NULL == firstArgumentBecomesCopyOfSecond )
609 {
610 for( int copyIndex( copySource.getLastIndex() );
611 0 <= copyIndex;
612 --copyIndex )
613 {
614 *(pointerArray[ copyIndex ]) = copySource[ copyIndex ];
615 }
616 }
617 else
618 {
619 for( int copyIndex( copySource.getLastIndex() );
620 0 <= copyIndex;
621 --copyIndex )
622 {
623 (*firstArgumentBecomesCopyOfSecond)( *(pointerArray[ copyIndex ]),
624 copySource[ copyIndex ] );
625 }
626 }
627 return *this;
628 }
629
630}
631
632#endif /* VECTORLIKEARRAY_HPP_ */
StoredClass * safeGetPointer(int const soughtIndex)
VectorlikeArray< StoredClass > & becomeCopyOf(VectorlikeArray< StoredClass > const &copySource, void(*firstArgumentBecomesCopyOfSecond)(StoredClass &, StoredClass const &)=NULL)
std::vector< StoredClass * > & getAsVector(std::vector< StoredClass * > &vectorToFill) const
VectorlikeArray< StoredClass > & increaseSize(int const numberToAdd=1)
VectorlikeArray< StoredClass > & setSize(int const newSize)
StoredClass ** pointerArray
StoredClass & getBack()
VectorlikeArray< StoredClass > & memoryFreeingResize(int const newSize=0)
StoredClass * getPointer(int const soughtIndex)
StoredClass & operator[](int const soughtIndex)
StoredClass & safeAt(int const soughtIndex)
StoredClass & getReference(int const soughtIndex)
std::list< StoredClass * > & getAsList(std::list< StoredClass * > &listToFill) const
StoredClass & getFront()
StoredClass * unsafeGetPointer(int const soughtIndex)
StoredClass & newEnd()
VectorlikeArray< StoredClass > & clearEntries()
VectorlikeArray(int const initialSize=0)