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