ATLAS Offline Software
AthLinks/ElementLink.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 /**
5  * @file AthLinks/ElementLink.h
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Apr, 2014
8  * @brief a persistable pointer to an element of a STORABLE (data object)
9  */
10 
11 
12 #include "AthLinks/exceptions.h"
13 #include "AthenaKernel/proxyDictFromEventContext.h"
14 #include "AthenaKernel/IProxyDict.h"
15 
16 
17 /**
18  * @brief Return the CLID for the class that we reference.
19  */
20 template <class STORABLE>
21 inline
22 const CLID& ElementLink<STORABLE>::classID()
23 {
24  return ClassID_traits<value_type>::ID();
25 }
26 
27 
28 /**
29  * @brief Default constructor. Makes a null link.
30  */
31 template <class STORABLE>
32 inline
33 ElementLink<STORABLE>::ElementLink()
34 {
35 }
36 
37 
38 /**
39  * @brief Construct a link from a string storable key and an index. O(1)
40  * @param dataID Key of the object.
41  * @param elemID The index of the element within the container.
42  * @param sg Associated store.
43  *
44  * If @c sg is 0, we take the global default.
45  */
46 template <class STORABLE>
47 inline
48 ElementLink<STORABLE>::ElementLink(const ID_type& dataID, index_type elemID,
49  IProxyDict* sg /*= 0*/)
50  : Base (dataID, classID(), elemID, sg)
51 {
52 }
53 
54 
55 /**
56  * @brief Construct a link from a string storable key and an index. O(1)
57  * @param dataID Key of the object.
58  * @param elemID The index of the element within the container.
59  * @param ctx Event context for this link.
60  */
61 template <class STORABLE>
62 inline
63 ElementLink<STORABLE>::ElementLink(const ID_type& dataID, index_type elemID,
64  const EventContext& ctx)
65  : Base (dataID, classID(), elemID, Atlas::proxyDictFromEventContext(ctx))
66 {
67 }
68 
69 
70 /**
71  * @brief Construct a link from a hashed storable key and an index. O(1)
72  * @param key Hashed key of the object.
73  * @param elemID The index of the element within the container.
74  * @param sg Associated store.
75  *
76  * If @c sg is 0, we take the global default.
77  */
78 template <class STORABLE>
79 inline
80 ElementLink<STORABLE>::ElementLink(sgkey_t key, index_type elemID,
81  IProxyDict* sg /*= 0*/)
82  : Base (key, classID(), elemID, sg)
83 {
84 }
85 
86 
87 /**
88  * @brief Construct a link from a hashed storable key and an index. O(1)
89  * @param key Hashed key of the object.
90  * @param elemID The index of the element within the container.
91  * @param ctx Event context for this link.
92  */
93 template <class STORABLE>
94 inline
95 ElementLink<STORABLE>::ElementLink(sgkey_t key, index_type elemID,
96  const EventContext& ctx)
97  : Base (key, classID(), elemID, Atlas::proxyDictFromEventContext(ctx))
98 {
99 }
100 
101 
102 /**
103  * @brief Construct from a string storable key, index, AND pointer to element. O(1)
104  * @param dataID Key of the object.
105  * @param elemID The index of the element within the container.
106  * @param pEl Pointer to the element.
107  * @param sg Associated store.
108  *
109  * USE CAREFULLY: no coherency checks, we just trust you!
110  *
111  * If @c sg is 0, we take the global default.
112  */
113 template <class STORABLE>
114 inline
115 ElementLink<STORABLE>::ElementLink(const ID_type& dataID,
116  index_type elemID,
117  ElementType pEl,
118  IProxyDict* sg /*= 0*/)
119  : Base (dataID, classID(), elemID, pEl, sg)
120 {
121 }
122 
123 
124 /**
125  * @brief Construct from a string storable key, index, AND pointer to element. O(1)
126  * @param dataID Key of the object.
127  * @param elemID The index of the element within the container.
128  * @param pEl Pointer to the element.
129  * @param ctx Event context for this link.
130  *
131  * USE CAREFULLY: no coherency checks, we just trust you!
132  */
133 template <class STORABLE>
134 inline
135 ElementLink<STORABLE>::ElementLink(const ID_type& dataID,
136  index_type elemID,
137  ElementType pEl,
138  const EventContext& ctx)
139  : Base (dataID, classID(), elemID, pEl, Atlas::proxyDictFromEventContext(ctx))
140 {
141 }
142 
143 
144 /**
145  * @brief Construct from a hashed storable key, index, AND pointer to element. O(1)
146  * @param key Hashed key of the object.
147  * @param elemID The index of the element within the container.
148  * @param pEl Pointer to the element.
149  * @param sg Associated store.
150  *
151  * USE CAREFULLY: no coherency checks, we just trust you!
152  *
153  * If @c sg is 0, we take the global default.
154  */
155 template <class STORABLE>
156 inline
157 ElementLink<STORABLE>::ElementLink (sgkey_t key,
158  index_type elemID,
159  ElementType pEl,
160  IProxyDict* sg /*= 0*/)
161  : Base (key, classID(), elemID, pEl, sg)
162 {
163 }
164 
165 
166 /**
167  * @brief Construct from a hashed storable key, index, AND pointer to element. O(1)
168  * @param key Hashed key of the object.
169  * @param elemID The index of the element within the container.
170  * @param pEl Pointer to the element.
171  * @param ctx Event context for this link.
172  *
173  * USE CAREFULLY: no coherency checks, we just trust you!
174  */
175 template <class STORABLE>
176 inline
177 ElementLink<STORABLE>::ElementLink (sgkey_t key,
178  index_type elemID,
179  ElementType pEl,
180  const EventContext& ctx)
181  : Base (key, classID(), elemID, pEl, Atlas::proxyDictFromEventContext(ctx))
182 {
183 }
184 
185 
186 /**
187  * @brief Construct a link from an index and reference to the container. O(1)
188  * @param data Reference to the container (storable).
189  * @param elemID The index of the element within the container.
190  * @param sg Associated store.
191  *
192  * If @c sg is 0, we take the global default.
193  */
194 template <class STORABLE>
195 inline
196 ElementLink<STORABLE>::ElementLink (BaseConstReference data,
197  index_type elemID,
198  IProxyDict* sg /* = 0*/)
199  : Base (&data, classID(), elemID, sg)
200 {
201 }
202 
203 
204 /**
205  * @brief Construct a link from an index and reference to the container. O(1)
206  * @param data Reference to the container (storable).
207  * @param elemID The index of the element within the container.
208  * @param ctx Event context for this link.
209  */
210 template <class STORABLE>
211 inline
212 ElementLink<STORABLE>::ElementLink (BaseConstReference data,
213  index_type elemID,
214  const EventContext& ctx)
215  : Base (&data, classID(), elemID, Atlas::proxyDictFromEventContext(ctx))
216 {
217 }
218 
219 
220 /**
221  * @brief Construct from an element and reference to the container. O(N)
222  * @param element The element to reference.
223  * @param data Reference to the container (storable).
224  * @param sg Associated store.
225  *
226  * Does the same thing as the default ctor followed by @c toContainedElement.
227  * Note the reversed parameter order compared to the previous
228  * constructor. This is to prevent ambiguities in the case that
229  * the contained type is convertable to an int.
230  *
231  * Will throw @c SG::ExcElementNotFound if the element is not
232  * in the container.
233  *
234  * If @c sg is 0, we take the global default.
235  */
236 template <class STORABLE>
237 inline
238 ElementLink<STORABLE>::ElementLink (const ElementType& element,
239  BaseConstReference data,
240  IProxyDict* sg /*= 0*/)
241 {
242  toContainedElement (data, element, sg);
243 }
244 
245 
246 /**
247  * @brief Construct from an element and reference to the container. O(N)
248  * @param element The element to reference.
249  * @param data Reference to the container (storable).
250  * @param ctx Event context for this link.
251  *
252  * Does the same thing as the default ctor followed by @c toContainedElement.
253  * Note the reversed parameter order compared to the previous
254  * constructor. This is to prevent ambiguities in the case that
255  * the contained type is convertable to an int.
256  *
257  * Will throw @c SG::ExcElementNotFound if the element is not
258  * in the container.
259  */
260 template <class STORABLE>
261 inline
262 ElementLink<STORABLE>::ElementLink (const ElementType& element,
263  BaseConstReference data,
264  const EventContext& ctx)
265 {
266  toContainedElement (data, element, ctx);
267 }
268 
269 
270 /**
271  * @brief Construct a link from another link, changing the index.
272  * @param other The source link.
273  * @param elemID The index for the new link.
274  *
275  * The index being constructed will reference the same container
276  * as @c other, but it will refer to element @c elemID.
277  */
278 template <class STORABLE>
279 inline
280 ElementLink<STORABLE>::ElementLink (const ElementLink& other,
281  index_type elemID)
282  : Base (other, elemID)
283 {
284 }
285 
286 
287 /**
288  * @brief Construct a link from a DataLink and an index.
289  * @param dlink Link to the container.
290  * @param index The index of the element within the container.
291  */
292 template <class STORABLE>
293 inline
294 ElementLink<STORABLE>::ElementLink (const DataLink<STORABLE>& dlink,
295  index_type index)
296  : Base (dlink, index)
297 {
298 }
299 
300 
301 /**
302  * @brief Constructor allowing a derived -> base conversion.
303  */
304 template <class STORABLE>
305 template <class U>
306 inline
307 ElementLink<STORABLE>::ElementLink (const ElementLink<U>& other)
308  : Base (other,
309  (SG::ElementLinkTraits<U>*)0,
310  (Traits*)0)
311 {
312 }
313 
314 
315 /**
316  * @brief Return a pointer to the currently-referenced container object.
317  * @return A pointer to an object of the type given by @a clid,
318  * or null on a failure (or if the reference is null).
319  */
320 template <class STORABLE>
321 inline
322 typename ElementLink<STORABLE>::const_pointer
323 ElementLink<STORABLE>::getDataPtr() const
324 {
325  return reinterpret_cast<const_pointer> (this->storable());
326 }
327 
328 
329 /**
330  * @brief Return a pointer to the currently-referenced container object.
331  * @return A pointer to an object of the type given by @a clid,
332  * or null on a failure (or if the reference is null).
333  */
334 template <class STORABLE>
335 inline
336 typename ElementLink<STORABLE>::pointer
337 ElementLink<STORABLE>::getDataNonConstPtr()
338 {
339  return reinterpret_cast<pointer> (this->storableNonConst());
340 }
341 
342 
343 /**
344  * @brief Return a link to the currently-referenced container object.
345  */
346 template <class STORABLE>
347 inline
348 DataLink<STORABLE> ElementLink<STORABLE>::getDataLink()
349 {
350  return DataLink<STORABLE> (this->key(), this->proxyHolder());
351 }
352 
353 
354 /**
355  * @brief Return a link to the currently-referenced container object.
356  */
357 template <class STORABLE>
358 inline
359 const DataLink<STORABLE> ElementLink<STORABLE>::getDataLink() const
360 {
361  return DataLink<STORABLE> (this->key(), this->proxyHolder());
362 }
363 
364 
365 /**
366  * @brief Return a pointer to the currently-referenced container object.
367  */
368 template <class STORABLE>
369 inline
370 typename ElementLink<STORABLE>::BaseConstPointer
371 ElementLink<STORABLE>::getStorableObjectPointer() const
372 {
373  return getDataPtr();
374 }
375 
376 
377 /**
378  * @brief Return a reference to the currently-referenced container object.
379  */
380 template <class STORABLE>
381 inline
382 typename ElementLink<STORABLE>::BaseConstReference
383 ElementLink<STORABLE>::getStorableObjectRef() const
384 {
385  return *getDataPtr();
386 }
387 
388 
389 /**
390  * @brief Return a pointer to the referenced element.
391  *
392  * Be aware: if the element is a pointer, then this will yield
393  * a pointer to a pointer.
394  */
395 template <class STORABLE>
396 inline
397 typename ElementLink<STORABLE>::ElementConstPointer
398 ElementLink<STORABLE>::cptr() const
399 {
400  ElementConstPointer ret = 0;
401  if (this->getCachedElement (ret))
402  return ret;
403 
404  const STORABLE* ptr = this->getDataPtr();
405  if (ptr && IndexingPolicy::isValid(this->storedIndex())) {
406  this->setCachedElement (IndexingPolicy::lookup(this->storedIndex(), *ptr));
407  this->getCachedElement (ret);
408  }
409  return ret;
410 }
411 
412 
413 /**
414  * @brief Return a reference to the referenced element.
415  *
416  * Will throw an exception if the link is not valid.
417  */
418 template <class STORABLE>
419 inline
420 typename ElementLink<STORABLE>::ElementConstReference
421 ElementLink<STORABLE>::operator* () const
422 {
423  ElementConstPointer ptr = cptr();
424  if (!ptr)
425  SG::throwExcInvalidLink (classID(), this->dataID(), this->key());
426  return *ptr;
427 }
428 
429 
430 /**
431  * @brief Return a pointer to the referenced element.
432  */
433 template <class STORABLE>
434 inline
435 typename ElementLink<STORABLE>::ElementConstPointer
436 ElementLink<STORABLE>::operator->() const
437 {
438  return cptr();
439 }
440 
441 
442 /**
443  * @brief Convert to a pointer to the referenced element.
444  */
445 template <class STORABLE>
446 inline
447 ElementLink<STORABLE>::operator ElementConstPointer () const
448 {
449  return cptr();
450 }
451 
452 
453 /**
454  * @brief Test to see if the link can be dereferenced.
455  *
456  * Will throw an exception if the container is not empty and the
457  * referenced element cannot be retrieved.
458  */
459 template <class STORABLE>
460 inline
461 bool ElementLink<STORABLE>::isValid() const
462 {
463  // This used to just call cptr(), but that was leading to dangling-pointer
464  // warnings with gcc12 when we were returning ElementLink's by value,
465  // as in ElementLinkVector. Doing it like this allows us to save
466  // a little work, anyway.
467  if (this->hasCachedElement()) return true;
468 
469  const STORABLE* ptr = this->getDataPtr();
470  if (ptr && !ptr->empty() && IndexingPolicy::isValid(this->storedIndex())) {
471  this->setCachedElement (IndexingPolicy::lookup(this->storedIndex(), *ptr));
472  return true;
473  }
474  return false;
475 }
476 
477 
478 /**
479  * @brief Test to see if the link can not be dereferenced.
480  */
481 template <class STORABLE>
482 inline
483 bool ElementLink<STORABLE>::operator!() const
484 {
485  return !isValid();
486 }
487 
488 
489 /**
490  * @brief Return the cached element, if any.
491  */
492 template <class STORABLE>
493 inline
494 typename ElementLink<STORABLE>::ElementType
495 ElementLink<STORABLE>::cachedElement() const
496 {
497  ElementConstPointer ret = 0;
498  if (this->getCachedElement (ret))
499  return *ret;
500  return ElementType();
501 }
502 
503 
504 /**
505  * @brief Set the link to an element given by index and pointer to container.
506  * @param data Reference to the container (storable).
507  * @param elemID The index of the element within the container.
508  * @param sg Associated store.
509  * @returns True if the link was changed.
510  *
511  * If the link is already set, this will return false and leave the
512  * link unchanged.
513  *
514  * If @c sg is 0, then we take the store from whatever the link's currently
515  * set to. If the link has no current store, then we take the global
516  * default.
517  */
518 template <class STORABLE>
519 inline
520 bool
521 ElementLink<STORABLE>::toIndexedElement(BaseConstReference data,
522  index_type elemID,
523  IProxyDict* sg /*= 0*/)
524 {
525  return Base::toIndexedElement (&data, classID(), elemID, sg);
526 }
527 
528 
529 /**
530  * @brief Set the link to an element given by index and pointer to container.
531  * @param data Reference to the container (storable).
532  * @param elemID The index of the element within the container.
533  * @param ctx The event context.
534  * @returns True if the link was changed.
535  *
536  * If the link is already set, this will return false and leave the
537  * link unchanged.
538  */
539 template <class STORABLE>
540 inline
541 bool
542 ElementLink<STORABLE>::toIndexedElement(BaseConstReference data,
543  index_type elemID,
544  const EventContext& ctx)
545 {
546  return Base::toIndexedElement (&data, classID(), elemID, Atlas::proxyDictFromEventContext(ctx));
547 }
548 
549 
550 /**
551  * @brief Set from element pointer and a reference to the container (storable)
552  * @param data Reference to the container (storable).
553  * @param element The element.
554  * @param sg Associated store.
555  * @returns True if the link was changed.
556  *
557  * O(N) for sequences!
558  *
559  * If the link is already set, this will return false and leave the
560  * link unchanged.
561  *
562  * If @c sg is 0, then we take the store from whatever the link's currently
563  * set to. If the link has no current store, then we take the global
564  * default.
565  */
566 template <class STORABLE>
567 inline
568 bool ElementLink<STORABLE>::toContainedElement(BaseConstReference data,
569  ElementType element,
570  IProxyDict* sg /*= 0*/)
571 {
572  index_type index = this->index();
573  IndexingPolicy::reverseLookup (data, element, index);
574  bool ret = Base::toIndexedElement (&data, classID(), index, sg);
575  if (ret)
576  this->storeCachedElement (element);
577  return ret;
578 }
579 
580 
581 /**
582  * @brief Set from element pointer and a reference to the container (storable)
583  * @param data Reference to the container (storable).
584  * @param element The element.
585  * @param ctx The event context.
586  * @returns True if the link was changed.
587  *
588  * O(N) for sequences!
589  *
590  * If the link is already set, this will return false and leave the
591  * link unchanged.
592  */
593 template <class STORABLE>
594 inline
595 bool ElementLink<STORABLE>::toContainedElement(BaseConstReference data,
596  ElementType element,
597  const EventContext& ctx)
598 {
599  index_type index = this->index();
600  IndexingPolicy::reverseLookup (data, element, index);
601  bool ret = Base::toIndexedElement (&data, classID(), index, Atlas::proxyDictFromEventContext(ctx));
602  if (ret)
603  this->storeCachedElement (element);
604  return ret;
605 }
606 
607 
608 /**
609  * @brief Set to point to an element.
610  * @param element The element.
611  * @returns True if the link was changed.
612  *
613  * The collection and the element can be specified independently
614  * using @c setElement and @c setStorableObject.
615  *
616  * If the link is already set, this will return false and leave the
617  * link unchanged.
618  */
619 template <class STORABLE>
620 inline
621 bool ElementLink<STORABLE>::setElement(ElementType element)
622 {
623  if (!this->isDefaultIndex() || this->hasCachedElement())
624  return false;
625  this->storeCachedElement (element);
626  const STORABLE* ptr = this->getDataPtr();
627  if (ptr) {
628  index_type index = this->index();
629  IndexingPolicy::reverseLookup (*ptr, element, index);
630  this->setIndex (index);
631  }
632  return true;
633 }
634 
635 
636 /**
637  * @brief Set link to point to a new container (storable).
638  * @param data Reference to the container (storable).
639  * @param replace True if we can change an existing link.
640  * @param sg Associated store.
641  * @returns True if the link was changed.
642  *
643  * If the link is already set, this will return false and leave the
644  * link unchanged unless @c replace is set. The @c replace argument
645  * should be set if the element is now in a new storable container;
646  * e.g. element ptr has been put in a new view container.
647  *
648  * If @c sg is 0, then we take the store from whatever the link's currently
649  * set to. If the link has no current store, then we take the global
650  * default.
651  */
652 template <class STORABLE>
653 inline
654 bool ElementLink<STORABLE>::setStorableObject(BaseConstReference data,
655  bool replace /*= false*/,
656  IProxyDict* sg /*= 0*/)
657 {
658  bool ret = Base::setStorableObject (&data, classID(), replace, sg);
659  if (ret) {
660  ElementConstPointer elt = 0;
661  if (this->isDefaultIndex() && this->getCachedElement (elt)) {
662  index_type index = this->index();
663  IndexingPolicy::reverseLookup (data, *elt, index);
664  this->setIndex (index);
665  return true;
666  }
667  }
668  return ret;
669 }
670 
671 
672 /**
673  * @brief Set link to point to a new container (storable).
674  * @param data Reference to the container (storable).
675  * @param replace True if we can change an existing link.
676  * @param ctx The event context.
677  * @returns True if the link was changed.
678  *
679  * If the link is already set, this will return false and leave the
680  * link unchanged unless @c replace is set. The @c replace argument
681  * should be set if the element is now in a new storable container;
682  * e.g. element ptr has been put in a new view container.
683  */
684 template <class STORABLE>
685 inline
686 bool ElementLink<STORABLE>::setStorableObject(BaseConstReference data,
687  bool replace,
688  const EventContext& ctx)
689 {
690  bool ret = Base::setStorableObject (&data, classID(), replace, Atlas::proxyDictFromEventContext(ctx));
691  if (ret) {
692  ElementConstPointer elt = 0;
693  if (this->isDefaultIndex() && this->getCachedElement (elt)) {
694  index_type index = this->index();
695  IndexingPolicy::reverseLookup (data, *elt, index);
696  this->setIndex (index);
697  return true;
698  }
699  }
700  return ret;
701 }
702 
703 
704 /**
705  * @brief Set the link to an element given by string key and index.
706  * @param dataID Key of the object.
707  * @param elemID The index of the element within the container.
708  * @param sg Associated store.
709  *
710  * If @c sg is 0, then we take the store from whatever the link's currently
711  * set to. If the link has no current store, then we take the global
712  * default.
713  */
714 template <class STORABLE>
715 inline
716 void ElementLink<STORABLE>::resetWithKeyAndIndex(const ID_type& dataID,
717  index_type elemID,
718  IProxyDict* sg /*= 0*/)
719 {
720  Base::resetWithKeyAndIndex (dataID, classID(), elemID, sg);
721 }
722 
723 
724 /**
725  * @brief Set the link to an element given by string key and index.
726  * @param dataID Key of the object.
727  * @param elemID The index of the element within the container.
728  * @param ctx The event context.
729  */
730 template <class STORABLE>
731 inline
732 void ElementLink<STORABLE>::resetWithKeyAndIndex(const ID_type& dataID,
733  index_type elemID,
734  const EventContext& ctx)
735 {
736  Base::resetWithKeyAndIndex (dataID, classID(), elemID, Atlas::proxyDictFromEventContext(ctx));
737 }
738 
739 
740 /**
741  * @brief Set the link to an element given by string key and index.
742  * @param key Hashed key of the object.
743  * @param elemID The index of the element within the container.
744  * @param sg Associated store.
745  *
746  * If @c sg is 0, then we take the store from whatever the link's currently
747  * set to. If the link has no current store, then we take the global
748  * default.
749  */
750 template <class STORABLE>
751 inline
752 void ElementLink<STORABLE>::resetWithKeyAndIndex(sgkey_t key,
753  index_type elemID,
754  IProxyDict* sg /*= 0*/)
755 {
756  Base::resetWithKeyAndIndex (key, classID(), elemID, sg);
757 }
758 
759 
760 /**
761  * @brief Set the link to an element given by string key and index.
762  * @param key Hashed key of the object.
763  * @param elemID The index of the element within the container.
764  * @param ctx The event context.
765  */
766 template <class STORABLE>
767 inline
768 void ElementLink<STORABLE>::resetWithKeyAndIndex(sgkey_t key,
769  index_type elemID,
770  const EventContext& ctx)
771 {
772  Base::resetWithKeyAndIndex (key, classID(), elemID, Atlas::proxyDictFromEventContext(ctx));
773 }
774 
775 
776 /**
777  * @brief Return a (void) pointer to the currently-referenced
778  * container object.
779  * @return A pointer to an object of the type given by @a clid,
780  * or null on a failure (or if the reference is null).
781  */
782 template <class STORABLE>
783 inline
784 const void* ElementLink<STORABLE>::storable() const
785 {
786  typedef STORABLE* fn_t (SG::DataProxy*);
787  fn_t* fn = &SG::DataProxy_cast<STORABLE>;
788  return this->storableBase (reinterpret_cast<castfn_t*> (fn), classID(), true);
789 }
790 
791 
792 /**
793  * @brief Return a (void) pointer to the currently-referenced
794  * container object.
795  * @return A pointer to an object of the type given by @a clid,
796  * or null on a failure (or if the reference is null).
797  */
798 template <class STORABLE>
799 inline
800 void* ElementLink<STORABLE>::storableNonConst()
801 {
802  typedef STORABLE* fn_t (SG::DataProxy*);
803  fn_t* fn = &SG::DataProxy_cast<STORABLE>;
804  return this->storableBase (reinterpret_cast<castfn_t*> (fn), classID(), false);
805 }
806 
807 
808 /**
809  * @brief Ordering relation for @c ElementLink (less-than)
810  * @param lhs Left-hand-side EL.
811  * @param rhs Right-hand-side EL.
812  */
813 template <typename STORABLE>
814 bool operator < (const ElementLink<STORABLE>& lhs,
815  const ElementLink<STORABLE>& rhs)
816 {
817  bool lhsDefault = lhs.isDefault();
818  bool rhsDefault = rhs.isDefault();
819  if (lhsDefault && rhsDefault) return false;
820  if (lhsDefault) return true;
821  if (rhsDefault) return false;
822  if (lhs.key() == 0 || rhs.key() == 0 || lhs.isDefaultIndex() || rhs.isDefaultIndex())
823  SG::throwExcIncomparableEL();
824  if (SG::sgkeyLess (lhs.key(), rhs.key())) return true;
825  if (SG::sgkeyLess (rhs.key(), lhs.key())) return false;
826  if (lhs.index() < rhs.index()) return true;
827  return false;
828 }
829 
830 
831 /**
832  * @brief Ordering relation for @c ElementLink (greater-than)
833  * @param lhs Left-hand-side EL.
834  * @param rhs Right-hand-side EL.
835  */
836 template <typename STORABLE>
837 inline
838 bool operator > (const ElementLink<STORABLE>& lhs,
839  const ElementLink<STORABLE>& rhs)
840 {
841  return (rhs < lhs);
842 }
843 
844 
845 /**
846  * @brief Equality relation for @c ElementLink.
847  * @param lhs Left-hand-side EL.
848  * @param rhs Right-hand-side EL.
849  */
850 template <typename STORABLE>
851 inline
852 bool operator == (const ElementLink<STORABLE>& lhs,
853  const ElementLink<STORABLE>& rhs)
854 {
855  return !((lhs < rhs) || (rhs < lhs));
856 }
857 
858 
859 /**
860  * @brief Inequality relation for @c ElementLink.
861  * @param lhs Left-hand-side EL.
862  * @param rhs Right-hand-side EL.
863  */
864 template <typename STORABLE>
865 inline
866 bool operator != (const ElementLink<STORABLE>& lhs,
867  const ElementLink<STORABLE>& rhs)
868 {
869  return !(lhs == rhs);
870 }
871 
872 
873 namespace SG_detail {
874 
875 
876 /**
877  * @brief See if an EL is being remapped.
878  * @param sgkey_in Original hashed key of the EL.
879  * @param index_in Original index of the EL.
880  * @param sgkey_out[out] New hashed key for the EL.
881  * @param index_out[out] New index for the EL.
882  * @return True if there is a remapping; false otherwise.
883  *
884  * This version is for the case where the EL index is a @c size_t.
885  * For other index types, the the templated version below is used
886  * (which doesn't allow remapping indices).
887  */
888 inline
889 bool checkForRemap (IProxyDict* sg,
890  SG::sgkey_t sgkey_in,
891  size_t index_in,
892  SG::sgkey_t& sgkey_out,
893  size_t& index_out)
894 {
895  return sg->tryELRemap (sgkey_in, index_in, sgkey_out, index_out);
896 }
897 
898 
899 /**
900  * @brief See if an EL is being remapped.
901  * @param sgkey_in Original hashed key of the EL.
902  * @param dum_in Ignored.
903  * @param sgkey_out[out] New hashed key for the EL.
904  * @param dum_out[out] Ignored.
905  * @return True if there is a remapping; false otherwise.
906  *
907  * This version catches the cases where the container index type
908  * isn't a @c size_t. We don't support changing the index in this case.
909  */
910 template <class T>
911 inline
912 bool checkForRemap (IProxyDict* sg,
913  SG::sgkey_t sgkey_in,
914  const T& /*dum_in*/,
915  SG::sgkey_t& sgkey_out,
916  T& /*dum_out*/)
917 {
918  size_t index_in = 0;
919  size_t index_out;
920  return sg->tryELRemap (sgkey_in, index_in, sgkey_out, index_out);
921 }
922 
923 
924 } // namespace SG_detail